ものづくりBLOG blog page

H8サンプルプログラム-その2

2010-05-26 (Wed) 03:11

H8サンプルプログラム-その2

CPUボード:RY3048Fone を使って、
制御対象回路として「ものづくり kumamoto Ver.01」を制御するサンプルプログラムを作ります。
7セグメントLED(LED1、LED2)の点灯、スイッチ入力を制御します。小さなテーマの集まりですが、対象としているハードウェアの接続(ケーブル、回路内のすべて)を確認しながら進めてください。その一つひとつがプログラムの力になります。


■テーマ概要
 ・制御のヒント
   PA.DR.BYTE → 0xff or ~0x00 = a~gの点灯
   PA.DR.BIT.B0 → a = 0:点灯、1:消灯
   PA.DR.BIT.B1 → b = 0:点灯、1:消灯
   PA.DR.BIT.B2 → c = 0:点灯、1:消灯
   PA.DR.BIT.B3 → d = 0:点灯、1:消灯
   PA.DR.BIT.B4 → e = 0:点灯、1:消灯
   PA.DR.BIT.B5 → f = 0:点灯、1:消灯
   PA.DR.BIT.B6 → g = 0:点灯、1:消灯
   PA.DR.BIT.B7 → n/a(接続なし)
   SW1(トグルスイッチ)の状態により、点灯するLEDを切り替える。
   SW1がオンの時は、LED1が点灯+LED2が消灯し、
   SW1がオフの時は、LED1が消灯+LED2が点灯する。
 ・テーマは、次の通りです。
   1)LED1とLED2の全セグメントを点灯する。
   2)LED1とLED2の全セグメントを消灯する。
   3)LED1とLED2のセグメント「a」だけを点灯する。
   4)LED1とLED2のセグメント「b」だけを点灯する。
   5)LED1とLED2のセグメント「c」だけを点灯する。
   6)LED1とLED2のセグメント「d」だけを点灯する。
   7)LED1とLED2のセグメント「e」だけを点灯する。
   8)LED1とLED2のセグメント「f」だけを点灯する。
   9)LED1とLED2のセグメント「g」だけを点灯する。
   10)SW2(プッシュスイッチ)でセグメントの点灯をシフトする。
   11)SW3(透過センサー)でセグメントの点灯をシフトする。
   12)SW2(プッシュスイッチ)でカウント表示(1桁)する。
   13)SW3(透過センサー)でカウント表示(1桁)する。
 注:この時、LED3~LED10は全消灯とする。        


■接続
制御対象回路 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);


#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;
}


int GetSW1(void)
{
    return( SW1 );
}


int GetSW2(void)
{
    return( SW2 );
}


int GetSW3(void)
{
    return( SW3 );
}


---この前まで---


■準備-その2
サンプル用のスタータプログラム(アセンブラ)を用意します。
ファイル名:demo02start.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」のファイル名称を「demo02start.src」変更して流用してもよいです。


■準備-その3
サンプル用のソースプログラムファイル(C言語)を用意します。
ファイル名:demo02.c
フォルダー:プロジェクト指定のフォルダー

注:この時、7セグメントLEDは全消灯とする。

---この次から---

#include "3048f.h"
#include "ry3048fone.h"

void main(void);

void main(void)
{
    /* ローカル変数の定義 */
    unsigned char LedShifted;
    int DuringON;
    int IsFirst;

    /* 処理 */
    InitializeIO();
    OE_7SEG = OE_ENABLE;
    OE_LED = OE_DISABLE;
    LED7SEG_1 = FET_DISABLE;
    LED7SEG_2 = FET_DISABLE;
    IsFirst = True;

    for(;;){
        if( GetSW1() == SW_ON ){
            LED7SEG_1 = FET_ENABLE;
            LED7SEG_2 = FET_DISABLE;
        } else {
            LED7SEG_1 = FET_DISABLE;
            LED7SEG_2 = FET_ENABLE;
        }

        /*ここにサンプルプログラムを書く*/

    }
}


---この前まで---

それでは、次に「/*ここにサンプルプログラムを書く*/」のところに、実際にプログラムを書いてみましょう。


■サンプルプログラムの作成
1)LED1とLED2の全セグメントを点灯する。

LED7SEG_ALL = LED_AL_ON;

全セグメント点灯(し続け)ます。


2)LED1とLED2の全セグメントを消灯する。

LED7SEG_ALL = LED_AL_OFF;

全セグメント消灯(し続け)ます。


3)LED1とLED2のセグメント「a」だけを点灯する。

LED7SEG_ALL = ~0x01;

PA.DR.BIT.B0だけを「0」にして、a を点灯(し続け)ます。
a だけを消灯させたい時は、チルダ「~」を外します。


4)LED1とLED2のセグメント「b」だけを点灯する。

LED7SEG_ALL = ~0x02;

PA.DR.BIT.B1だけを「0」にして、b を点灯(し続け)ます。
b だけを消灯させたい時は、チルダ「~」を外します。


5)LED1とLED2のセグメント「c」だけを点灯する。

LED7SEG_ALL = ~0x04;

PA.DR.BIT.B2だけを「0」にして、c を点灯(し続け)ます。
c だけを消灯させたい時は、チルダ「~」を外します。


6)LED1とLED2のセグメント「d」だけを点灯する。

LED7SEG_ALL = ~0x08;

PA.DR.BIT.B3だけを「0」にして、d を点灯(し続け)ます。
d だけを消灯させたい時は、チルダ「~」を外します。


7)LED1とLED2のセグメント「e」だけを点灯する。

LED7SEG_ALL = ~0x10;

PA.DR.BIT.B4だけを「0」にして、e を点灯(し続け)ます。
e だけを消灯させたい時は、チルダ「~」を外します。


