- ベストアンサー
C言語でプログラミングし、PICマイコンでLEDを制御する
現在PICを使ってLEDを制御する事を勉強しています。 3つのLEDを3秒間隔で点灯させ、それを無限に繰り返すプログラムを考えてみました。LEDは一つのポートに一つのLEDを割り振るのではなく、ICを使って制御しています。 これを発展させ、待ち時間の3秒間にRA2ポートに入力があるとLEDの点灯をその場所で停止させ、もう一度RA2ポートに入力するとループが再開するといった内容にしようと考えていますが、調べてもどうすればいいのか分かりません、分かる方は教えて頂けないでしょうか # include <16f84a.h> # fuses HS, NOWDT, NOPROTECT # use delay(clock=20000000) int flag, sec, count; main() //main関数の開始宣言 { set_tris_a(0x10); set_tris_b(0x10); #use fast_io(a) //port_aの高速処理を行う設定 #use fast_io(b) //port_bの高速処理を行う設定 while(1){ //無限ループのwhile文の宣言 output_low(PIN_A0); //RA0の出力 output_low(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED1が点灯 delay_ms( 3000 ) ; //3秒待つ output_high(PIN_A0); //RA0の出力 output_low(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED2が点灯 delat_ms( 3000 ) ; //3秒待つ output_low(PIN_A0); //RA0の出力 output_high(PIN_B5); //RB5の出力 output_low(PIN_B6); //RB6の出力 output_low(PIN_B7); //RB7の出力 //LED3が点灯 delay_ms( 3000 ) ; //3秒待つ }
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
★回答ではないが気になったので。 >main() //main関数の開始宣言 ↑ main関数の定義です。開始の宣言ではないです。記述の開始かな。 >while(1){ //無限ループのwhile文の宣言 ↑ while文の宣言という表現はおかしいね。 ちなみに無限ループなら for( ; ; ){ … } でも出来ます。 本題: ・LED の点灯と停止の方法 RA2ポートの入力状態のチェック方法 の2つを教えて下さい。 ・考え方としては delay_ms() 関数の部分にRA2ポートの入力状態をチェックしてその場で 停止したり、再開させたりすれば良いと思います。つまり、delay_ms() 関数で 3 秒間 のループを作ってそのループ内でRA2ポートの入力状態から停止、再開を出来るように 記述するわけです。 while (1){ // LED1の点灯 for ( int i = 0 ; i < 3000 ; ){ /* RA2ポートの入力状態を読み出す 例えば flag 変数に停止なら 0、再開なら 1 を入れるとする */ if ( flag ){ // 再開の時に処理 i++; // ここでインクリメント } delat_ms( 1 ); // 1ms待つ } // LED2の点灯 for ( int i = 0 ; i < 3000 ; ){ : 上と同じ処理 : } // LED3の点灯 for ( int i = 0 ; i < 3000 ; ){ : 上と同じ処理 : } } 最後に: ・for 文のループは関数にして3箇所に記述したほうが便利です。 ・以上。
その他の回答 (3)
- zwi
- ベストアンサー率56% (730/1282)
>つまりこの反転処理というのはflag変数を反転させるための処理ということなのですね。 その通りです。 チャタリングに関しては、ここが参考になるかと。 http://www.picgames.org/modules/tinyd1/index.php?id=5 高度な処理としては、チャタリングの処理をタイマー割り込みで処理させるとメインループがシンプルになるので、勉強が進んだら挑戦してみてください。 それとbeforeRA2はRA1の値を代入してからループに入るようにしてください。そうしないと、何も変化していないのにトリガ反転する恐れがあります。 おまけで、このプログラムをアセンブラのテクニックで書くとこんな感じにも書けます。参考まで。 int i; while( 1 ) { for( i=0 ; i<3 ; i++ ) { // PIN_A,PIN_Bは、ポートのレジスタを8bitでアクセスします。 PIN_A = (PIN_A & 0xfe) | (i & 0x01); PIN_B = (PIN_B & 0x1f) | ((i & 0x0e)<<4); delay_ms( 3000 ) ; //3秒待つ } }
お礼
チャダリングについて理解できました! これを知らないでプログラムをしたらおかしな動作をしそうです(汗 プログラムというのは奥が深いですね、今回は非常に参考になりました、ありがとうございます。
- zwi
- ベストアンサー率56% (730/1282)
ANo.2の方の答えで、ほぼ問題ないと思います。 ただし、RA2の入力がSWからの場合はチャタリング対策処理されていることが必要です。そこは大丈夫ですか? それと、トリガ反転するプログラムも組む必要があります。使われているのはCCS Cだと思うのですが使った事が無いので、それっぽくイメージで書かせてもらいます。 // トリガ反転処理。 if( RA2 != beforeRA2 ) { //1回前のRA2と状態が違う場合 beforeRA2 = RA2; //状態を保存する。 if( RA2 == 1 ) { //SWが1ならトリガ反転する。 flag ^= 1; //フラグの状態を反転する。 } }
お礼
間違いに気づきました、入力はRA2でなくRA1でした、申し訳ありません。 チャダリング処理、トリガ反転・・・全く意識していませんでした まだまだ勉強不足な事が多いようです。 つまりこの反転処理というのはflag変数を反転させるための処理ということなのですね。
- SRitchie
- ベストアンサー率21% (103/470)
文面及び添付ソースから詳細はわかりませんが、添付ソースにポートAの入力or割り込みをチェックするルーチンが無いですよね。
お礼
詳しい回答有難うございます 確かに日本語表現もおかしい所がありました、これでは分かり難くなってしまいますね。 for文でループを作るというのは考え付きませんでした! 確かにこれであれば【3秒間の間に信号を入れる→LED停止】という形になりそうです。 非常に参考になりました。