PICでCの練習 2007.05.08(火)〜 LessonC_15。 タイマー0割り込みでキーのチャタリング除去処理。ビットフィールドを使います。
著作者名: 中野 良知 作成開始: 2007.05.08(火) 修正 : 2007.05.09(水) ビットフィールド初期化の書式を修正。 : 2007.05.14(月) ソースコードでconfigのXTALをHSに変更。 : 実験回路図に電源パスコンを追加。 : 発振子のGNDと5PIN(GND)を直近に変更。
目次 1. 目的 2. ゼネラルフローチャート 3. プログラムソースコード 4. キーワード 4.1. ビットフィールド 4.2. エッジ検出 5. 実行結果 6. 実験回路 1. 目的 1msecごとのタイマー0割込みでキー入力のチャタリング除去をします。 キーオンエッジ検出フラグにビットフィールドを使います。 2. ゼネラルフローチャート (main) ↓ ポートの初期化 ↓ タイマー関連の初期化 ↓ ├←─────────────┐ ↓ no │ <キーオンエッジ?>→──────┤ ↓yes │ RB0ビット反転出力 │ ↓ │ キーオンエッジビットリセット │ └──────────────┘ (タイマー割り込み) ↓ タイマー再起動 ↓ キー入力チャタリング除去 ↓ no <キーオン(立下り)エッジ?>→──(割り込み終了) ↓yes キーオンエッジビットセット ↓ (割り込み終了) 3. プログラムソースコード //***************************************************************************** // タイトル : LesssonC_15 // 作者 : ioio // 目的 : タイマー0の割り込みで、キー入力のチャッタリング除去をします。 // : キーオンエッジ検出でビットフィールドを使用します。 // マイコン : PIC16F84A // クロック : 20MHz // Config : PROTECT=OFF, WDTE=OFF, XTAL // Compiler : PICC Lite(V9.6)。 HI-TEC software製。 // Compile : >picl -16f84a lesson.c // ASM List : >picl -16f84a --ASMLIST lesson.c //***************************************************************************** // 変更履歴 // 2007.05.08(火) 作成 // 2007.05.14(月) configでXTALをHS_OSILLATORに変更 //***************************************************************************** //----------------------------------------------------------------------------- // ヘッダーファイル #include "pic.h" // デバイス関連の定義を展開 //----------------------------------------------------------------------------- // コンフィグレーション定義 __CONFIG(0x3FFA); // PROTECT=OFF, WDTE=OFF, HS_OSILLATOR //----------------------------------------------------------------------------- // 関数定義 //----------------------------------------------------------------------------- // 定数の定義 #define SET_TMR0 256-156 // 156*32*200ns=998.4us //----------------------------------------------------------------------------- // グローバル変数定義 unsigned int chat_cnt; // キーチャタリング除去カウンタ unsigned char key_new; // 最新のキー入力 unsigned char key_old; // 前回のキー入力 unsigned char key_fix; // キー入力確定 //----------------------------------------------------------------------------- // ビットフィールド構造体定義 struct { unsigned k1:1; // メンバーk1に1ビット分を割り当て } key_on = {0}; // キーオンエッジ検出初期化=キーオフ //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void main(void) { TRISB = 0x00; // PortB b0,b1,b2,b3,b4,b5,b6,b7=Out INTCON = 0b10100000; // TMR0割り込み許可。全割り込み許可 OPTION = 0b11000100; // プリスケール=1/32。内部命令サイクルを選択 TMR0 = SET_TMR0; // タイマー0設定 PORTB = 0x00; // ポートB初期化 chat_cnt = 0; // キーチャタリング除去カウンタ初期化 key_old = 0x01; // キー入力の前回値を初期化=キーオフ key_fix = 0x01; // キー入力確定値初期化=キーオフ while(1){ if(key_on.k1){ // キーオンエッジならば key_on.k1 = 0; // キーオンエッジリセット RB0 ^= 1; // LEDビット出力反転 } } } //----------------------------------------------------------------------------- // タイトル: 1msecのタイマー割り込み関数 // 作成 : 2007.05.08(火) // 機能 : タイマーの再起動 // : キー入力のチャタリング除去 // : キー入力のオンエッジ検出 //----------------------------------------------------------------------------- static void interrupt isr(void) { TMR0 = SET_TMR0; // タイマー0設定(再スタート) T0IF = 0; // タイマー0オーバーフローフラグリセット // キーのチャタリング除去とオンエッジ検出 key_new = PORTA & 0x01; // 最新のキー入力を取り込む if(key_new ^ key_old){ // 前回のキー入力と比較。排他的論理和。 // 前回と一致しなければ chat_cnt = 0; key_old = key_new; // 今回のキー入力を保存 }else{ // 前回と一致すれば if(++chat_cnt == 10){ // 10msec間キー入力が安定していれば // キー入力オンエッジ検出。(立下りエッジ検出) if((key_new ^ key_fix) & key_fix){ key_on.k1 = 1; // キーオンフラグセット } key_fix = key_new; // キー確定に保存 chat_cnt--; // チャッター処理カウンタを-1 } } } //***************************************************************************** //***************************************************************************** 4. キーワード 4.1. ビットフィールド key_on変数をビットフィールド構造にします。 7 6 5 4 3 2 1 0 ┌───┬───┬───┬───┬───┬───┬───┬───┐ │ │ │ │ │ │ │ k2 │ k1 │ └───┴───┴───┴───┴───┴───┴───┴───┘ ビットフィールドの定義は struct{ unsigned k1:1; // メンバーk1に1ビット分をを割り当てます。 unsigned k2:1; // メンバーk2に1ビット分をを割り当てます。 } key_on = {0, 0}; // 変数名をkey_on。 各メンバーを0に初期化します。 メンバーは記述順にLSBから割り当てられます。 使い方 key_on.k1 = 0; // ビットk1をリセットします。 key_on.k1 = 1; // ビットk1をセットします。 if(key_on.k1){} // ビットk1が1なら、{}を実行します。 今回はk1だけを割り当てましたが、1ビットあるいは複数ビットの情報を1バイトの 変数内に効率よく割り当てる事が出来ます。 4.2. エッジ検出 if((key_new ^ key_fix) & key_fix){ key_on.k1 = 1; // キーオンフラグセット } でキーの立下りエッジを判定し、検出フラグをセットします。 ^は排他的論理和。 &は論理積を表す記号です。 ────┐ ┌───────── RA0 └───────────┘ ────┐ ┌───────── key_new └───────────┘ ──────┐ ┌─────── key_fix └───────────┘ key_new ┌┐ ┌┐ ^ key_fix ─────┘└──────────┘└─────── ┌┐ & key_fix ─────┘└─────────────────── ┌──────────────────── key_on.k1 ─────┘ key_in.k1はプログラムでリセットするまで1を保持します。 5. 実行結果 上:RA0(キー入力)の波形。 下:RB0(LED出力)の波形。 チャタリングを除去した後、10.8msec後にLED出力が変わります。 6. 実験回路 PIC16F84A ┌────┐14 │ VDD├──────●──────●────●──── +5V │ │ │ │0.1u │ │ │ R10K ┴ /50V │┴│100u/16V │ │4 │ 0.1u/50V ┬ └┬┘ │ -MCLR├──────●─┤├───●────┘ │ │ │ │ │16 ┌ ─ ─ ─ ┐ │ │ OSC1├───●─┤├──┐ │ │ │ │┴ ││ │ │ │ □ 20MHz │ │ │ │15 │┬ ││ │ │ OSC2├───●─┤├──● │ │ │ └ ─ ─ ─│┘ │ │ │5 ┌───────┘ │ │ Vss├─●───────────● │ │ │ │ │ LED │ │ │6 ┌─┬┐K │ │ RB0├──┤ │├─R220──● │ │ └─┴┘ │ │ │ │ └────┘ ┴ GND 0.1u/50VのコンデンサーはVDDとVssの近くに接続します。 発振子のGNDはVssの直ぐ近くに接続します。
LessonCのTopへ
サイトのTopへ
法律条項 この資料により生じたいかなる障害や損害に対し、著者は全てを免責されるものとします。 この資料は、著作権法の下で保護され、入手先、著者、日付、法律条項を含んだ場合にのみ複製が可能です。
inserted by FC2 system