チャタリングを防止して、スイッチ入力を完成させよう:イチから作って丸ごと学ぶ! H8マイコン道(9)(2/3 ページ)
今回は、マイコン制御プログラムの基礎中の基礎、スイッチ入力にかかわるC言語プログラミングについて詳しく解説する!
スイッチの状態の変化を調べるプログラム
――せっかくコンパイルまで完了したのに、プログラムが思うように動きません……。どうやら晴子さんは、ガッカリする健一君の姿を予想していたようですね。さて、今回も晴子さんのペースにすっかり翻弄(ほんろう)されている健一君。彼のプログラムのどこがいけなかったのでしょうか?
晴子さんからの宿題(2)
SW1を押した回数を、7セグメントLEDに表示するプログラムを作ってね。ただし、カウンタの初期値は「0」よ。それと、「9」の次のカウントで最初の「0」に戻ること!
それでは、謎を解明していきましょう。まずは、先ほどの健一君のプログラム(ソースコード1)を逆フローしていきます(図2)。
健一君のプログラムでは、「SW1」が押されている間、7セグメントLEDに「8」が表示されます。図2が、そのフローチャートです。
「SW1」が押されているときの処理の流れを赤線で示しました。このように、「SW1」が押されている間、「0」から「9」までのカウントが繰り返されます。しかし、マイコンの処理速度というのは大変高速なので、7セグメントLEDには「0」から「9」までが高速表示され、結果的に「8」と表示されているように見えていたのです。
どうやら健一君は、「SW1が押されているときにカウント処理する」と考えたようですが、そこに誤りがあったのです!
それでは、スイッチが押された回数を数えるプログラムとは、どんな処理になるのでしょうか?
実はこの処理には、2つのとらえ方があります。
それは、
- ①スイッチが押されていない状態から、押されたときにカウントする
- ②スイッチが押された状態から、離れたときにカウントする
です。
分かりやすいように、タイミングチャートで示してみましょう(図3)。
健一君のプログラムの場合、図3のピンク色で示した時間に、カウントを繰り返し実行するようになっていました。前回の宿題(2)では、図3の赤色で示した①か②のいずれかの時点、つまり、「スイッチのON/OFFが、変化したときにカウントする」プログラムを作ればよいのです。
ここでは、図3①のスイッチ操作をとらえるものとして、フローチャートを作ってみました(図4)。
スイッチが押されていない間、図4①のループでスイッチが押されるのを待ちます。スイッチが押されたならば、カウント処理し、さらに図4②のループでスイッチが押されている間待機します。
これでプログラムはうまく動きますが、CPUの処理能力はほとんど入力待ちループに費やされることが分かります。
それでは、ここまでの解説を基にしたC言語のプログラムを確認してみましょう(ソースコード2)。
/* 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 (;;) {
        while ((PDR1 & SW1) != 0);/* SW1が押されていないとき待機 */
        if (count < 9)
            count++;
        else
            count = 0;
        PDR8 = LED[count];
        while ((PDR1 & SW1) == 0);/* SW1が押されているとき待機 */
    }
    return 0;
}
| ソースコード2 健一君のプログラムを修正 | 
- ソースコード2のダウンロード(swcount_02.lzh)
わー!! プログラムが動いた。
見て、見て、晴子さん!
ちゃんとカウント処理してる〜。
よかったわねー。
さすが、健一君。
うん? 晴子さん、何だか妙に優しいなー。
おっ! するどい!
じゃあ、もう少しだけスイッチを押してみて。
はい……。
えっ、何! いまの?
カウントが飛んだ!
※画像2を参照のこと。
そう、それが第2の“ワナ”よ。
いまのプログラムには、「チャタリング」の配慮がなされていないの。
分かる?
えっ、チャタリングって?
ってことは、まだプログラムは完成していないの?
あーあ。今日は早く帰ってゲームしたかったのに……。
まったく!
Copyright © ITmedia, Inc. All Rights Reserved.












