チャタリングを防止して、スイッチ入力を完成させよう:イチから作って丸ごと学ぶ! H8マイコン道(9)(1/3 ページ)
今回は、マイコン制御プログラムの基礎中の基礎、スイッチ入力にかかわるC言語プログラミングについて詳しく解説する!
前回のあらすじ
――マイコンボード「H8Tiny-USB」の入出力インターフェイスを理解し、C言語によるポート制御までをマスターした健一君。立派に制御プログラミングの世界へ足を踏み入れたようです。しかし、ホッとする間もなく、晴子さんから次なる宿題が……。(前回へ)
健一君、今回はちゃんと宿題をやってきたのでしょうか。また、晴子さんに怒られないといいのですが……。
おっと、健一君が来たみたいです。
H8Tiny-USBのハードウェアを分析しよう
ここは健一君が所属する大学のサークル部屋。また、いつもの足音が聞こえてきました……。
こんにちは!
あら、健一君。
ほっぺたにヨダレのあとが付いているけど……。
当然、今回はワタシの宿題ちゃんとやってきたわよね。
ギクッーーー。
それが、あの〜、その〜(汗)。
ちょっと!
相変わらずハッキリしないわね!!
実は、プログラムを作ってみたんですが、コンパイルにしくじって……。
どうしたものかと……。
まったく世話が焼けるわね。
それじゃ、今日もスパルタでいくわよ!!
は、はい……。
――「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 健一君が作ったプログラム |
- ソースコード1のダウンロード(swcount_01.lzh)
なるほど、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関数がリンクできなかったのです。
詳しい説明は後にして(注)、先に進むためにリンクを完了させてしまいましょう。
以下のコマンドを入力してください。
$ 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に最終的に生成されたファイル一覧を示します。
後は、「swcount.mot」ファイルをライタでROM焼き(ROMに書き込むこと)して、プログラムを実行してください。
よ〜し!
コンパイルも通ったことだし、実行しちゃいますよーーー!
フフッ。
健一君のプログラム、しっかり動くかしら。
見ものだわー。
それじゃ「SW1」を押して……。
あれっ、「8」が表示される!?(汗)
このプログラム、カウンタになってないじゃないかー。
おかしいなー。
※画像1を参照のこと。
やったー!
絶対そうなると思ったわ。
まんまとワタシの“ワナ”にはまってくれたわ。
え〜っ。
そんな〜。
Copyright © ITmedia, Inc. All Rights Reserved.