連載
» 2009年12月16日 00時00分 UPDATE

イチから作って丸ごと学ぶ! H8マイコン道(9):チャタリングを防止して、スイッチ入力を完成させよう (1/3)

今回は、マイコン制御プログラムの基礎中の基礎、スイッチ入力にかかわるC言語プログラミングについて詳しく解説する!

[横田一弘 埼玉県立新座総合技術高等学校 教諭,@IT MONOist]

前回のあらすじ

――マイコンボード「H8Tiny-USB」の入出力インターフェイスを理解し、C言語によるポート制御までをマスターした健一君。立派に制御プログラミングの世界へ足を踏み入れたようです。しかし、ホッとする間もなく、晴子さんから次なる宿題が……。前回へ

 健一君、今回はちゃんと宿題をやってきたのでしょうか。また、晴子さんに怒られないといいのですが……。

 おっと、健一君が来たみたいです。


本連載の登場人物

ay_S_icon_ani.gif
佐藤 健一(さとう けんいち)
電子工学を専攻している大学2年生。ロボットサークルに参加している。最近、やっと電子工作ができるようになったが……。

ay_H_icon_ani.gif
岡野 晴子(おかの はるこ)
健一君が所属するサークルの先輩。組み込みソフトウェアを研究しており、サークルでも中心的な存在。活発で頼れる(健一君あこがれの)女性。



※注:本連載では、筆者が実際にH8Tiny-USBを制作し、動作確認を行った内容を掲載していますが、読者個人で作成したH8Tiny-USBの動作保証や、H8Tiny-USBを使用したことによる、損害・損失については一切保証できません。すべての作業は自己責任で行ってください。よろしくお願いします。


H8Tiny-USBのハードウェアを分析しよう

ここは健一君が所属する大学のサークル部屋。また、いつもの足音が聞こえてきました……。

photo

こんにちは!


photo

あら、健一君。


ほっぺたにヨダレのあとが付いているけど……。


当然、今回はワタシの宿題ちゃんとやってきたわよね。


photo

ギクッーーー。


それが、あの〜、その〜(汗)。


photo

ちょっと!


相変わらずハッキリしないわね!!


photo

実は、プログラムを作ってみたんですが、コンパイルにしくじって……。


どうしたものかと……。


photo

まったく世話が焼けるわね。


それじゃ、今日もスパルタでいくわよ!!


photo

は、はい……。



――「H8マイコン道」もソフトウェア編の3回目に突入しました。晴子さんが出した宿題に健一君も頑張って取り組んだようです。しかし、健一君にとっては、まだまだマイコン制御プログラムの世界は奥が深いようです。まずは、健一君のプログラムをH8Tiny-USBで動かすことからはじめましょう!

 以下は、健一君が作ったプログラムです(ソースコード1)。

/* SW1が押された回数を表示する。
 *
 */
#define PCR1 (*((volatile unsigned char *)0xffe4))
#define PDR1 (*((volatile unsigned char *)0xffd4))
#define PCR5 (*((volatile unsigned char *)0xffe8))
#define PDR5 (*((volatile unsigned char *)0xffd8))
#define PCR8 (*((volatile unsigned char *)0xffeb))
#define PDR8 (*((volatile unsigned char *)0xffdb))
 
#define SW1 0x01
#define SW2 0x02
#define SW3 0x04
 
int main(void)
{
    unsigned char LED[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    int count;
 
    PCR1 = 0x0;
    PDR5 = 0xfe;
    PCR5 = 0x03;
    PDR8 = 0xff;
    PCR8 = 0xff;
 
    count = 0;
    PDR8 = LED[count];
    for (;;) {
        if ((PDR1 & SW1) == 0) {/* SW1が押された */
            if (count < 9)
                count++;
            else
                count = 0;
            PDR8 = LED[count];
        }
    }
    return 0;
}
ソースコード1 健一君が作ったプログラム

 なるほど、C言語のプログラムとしては、うまくできているようですね。晴子さんの宿題(2)では、7セグメントLEDに「0」〜「9」まで表示させることになっていました。

晴子さんからの宿題(2)

SW1を押した回数を、7セグメントLEDに表示するプログラムを作ってね。ただし、カウンタの初期値は「0」よ。それと、「9」の次のカウントで最初の「0」に戻ること!



 健一君のプログラム(ソースコード1)を見てみると、char配列LEDに表示パターンを設定しているようです。

 それでは、ソフトウェア編第1回に倣ってプログラムを実行してみましょう!

 マイコンのC言語プログラムには、「スタートアップ・ルーチン」が必要でした。まず、これを以下のコマンドでアセンブルします。

$ h8300-elf-gcc -c crt0.s 

 どうやら無事にアセンブルできたようです。

 次に、C言語プログラムを以下のコマンドでコンパイルします。

$ h8300-elf-gcc -c -mh -mn swcount.c 

 ここでもエラーは出ません。

 続いて、スタートアップ・ルーチンとC言語プログラムをリンクします。

$ h8300-elf-gcc -o swcount.bin -T 3664.x -nostdlib crt0.o swcount.o
swcount.o: In function `_main':
swcount.c:(.text+0x1b): undefined reference to `_memcpy'
collect2: ld returned 1 exit status 

 あらあら、リンクの過程でエラーが出てしまいましたね。健一君は、ここでつまずいたようです。メッセージを読むと、このプログラムは内部でmemcpy関数を使っているようです。ここでは、それを“リンクできない”というエラーが起こっています。

 コマンドの「-nostdlib」は、標準のスタートアップ・ルーチンや標準関数を“リンクしない”指定です。このオプションを指定してしまったため、標準関数であるmemcpy関数がリンクできなかったのです。

 詳しい説明は後にして(注)、先に進むためにリンクを完了させてしまいましょう。

※注:詳しくは、本稿の3ページ「変数の記憶域はどこだ」で解説します。


 以下のコマンドを入力してください。

$ h8300-elf-gcc -o swcount.bin -T 3664.x -nostdlib -mh
 -mn crt0.o swcount.o -lc 

 いかがでしょうか。無事にリンクできましたね。最後の「-lc」オプションで標準関数を“リンクする”と指定したのです。

 これで実行ファイルが生成されたので、ヘキサファイルに変換します。以下のコマンドを入力してください。

$ h8300-elf-objcopy -O srec swcount.bin swcount.mot 

 図1に最終的に生成されたファイル一覧を示します。

無事に生成されたファイル 図1 無事に生成されたファイル

 後は、「swcount.mot」ファイルをライタでROM焼き(ROMに書き込むこと)して、プログラムを実行してください。

photo

よ〜し!


コンパイルも通ったことだし、実行しちゃいますよーーー!


photo

フフッ。


健一君のプログラム、しっかり動くかしら。


見ものだわー。


photo

それじゃ「SW1」を押して……。


あれっ、「8」が表示される!?(汗)


このプログラム、カウンタになってないじゃないかー。


おかしいなー。

※画像1を参照のこと。


photo

やったー!


絶対そうなると思ったわ。


まんまとワタシの“ワナ”にはまってくれたわ。


photo

え〜っ。


そんな〜。



ソースコード1の実行結果 画像1 ソースコード1の実行結果

       1|2|3 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.