H8サンプルプログラム-その3
CPUボード:RY3048Fone を使って、
制御対象回路として「ものづくり kumamoto Ver.01」を制御するサンプルプログラムを作ります。
7セグメントLED(LED1、LED2)の点灯、スイッチ入力を制御します。小さなテーマの集まりですが、対象としているハードウェアの接続(ケーブル、回路内のすべて)を確認しながら進めてください。その一つひとつがプログラムの力になります。
■テーマ概要
7セグメントLEDを使い、1秒間隔でカウントアップ、カウントダウンするカウンタを作ります。
表示の初期値は、SW1(トグルスイッチ)がオンの時、「00」とし、オフの時、「99」とします。
カウント間隔(表示):1秒(システムクロックから発生させます)
SW1:カウント方向の指示 →オンの時、カウントアップします。オフの時、カウントダウンします。
SW2(プッシュスイッチ):カウント動作停止 →プッシュ(オン)時、カウント停止します。
SW3(透過センサー):カウント動作開始 →遮光(オフ)時、カウント開始する。
■接続
制御対象回路 CPUボード:RY3048Fone
CN1 → J2
CN2 → J3
J1 → トグルスイッチ、プッシュスイッチ、透過センサー
■開発環境
ルネサスエレクトロニクス社 High-performance Embedded Workshop を使います。
最新版をルネサスエレクトロニクス社のホームページよりダウンロードしてセットアップしてください。
注:このプロジェクトでは、「H8S,H8/300 Standard Toolchain...」(「ビルド」メニューから起動)の設定を変更している。「標準ライブラリ」の「モード」をデフォルト設定の「ライブラリファイル指定なし」から、「ライブラリファイル作成(常に)」に設定した。そうしないと下記リンクエラーが発生する。
L2310 (E) Undefined external symbol "$sp_regsv$3" referenced in "C:\sakaki\・・\demo02.obj"
L2310 (E) Undefined external symbol "$spregld2$3" referenced in "C:\sakaki\・・\demo03.obj"
Optimizing Linkage Editor Abort
→この対応で一度、ライブラリファイルが作成されると、その後、以前の「ライブラリファイル指定なし」に戻してもリンクエラーは発生しなくなった。理由は、不明。しかし、今後の事が心配である為、「ライブラリファイル指定なし」には戻さない。
■準備-その1
ヘッダファイルを用意します。
ファイル名:ry3048fone.h
フォルダー:自分の開発環境に合わせる。
ヘッダファイルの内容は、次の通り。
---この次から---
void InitializeIO(void);
int GetSW1(void);
int GetSW2(void);
int GetSW3(void);
void Wait1msec(void);
void WaitMsec(int msec);
#define COUNT_START 1
#define COUNT_STOP 0
#define LED_AL_OFF 0xff
#define LED_AL_ON 0x00
#define OE_ENABLE 0
#define OE_DISABLE 1
#define FET_ENABLE 1
#define FET_DISABLE 0
#define LED7SEG_ALL PA.DR.BYTE
#define OE_7SEG PB.DR.BIT.B7
#define OE_LED PB.DR.BIT.B6
#define A 0x01
#define B 0x02
#define C 0x04
#define D 0x08
#define E 0x10
#define F 0x20
#define G 0x40
#define SW1 P7.DR.BIT.B1
#define SW2 P7.DR.BIT.B3
#define SW3 P7.DR.BIT.B5
#define SW_ON 0
#define SW_OFF 1
#define True 1
#define False 0
const char LEDSegData[10] = {
~(A+B+C+D+E+F),
~(B+C),
~(A+B+G+E+D),
~(A+B+G+C+D),
~(F+G+B+C),
~(A+F+G+C+D),
~(A+F+G+C+D+E),
~(A+B+C),
~(A+B+C+D+E+F+G),
~(A+B+C+D+F+G) };
void InitializeIO(void)
{
/* 入出力端子の定義 */
PA.DR.BYTE = 0;
PA.DDR = 0xff;
PA.DR.BYTE = LED_AL_OFF;
PB.DR.BYTE = 0;
PB.DDR = 0xff;
/* タイマーの定義 */
ITU1.TCR.BYTE = 0x23;
ITU1.GRA = 0x0c00;
ITU.TSTR.BIT.STR1 = COUNT_START;
}
void Wait1msec(void)
{
for(;;){
if( ITU1.TSR.BIT.IMFA != 0 ) break;
}
ITU1.TSR.BIT.IMFA = 0;
}
void WaitMsec(int msec)
{
int iCnt;
if( msec < 0 ) return;
for( iCnt = 0 ; iCnt < msec ; iCnt++ ) Wait1msec();
}
int GetSW1(void)
{
return( SW1 );
}
int GetSW2(void)
{
return( SW2 );
}
int GetSW3(void)
{
return( SW3 );
}
---この前まで---
■準備-その2
サンプル用のスタータプログラム(アセンブラ)を用意します。
ファイル名:demo03start.src
フォルダー:プロジェクト指定のフォルダー
---この次から---
.CPU 300HA:20
STACK_BASE: .EQU H'FFFF10 ; スタック基底アドレス(モード7)
.IMPORT _main ; 外部参照(main関数)
.SECTION V ; H'000000
.DATA.L RESET_START
.SECTION P ; H'000100
RESET_START:
MOV.L #STACK_BASE,ER7 ; スタックの設定
JSR @_main ; C言語のmain()関数へジャンプ
OWARI:
BRA OWARI
.END
---この前まで---
注:このファイル(拡張子が「src」)は、これまで作成してきた中に入っています。それをそのまま、ファイル名を変えて利用されても構いません。先に作成したファイル「demo01start.src」のファイル名称を「demo03start.src」変更して流用してもよいです。
■準備-その3
サンプル用のソースプログラムファイル(C言語)を用意します。
ファイル名:demo03.c
フォルダー:プロジェクト指定のフォルダー
---この次から---
#include "3048f.h"
#include "ry3048fone.h"
void main(void);
void main(void)
{
/* ローカル変数の定義 */
int Digit1st;
int Digit2nd;
int CountOfSeconds;
int i;
int CountEnable;
/* 処理 */
InitializeIO();
OE_7SEG = OE_ENABLE;
OE_LED = OE_DISABLE;
if( GetSW1() == SW_ON ) CountOfSeconds = 0;
else CountOfSeconds = 99;
CountEnable = False;
for(;;){
Digit2nd = CountOfSeconds / 10;
Digit1st = CountOfSeconds - ( Digit2nd * 10 );
for( i = 0 ; i < 500 ; i++ ){
if( GetSW2() == SW_ON ) CountEnable = False;
if( GetSW3() == SW_OFF ) CountEnable = True;
LED7SEG_ALL = LEDSegData[Digit2nd];
LED7SEG_1 = FET_ENABLE;
LED7SEG_2 = FET_DISABLE;
Wait1msec();
LED7SEG_ALL = LEDSegData[Digit1st];
LED7SEG_1 = FET_DISABLE;
LED7SEG_2 = FET_ENABLE;
Wait1msec();
}
if( GetSW1() == SW_ON
&& CountEnable == True ){
if( CountOfSeconds >= 99 ) CountOfSeconds = 0;
else CountOfSeconds++;
} else if( GetSW1() == SW_OFF
&& CountEnable == True ){
if( CountOfSeconds <= 0 ) CountOfSeconds = 99;
else CountOfSeconds--;
}
}
}
---この前まで---
注:時間「≒1000msec」について
この計算は、関数「Wait1msec()」を2つ、それを500回ループで回すので、(1msec+1msec)x500=1000msec となる。しかし、厳密には、同じループ内に合計6ステップのステートメントがあるので、その分の処理時間が加わる事になる。そういった意味合いで、「≒1000msec」となる。