PICでCの練習 2007.05.09(火)〜 LessonC_16。 タイマー0割り込みで+1するカウンターでキー押し期間を計測します。
著作者名: 中野 良知 作成開始: 2007.05.09(水) 修正 : 2007.05.14(月) ソースコードでconfigのXTALをHSに変更。 : 実験回路図に電源パスコンを追加。 : 発振子のGNDと5PIN(GND)を直近に変更。
目次 1. 目的 2. ゼネラルフローチャート 3. プログラムソースコード 4. キーワード 4.1. if(!key_fix){} 4.2. キーオフエッジ検出 5. 実行結果 6. 実験回路 1. 目的 1msecごとのタイマー0割込みでインクリメントするカウンタでキーがオンしている期 間を測ります。 キー入力のチャタリング除去。キーオン・オフのエッジ検出フラグにビットフィール ドを使います。 2. ゼネラルフローチャート (main) ↓ ポートの初期化 ↓ タイマー関連の初期化 ↓ ├←─────────────┐ ↓ no │ <キーオンエッジ?>→──────┤ ↓yes │ カウンターリセット │ ↓ no │ <キーオフエッジ?>→──────┤ ↓yes │ カウンター値でLED点灯 │ ↓ no │ < キーオン?> →────────┤ ↓yes │ カウンター値でLED点灯 │ └──────────────┘ (タイマー割り込み) ↓ タイマー再起動 ↓ カウンターインクリメント ↓ キー入力チャタリング除去 ↓ no <キーオン(立下り)エッジ?>→─┐ ↓yes │ キーオンエッジビットセット │ ↓ │ (割り込み終了) │ │ ┌─────────────┘ <キーオフ(立上り)エッジ?>→─┐ ↓yes │ キーオフエッジビットセット │ ↓ │ ├─────────────┘ ↓ (割り込み終了) 3. プログラムソースコード //***************************************************************************** // タイトル : LesssonC_16 // 作者 : 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.09(水) 作成 // 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; // キー入力確定 unsigned char time_cnt1ms; // キーオンカウンタ unsigned char time_cnt100ms; // キーオンカウンタ //----------------------------------------------------------------------------- // ビットフィールド構造体定義 struct { unsigned on:1; // メンバーonに1ビット分を割り当て unsigned off:1; // メンバーoffに1ビット分を割り当て } key_edj={0,0}; // メンバーon,offをリセット //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- 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初期化。LED全消灯 chat_cnt = 0; // キーチャタリング除去カウンタ初期化 key_old = 0x01; // キー入力の前回値を初期化=キーオフ key_fix = 0x01; // キー入力確定値初期化=キーオフ while(1){ if(key_edj.on){ // キーオンエッジならば key_edj.on = 0; // キーオンエッジリセット time_cnt1ms = 0; // 計測開始。カウンタクリア time_cnt100ms = 0; // 計測開始。カウンタクリア } if(key_edj.off){ // キーオフエッジならば key_edj.off = 0; // キーオフエッジリセット // 計測値を表示 PORTB = time_cnt100ms; // LED表示 } if(!key_fix){ // キーオンなら PORTB = time_cnt100ms; // LED表示 } } } //----------------------------------------------------------------------------- // タイトル: 1msecのタイマー割り込み関数 // 作成 : 2007.05.09(水) // 機能 : タイマーの再起動 // : キー入力のチャタリング除去 // : キー入力のオン・オフエッジ検出 //----------------------------------------------------------------------------- static void interrupt isr(void) { TMR0 = SET_TMR0; // タイマー0設定(再スタート) T0IF = 0; // タイマー0オーバーフローフラグリセット if(++time_cnt1ms == 100){ // 1msec桁カウンタ+1 time_cnt1ms = 0; ++time_cnt100ms; // 100msec桁カウンタ+1 } // キーのチャタリング除去とオン・オフのエッジ検出 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_edj.on = 1; // キーオンフラグセット } // キー入力オフエッジ検出。(立上がりエッジ検出) if((key_new ^ key_fix) & key_new){ key_edj.off = 1; // キーオフフラグセット RB0 = 1; } key_fix = key_new; // キー確定に保存 chat_cnt--; // チャッター処理カウンタを-1 } } } //***************************************************************************** //***************************************************************************** 4. キーワード 4.1. if(!key_fix){} key_fixの前に!が付くと、key_fixが0なら{}を実行し、0以外なら{}をスキップしま す。 4.2. キーオフエッジ検出 if((key_new ^ key_fix) & key_new){ key_edj.off = 1; // キーオフフラグセット } でキーの立上がりエッジを判定し、検出フラグをセットします。 ^は排他的論理和。 &は論理積を表す記号です。 ────┐ ┌───────── RA0 └───────────┘ ────┐ ┌────────── key_new └───────────┘ ──────┐ ┌──────── key_fix └───────────┘ key_new ┌┐ ┌┐ ^ key_fix ─────┘└──────────┘└──────── ┌┐ & key_new ─────────────────┘└──────── ┌───────── key_edj.off ────────────────┘ key_edj.offはプログラムでリセットするまで1を保持します。 5. 実行結果 キーオフ時のwhile(1){}処理時間 = 2.44usec。 キーオン時のwhile(1){}処理時間 = 2.96usec。 タイマー割り込み処理時間 = 8.2usec。 上:RA0(キー入力)の波形。 下:key_edj.offの波形。 チャタリングを除去した後、10.4msec後にkey_edj.offがセットされます。 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──● │ │ └─┴┘ │ │ │ LED │ │ │7 ┌─┬┐K │ │ RB1├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │8 ┌─┬┐K │ │ RB2├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │9 ┌─┬┐K │ │ RB3├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │10 ┌─┬┐K │ │ RB4├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │11 ┌─┬┐K │ │ RB5├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │12 ┌─┬┐K │ │ RB6├──┤ │├─R220──● │ │ └─┴┘ │ │ │ LED │ │ │13 ┌─┬┐K │ │ RB7├──┤ │├─R220──● │ │ └─┴┘ │ │ │ │ └────┘ ┴ GND 0.1u/50VのコンデンサーはVDDとVssの近くに接続します。 発振子のGNDはVssの直ぐ近くに接続します。
LessonCのTopへ
サイトのTopへ
法律条項 この資料により生じたいかなる障害や損害に対し、著者は全てを免責されるものとします。 この資料は、著作権法の下で保護され、入手先、著者、日付、法律条項を含んだ場合にのみ複製が可能です。
inserted by FC2 system