イチから作って丸ごと学ぶ! H8マイコン道

イチから作って丸ごと学ぶ! H8マイコン道(9)

チャタリングを防止して、
スイッチ入力を完成させよう

横田 一弘 埼玉県立新座総合技術高等学校 教諭 2009/12/16

- PR -

プログラムでチャタリングを
防止するには

――ようやくプログラムが完成したと思ったのに、スイッチを何回か押すと、カウントが飛んでしまうという現象が起きてしまいました。健一君も頭を抱えています。そう、この問題は「チャタリング」と呼ばれるスイッチによって引き起こされる現象が原因です。ここでは、チャタリング対策について紹介していきます。

 チャタリングとは、スイッチ接点の振動により、1回の入力にもかかわらず数回ON/OFFしたかのように、信号が発生してしまう現象をいいます。スイッチの接点は、機械的なものなので、ON/OFF時にこのような現象が生じてしまうのです。

 チャタリングをタイムチャートで見てみると、図5のようなON/OFFの振動になります。前述のとおり、マイコンの処理速度は大変高速です。そのため、この振動を“スイッチが数回押された”ものとして処理してしまうのです。


図5 スイッチ入力によるチャタリングの発生

 さて、このチャタリングをどのように防止したらよいのでしょうか。その解答例を以下に示します(ソースコード3)

/* 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


void wait(int);


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が押されていないとき待機 */
        wait(1000);                 /* チャタリング対策 */
        if (count < 9)
            count++;
        else
            count = 0;
        PDR8 = LED[count];
        while ((PDR1 & SW1) == 0);  /* SW1が押されているとき待機 */
        wait(1000);                 /* チャタリング対策 */
    }
    return 0;
}