8)LED1とLED2のセグメント「f」だけを点灯する。

LED7SEG_ALL = ~0x20;

PA.DR.BIT.B5だけを「0」にして、f を点灯(し続け)ます。
f だけを消灯させたい時は、チルダ「~」を外します。


9)LED1とLED2のセグメント「g」だけを点灯する。

LED7SEG_ALL = ~0x40;

PA.DR.BIT.B6だけを「0」にして、g を点灯(し続け)ます。
g だけを消灯させたい時は、チルダ「~」を外します。


10)SW2(プッシュスイッチ)でセグメントの点灯をシフトする。
 初期状態の時、a のみが点灯し、SW2を一回押下すると次に b が点灯する。
 SW2を押下する毎に以後、一つずつセグメントの点灯がシフト(a→b→c→d→e→f→g)する。
 g 迄到達したら、次の押下で a に戻り、以後これを繰り返す。
 注:この処理では、スイッチのチャタリングが影響し、セグメントのシフト点灯が旨くいかない時がある。
   オン状態を確実にするため、フラグ「DuringON」を使ったが、もう少し工夫が必要と思われる。

if( IsFirst == True ){
    LedShifted = 0x01;
    DuringON = False;
    IsFirst = False;
}
if( GetSW2() == SW_ON && DuringON == False ){
    DuringON = True;
    if( LedShifted == 0x40 ) LedShifted = 0x01;
    else LedShifted = LedShifted << 1;
}
if( GetSW2() != SW_ON ) DuringON = False;
LED7SEG_ALL = ~LedShifted;

注:シフト中のLEDだけを消灯する時は、チルダ「~」を外す。


11)SW3(透過センサー)でセグメントの点灯をシフトする。
 初期状態の時、a のみが点灯し、SW2を一回押下すると次に b が点灯する。
 SW3を遮光する毎に以後、一つずつセグメントの点灯がシフト(a→b→c→d→e→f→g)する。
 g 迄到達したら、次の遮光で a に戻り、以後これを繰り返す。
注:透過センサーでは、プッシュスイッチの様なチャタリングがないので、セグメントのシフト点灯は、この処理で問題なく動作する。只、スイッチの操作で初期状態として、遮光(オフ状態)から入るか、透過(オン状態)から入るかを決めないといけない。SW2の時の初期状態と同様に、LedShifted を 0x01 として、透過(オン状態)から入ると、電源投入時、シフト処理が一回入る為、b から点灯開始となる。これを回避するには、LedShifted を 0x40 から始めるとよい。初期状態が透過(オン状態)なので、その最初のシフト処理を通り、LedShifted が 0x40→0x01 となって、最初の点灯が a となる。

if( IsFirst == True ){
    LedShifted = 0x40;
    DuringON = False;
    IsFirst = False;
}
if( GetSW3() == SW_ON && DuringON == False ){
    DuringON = True;
    if( LedShifted == 0x40 ) LedShifted = 0x01;
    else LedShifted = LedShifted << 1;
}
if( GetSW3() != SW_ON ) DuringON = False;
LED7SEG_ALL = ~LedShifted;

注:シフト中のLEDだけを消灯する時は、チルダ「~」を外す。


12)SW2(プッシュスイッチ)でカウント表示(1桁)する。
 初期状態の時、0を表示し、SW2を一回押下すると 0→1 とカウントする。
 SW2を押下する毎に以後、一つずつカウントアップ(0→1→2→3→4→5→6→7→8→9)する。
 9迄到達したら、次の押下で0に戻り、以後これを繰り返す。
注:この処理では、スイッチのチャタリングが影響し、カウント結果の値表示が旨くいかない時がある。オン状態を確実にするため、フラグ「DuringON」を使ったが、もう少し工夫が必要と思われる。

if( IsFirst == True ){
    LedShifted = 0;
    DuringON = False;
    IsFirst = False;
}
if( GetSW2() == SW_ON && DuringON == False ){
    DuringON = True;
    if( LedShifted == 9 ) LedShifted = 0;
    else LedShifted++;
}
if( GetSW2() != SW_ON ) DuringON = False;
LED7SEG_ALL = LEDSegData[LedShifted];


13)SW3(透過センサー)でカウント表示(1桁)する。
 初期状態の時、0を表示し、SW3を一回遮光すると 0→1 とカウントする。
 SW3を遮光する毎に以後、一つずつカウントアップ(0→1→2→3→4→5→6→7→8→9)する。
 9迄到達したら、次の遮光で0に戻り、以後これを繰り返す。
注:透過センサーでは、プッシュスイッチの様なチャタリングがないので、セグメントのシフト点灯は、この処理で問題なく動作する。只、スイッチの操作で初期状態として、遮光(オフ状態)から入るか、透過(オン状態)から入るかを決めないといけない。SW2の時の初期状態と同様に、LedShifted を 0 として、透過(オン状態)から入ると、電源投入時、シフト処理が一回入る為、1 から点灯開始となる。これを回避するには、LedShifted を 9 から始めるとよい。初期状態が透過(オン状態)なので、その最初のシフト処理を通り、LedShifted が 9→0 となって、最初の点灯が 0 となる。

if( IsFirst == True ){
    LedShifted = 9;
    DuringON = False;
    IsFirst = False;
}
if( GetSW3() == SW_ON && DuringON == False ){
    DuringON = True;
    if( LedShifted == 9 ) LedShifted = 0;
    else LedShifted++;
}
if( GetSW3() != SW_ON ) DuringON = False;
LED7SEG_ALL = LEDSegData[LedShifted];

 

ものづくりBLOG

Blog Category

Blog Calendar

RSS 2.0