質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2777閲覧

PICのボタン入力遅延

GM-DS

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/08/25 00:58

編集2020/08/25 01:38

お世話になっております。
以前、このサイトで様々な方にお世話になり、ご教示頂いたコードを基にコードを作成しています。
今回も引き続きPIC16F1503を使用して下記動作のプログラミングを作成致しました。

①LSW1がONの時、PB1を0.2秒押すと作動してLED1が点滅、LED3・4が点灯
②10秒以内にPrSWがONすると、LED1が点灯、LED3・4が消灯
③作動後、PrSWがONせず10秒経過すると、LED2点滅、LED1・3・4が消灯、BZ-ON

●問題点
①PB1を確実に押したと言う意味合いで0.2秒の長押しコードを作成しました(※1)。
現状、動作は正常にしています。しかしながら、C言語初心者と言う事もあり、良いものなのか不安です。
そこで、今後の為に、アドバイスを頂きたいと思っております。
②PB1(作動)とPB2(停止)を交互に押していると、不定なタイミングで急にmode3になってしまいLED2が点滅、BZ-ONする現象が起きました。そこで私なりに考えて、出力のmode0のコードに※2を追加致しました。現状、繰り返し試験を行いましたが現象は発生していません。
しかし、①で述べたようにいいものなのか不安です。同じようにアドバイスを頂きたいと思っております。

以上、よろしくお願いいたします。

