みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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秒待つ
}

投稿日時 - 2007-06-22 12:43:53

QNo.3106023

困ってます

質問者が選んだベストアンサー

★回答ではないが気になったので。
>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箇所に記述したほうが便利です。
・以上。

投稿日時 - 2007-06-22 13:40:57

お礼

詳しい回答有難うございます
確かに日本語表現もおかしい所がありました、これでは分かり難くなってしまいますね。

for文でループを作るというのは考え付きませんでした!
確かにこれであれば【3秒間の間に信号を入れる→LED停止】という形になりそうです。
非常に参考になりました。

投稿日時 - 2007-06-22 18:16:19

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

zwi

>つまりこの反転処理というのは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秒待つ
}
}

投稿日時 - 2007-06-22 18:55:18

お礼

チャダリングについて理解できました!
これを知らないでプログラムをしたらおかしな動作をしそうです(汗

プログラムというのは奥が深いですね、今回は非常に参考になりました、ありがとうございます。

投稿日時 - 2007-06-25 11:50:03

ANo.3

zwi

ANo.2の方の答えで、ほぼ問題ないと思います。

ただし、RA2の入力がSWからの場合はチャタリング対策処理されていることが必要です。そこは大丈夫ですか?

それと、トリガ反転するプログラムも組む必要があります。使われているのはCCS Cだと思うのですが使った事が無いので、それっぽくイメージで書かせてもらいます。

// トリガ反転処理。
if( RA2 != beforeRA2 ) { //1回前のRA2と状態が違う場合
beforeRA2 = RA2; //状態を保存する。
if( RA2 == 1 ) { //SWが1ならトリガ反転する。
flag ^= 1; //フラグの状態を反転する。
}
}

投稿日時 - 2007-06-22 15:01:59

お礼

間違いに気づきました、入力はRA2でなくRA1でした、申し訳ありません。

チャダリング処理、トリガ反転・・・全く意識していませんでした
まだまだ勉強不足な事が多いようです。

つまりこの反転処理というのはflag変数を反転させるための処理ということなのですね。

投稿日時 - 2007-06-22 18:25:45

ANo.1

文面及び添付ソースから詳細はわかりませんが、添付ソースにポートAの入力or割り込みをチェックするルーチンが無いですよね。

投稿日時 - 2007-06-22 13:00:15

あなたにオススメの質問