void wait(int n)
{
    while (--n);
}
ソースコード3 チャタリング対策をしたプログラム
ソースコード3のダウンロード(swcount_03.lzh

 ここでもう一度、図5をご覧ください。このプログラムでは、図5黄色で示した時間分、「wait」関数で時間を稼ぎ、チャタリングを読み飛ばしています。「wait」関数は、空のループにより、一定時間CPUの処理を浪費します。

     
  これでチャタリング対策もばっちりだね。
晴子さん、今度はプログラムもちゃんと動いているよ!
 
健一君(笑)
     
   
晴子さん
  フフッ。
健一君、うれしそうねー。
とっても教えがいがあるわ。
 
     
     
  エヘヘッ。
それじゃ、お言葉に甘えて、ボクのプログラム(ソースコード1)で起きたリンクエラーについて、もっと教えてくださいよ。
 
健一君(笑)
     
   
晴子さん
  そうね。
もう少しだけ、健一君に付き合ってあげるわ。
 
     

変数の記憶域はどこだ

――健一君のプログラム(ソースコード1)では、記述していないmemcpy関数が勝手に入っていました。なぜ、そのようなことが起こるのでしょうか? そこには、変数の記憶域をどのようにメモリに配置するかという、C言語の仕組みが絡んできます。

 C言語では、関数の中で宣言される(staticなし)変数を、“自動変数”と呼びます。そして、この自動変数の記憶域は、“スタック領域”に設けられます。

 スタック領域は、マイコンのRAMに位置しますから、記憶域が確保されたばかりの内容は“不定”です。そのため、初期値を持つ変数の場合、変数初期化のプログラムが挿入されるのです。

 今回のプログラムの場合、

(1)main関数が呼ばれる
(2)char配列LEDの記憶域と、int変数countの記憶域をスタックに確保する
(3)memcpy関数により、char配列LEDの初期値をROMからコピーする
(4)main関数の処理がはじまる

となります。

 さて今回は、memcpy関数のような標準Cライブラリ関数のリンクを、「-l」オプションを指定することで解決しました。

 「-l」オプションで、「-lc」とすると、標準Cライブラリがリンクに加わります。また、「-lgcc」とすると、longとlongの割り算など、C言語の実行に必要なライブラリがリンクに加わります。さらに、H8マイコン用GCCは、H8マイコン・シリーズをサポートしているので、CPU指定のオプションも必要になります。一口に“H8マイコン”といっても、搭載されているCPUは数種類あります。ここでは、「-mh」オプション、「-mn」オプションを併せて指定することで、H8Tiny用のライブラリをリンクさせています。

コラム: static変数
 

今回は、memcpy関数をリンクすることで、実行プログラムを作りましたが、そもそもmemcpy関数を使わないC言語プログラムの記述はできないのでしょうか? ここでは、静的変数(static変数)として変数を宣言する方法を紹介します。

関数内で変数宣言するとき、記憶クラス指定子「static」を付けると、その変数には静的記憶域が確保されます。

例として、

    static unsigned char LED[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

とすると、char変数LEDは静的変数になります。

静的変数は、プログラムの実行開始時に記憶域が確保され、1度だけ内容が初期化されます。

プログラム中でchar変数LEDに値が代入されることはないため、char変数LEDは、“読み取り専用(Read Only)”と解釈しても差し支えありません。ですからCコンパイラは、char変数LEDをROMに配置します。ちなみに、char変数LEDをグローバル変数としても同じ効果が得られます。


   
晴子さん
  どうだった?
制御プログラミングって、いろいろ大変でしょ。
 
     
     
  はい。
いろいろ“ワナ”にはまったけど、今回もC言語のいい勉強になりましたよ。
 
健一君
     
   
晴子さん
  そうねー。
マイコンプログラミングの世界は、本当に奥が深いわ。
健一君もまだまだ頑張らないとね!!
 
     
     
  はい。
それじゃあ、今日はありがとうございました!
さーて、帰ろっと!
 
健一君(笑)
     
   
晴子さん(ニヤリ)
  ちょっと、待ちなさい!
今日も例のアレ(宿題)を出すわよ!!
 
     
     
  え〜。
またですか…… 
 
健一君(暗)
     
   
晴子さん(怒)
  キッ!  
     
     
  ヒッー。
お、お手柔らかに(涙) 
 
健一君(涙)
     

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

マイコン内蔵のタイマを使って、1秒間隔で「0」から「9」の数字を7セグメントLEDに巡回表示するプログラムを作ってね。くれぐれも時間は正確によ!

答え. 解答はこちら(←クリック)


 今回は――スイッチの状態をとらえる(レベル・センス)のか、スイッチのON/OFF変化をとらえる(エッジ・センス)のか――、スイッチ入力にかかわるプログラミングを解説しました。また、変数の記憶域がRAMかROMか、どこに、どのように確保されるのか、C言語プログラムの機能を解説しました。これらは、マイコン制御プログラミングの基礎中の基礎です。ここでしっかりとマスターしてください。

 さて、次回は「H8マイコンの周辺機能・タイマ」を紹介します。併せて、「割り込みプログラム」についても解説する予定です。ご期待ください!(次回に続く)

  • 連載バックナンバー
  • 全記事インデックス
  • 組み込み開発トップ
  • MONOistトップ

スキルアップ/キャリアアップ(JOB@IT)

スポンサーからのお知らせ

- PR -
@IT Sepcial

震災関連・復興支援情報

震災関連・復興支援情報
@IT MONOist/EE Times Japan/環境メディアの製造業技術者向け3メディアを中心に、震災関連/復興支援情報を集めました

次世代エンベデッドコーナー

次世代エンベデッド
“次世代”の組み込み機器を開発するエンジニアを支援するコーナー。新潮流・新技術をインタビューやコラム、解説記事で分かりやすく紹介!

Windows Embeddedコーナー

Windows Embedded
Windows Embedded専門コーナー。Windows Embedded StandardやWindows Embedded CEをはじめとする「Windows Embedded」ファミリの最新動向や技術情報をお届けします!!

Androidコーナー

Android
Android専門コーナー。組み込みデバイスへの適用からアプリケーション開発、イベントレポート、ニュースなどAndroidに関するさまざまな技術情報がここに集結!!

@IT MONOist 求人情報

- PR -