void main (void){ //マイコン設定 OSCCON = 0b01111000; //内部クロック周波数を16MHzに設定 ANSELA = 0b00000000; //PortA全てのピンをデジタルモードに設定 ANSELC = 0b00000000; //PortC全てのピンをデジタルモードに設定 TRISA = 0b00110000; //PortAピン設定 TRISC = 0b00110000; //PortCピン設定 //初期処理:電源ON後、全ての出力を一度OFFにする。 LED1 =0; LED2 =0; LED3 =0; LED4 =0; BZ =0; int cnt=0; //カウント int PB1cnt=0; //PB1入力遅延用カウント int mode=0; //modeは出力 //mode0:全停止 //mode1(作動)=LED1点滅、LED3点灯、LED4点灯 //mode2(OK)=LED1点灯、LED3-OFF、LED4-OFF //mode3(NG)=LED2点滅、LED3-OFF、LED4-OFF、BZ-ON __delay_ms(1000); //電源投入後、誤作動を起こさないよう1秒待機してから本プログラムへ移行 while(1){ //入力 //mode0の時、LSW1+PB1(作動)がONしたら、modeを1にしてカウンタも初期化 if(mode==0 && PB1==0 && LSW1==0){ ※1 for(PB1cnt=0;PB1cnt<20;PB1cnt++){ __delay_ms(10); if(PB1==1)break; } if(PB1cnt==20){ mode=1; cnt=0; PB1cnt=0; } } //PrSWがONしたらmodeを2にする if(PrSW==0){ mode=2; } //PrSWがOFF、PB2(停止)がONしたら、どんな状態からでもmodeを0にする if(PrSW==1 && PB2==0){ mode=0; } //PrSWがOFFの時、modeを0にする if(mode!=3 && mode!=1 && PrSW==1){ mode=0; } //出力 if(mode==0){ //全停止 LED1=0; LED2=0; THUP=0; CL =0; BZ =0; ※2 cnt =0; } else if(mode==1){ //mode1(作動)=LED1点滅、LED3-ON、LED4-ON LED1=(cnt%100<50); LED2=0; LED3=1; LED4=1; BZ =0; __delay_ms(10); if(++cnt==1000){ //カウントが1000(10秒)になった時、modeを3、カウントを0にする mode=3; cnt =0; } } else if(mode==2){ //mode2(OK)=LED1点灯、LED3-OFF、LED4-OFF LED1=1; LED2=0; LED3=0; LED4=0; BZ =0; } else if(mode==3){ //mode3(NG)=LED2点滅、LED3-OFF、LED4-OFF、BZ-ON LED1=0; LED2=(cnt<50); LED3=0; LED4=0; BZ =1; __delay_ms(10); if(++cnt==100){ cnt=0; //1秒たったらカウントを0にして最初からカウント } } } return; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fiveHundred

2020/08/25 01:03

C#とは関係なさそうなので、もしそうであればタグから外してください。 (C#はC/C++とは別物です)
GM-DS

2020/08/25 01:38

C#をタグから外しました。失礼いたしました。
guest

回答2

0


チャタリング回避の目的としては不要な処理です。
PB1押下はmodeを1に変更し、開放は何もしませんが、
この場合チャタリングで短時間に接触と非接触が入れ替わってもmodeが1になるだけで悪影響はありません。
チャタリング回避が必要なのは押下回数を数えるなど、開放時にも別の処理をする場合です。

なお、しばしば混同されますが、チャタリングでなくノイズによってボタン非押下時に反応してしまうのを回避する目的では有用です。
私は今まで経験が無いのですが、おそらく強力な電波が飛び交うような環境では発生するのではないかと思っています。


※2を除いたコードは「modeが1の時カウントを進め、そうでないときカウントを保持」ですので、
作動と停止を交互に押せば「累計で」10秒になったタイミングでmode3になるでしょう。
それが求める動作でないなら、正しい変更だと思います。

投稿2020/08/26 01:02

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GM-DS

2020/08/26 08:39

ikadzuchi様 お忙しい中、ご回答ありがとうございます。 まったく意味のないコードでなく良かったですw チャタリング対策についてはy_waiwai様に教えて頂いたコードを解読しながら試験中です。 ②については意味のある変更で良かったです。先輩方の裏付けがあれば安心です。 ありがとうございます。
guest

0

ベストアンサー

スイッチ(接点)にはチャタリングというものが発生します
スイッチの入/切した場合に、数msの間にON/OFFを繰り返してしまうというものです

ということで、スイッチの状態を入力する場合にはこのチャタリングというのを除去する必要があります
スイッチの状態を読む場合、10msほどの間隔を開けて2回読み出し、1回目と2回めの状態を比較し、違ってる場合はその結果を捨て、同一の場合のみスイッチの処理を行う、ということをします

投稿2020/08/25 02:36

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GM-DS

2020/08/25 04:20

y_waiwai様 お忙しい中、返信ありがとうございます。 実は、チャタリングについてのコードは本サイトの過去の質問をみて考えました。 しかしながら理屈は分かるのですが、コードが理解できませんでした。 そのコードを載せるのもどうかと思い、自分なりに考えたコードを作成致しました。 チャタリング対策も含め考えたコードでした。
y_waiwai

2020/08/25 04:27

まあ、オイラがするなら、タイマ割り込みを実装し、タイマ割り込み内で定期的にスイッチの状態を読み出し、チャタリング除去、エッジ検出もろもろ処理してしまい、メインループ中ではその状態を読むだけ、にしてしまいますね
GM-DS

2020/08/25 06:14

割り込みですか・・・ 私にはまだ高度です・・・ 因みに私のコードではチャタリング対策・長押しにはなっていませんか? また、たまに入ってしまうmode3対策は間違えていますでしょうか?
y_waiwai

2020/08/25 06:43

ちょっとそのコードではなにやってるかわからんですw とりあえずチャタリング除去する入力関数です 差し替えてやってみよう int KEYIN(){ int flg; while(1){ flg=PB1; __delay_ms(10); if(flg==PB1) break; } return flg; }
GM-DS

2020/08/25 09:28

返信ありがとうございます。 ダメなコードでしたか・・・w ご教示ありがとうございます。 これはflgを宣言して、PB1の状態をflgに代入して、10ms後に比較をして同じならこのwhileから抜けてflgを0にする?でしょうか? 最初の「KEYIN(){」はどのような意味なのでしょうか? 初歩的な質問になってしまっていると思います。 申し訳ございません。 ご教示の程、よろしくお願いいたします。
GM-DS

2020/08/27 02:40 編集

すみません。 頂いたコードを勉強致しました。 int KEYIN(){//ここにflgの状態を返す int flg; while(1){ flg=PB1;//PB1の状態をflgに代入 __delay_ms(10);//10ms待機 if(flg==PB1) break; //flgとPB1が同じならこのwhileから抜ける } return flg;//flgの状態をKEYIN()に返す } flgはbreakから抜けた=真と言う事だからKEYIN()に真が返ると言う意味になるのでしょうか? 頂いたコードを理解することができず申し訳ございません。 お手数ですがご教示の程、よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問