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

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

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

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

Q&A

解決済

3回答

41047閲覧

ボタンを押すとLEDが点灯、もう一度押すと消灯というプログラムを作りたいです

isida

総合スコア11

C

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

0グッド

0クリップ

投稿2015/11/12 01:58

###前提・実現したいこと
C言語初心者です。ボタンを押すとLEDが点灯、もう一度押すと消灯というプログラムを作りたいです。
似たような質問もいくつかあり、その回答も参考にして考えましたがよくわからなくなりました。
よくある質問だと思いますがよろしくお願いします。

###発生している問題・エラーメッセージ
現在のプログラムだとボタンを押している間は点灯、離すと消灯、離しても点灯することがあります。

###ソースコード
#define SW_OFF 0
#define SW_ON 1
unsigned char getSW(void); //スイッチ読込関数の宣言
void LED_CTR(void); //LED制御関数の宣言
void LED(unsigned char number); //LED点灯関数の宣言

void main(void)
{
while(1){
LED_CTR(); //LED制御
}
}

void LED_CTR() //LED制御関数
{
static int sw = 0;
unsigned char a; //スイッチ入力の格納変数の宣言
a = getSW(); //スイッチ入力の読み込み
if(a == 1) { //スイッチ入力の判別
++sw;
sw &=1;
LED(sw);
}
}

unsigned char getSW(void) //スイッチ読込関数
{
unsigned char flag = 0;
if(P1.0 == SW_ON) //P1.0はスイッチポート
{
flag = 1;
}
return flag;
}

void LED(unsigned char number) //LED点灯関数
{

if(number == 1)
{
P2.1 = 1; //P2.1はLEDポート
}else{
P2.1 = 0;
}
}

###補足情報(言語/FW/ツール等のバージョンなど)
c言語

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。
2点問題があるようです。

まず1点目は、LED_CTR()を見ると、スイッチがONの間、継続して++swしているため、LEDのON/OFFを高速に繰り返しているようです。そこで、スイッチがOFF->ONへ変化した時だけ++swする必要があります。

次に2点目は、機械接点式のスイッチはチャタリングがあり、ONとOFFが切り替わる瞬間、高速にON/OFFを繰り返します。ですので、チャタ取りも必要です。
良くある方法は、数mSec程度あけて2回スイッチの状態を読み取り、一致したら確定します。
ここに詳しい解説があります。

チャタ取り後に、OFF->ONチェックすると安定するようになりますよ。


【追記】
ちょっと安易すぎるのですが、チャタ取りも含めたLED_CTR()関数を作ってみました。
OFF->ON検出のところは、catsforepawさんのコードとほぼ同じです。

C

1void LED_CTR() //LED制御関数 2{ 3 static int sw = 0; 4 unsigned char now; //スイッチ入力の格納変数の宣言 5 static unsigned char last = 0; 6 int i; 7 for (i=0; i < 100; ++i) 8 { 9 now=getKey(); 10 if (now == last) 11return; 12 } 13 14 if ((last == 0) && (now != 0)) 15 { 16 ++sw; 17 sw &=1; 18 LED(sw); 19 } 20 last=now; 21}

for文で100回回してます。もし、LEDのON/OFFが安定しない(キーを1回押しただけでON->OFF->ONを何回か行う)ような時は、もっと数を増やしてみてください。

なお、一般的にはgetKey()の前あたりでちゃんと時間を測って数mSecの待ちをタイマで行うべきです。
お使いのシステムのタイマが分からないので、安易にループを回してます。この辺は次の課題として頑張って下さい。

投稿2015/11/12 02:16

編集2015/11/12 12:50
Chironian

総合スコア23272

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

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

isida

2015/11/12 11:35

返信ありがとうございます。上の方もおっしゃるようにOFF->ONへ変化した時だけ++swする必要があるようです。ボタンの状態の読み取り方法でもうちょっとヒントもらえませんか?
isida

2015/11/18 00:21

上記の変更点でボタン一つで切り替えることができるようになりました。ありがとうございました。まだまだ勉強が必要なので頑張ります。
guest

0

チャタリングというよりは、スイッチの判定をエッジで行っていないことが問題の原因だと思います。
エッジとは、立ち上がり(OFF状態→ON状態への変化)と立ち下がり(ON状態→OFF状態への変化)のことです。
ですので、読み取ったスイッチの状態もstatic変数で覚えておく必要があります。そして、たった今読み取った状態と前回読み取った状態を比較して、変化があったときだけLEDをON/OFFするという処理が必要です。

追記

チャタリング対策も場合によっては必要かもしれません。ソースを見ると、超高速でスイッチの判定をしているので、スイッチ回路のお金のかけ具合によってはチャタリングが発生します。

さらに追記

ご質問の件では押したときだけ反応させたいとのことなので、立ち上がり(OFF→ON)だけを判定すれば良いことになります。

LED_CTR関数への修正はこんな感じになります。

C

1static int sw = 0; // 変更なし 2static unsigned char last = 0; // スイッチの状態を覚えるためのstatic変数を追加 3// スイッチの読み込みは変更なし 4if(last == 0 && a == 1) // スイッチ入力の判定を変更(前回OFFで今回ON) 5{ 6 // この中も変更なし 7} 8last = now; // スイッチの状態を覚えておく

投稿2015/11/12 10:07

編集2015/11/12 12:07
catsforepaw

総合スコア5938

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

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

Chironian

2015/11/12 10:39

あちゃ、私の回答、分かりにくかったみたいですね。修正しました。 それと、チャタがある時はOFF->ONが頻繁に発生するので、チャタを取らないとなかなか安定してLEDがON/OFFしなくなります。
catsforepaw

2015/11/12 10:43

すみません。私の方こそあまり読まずに回答しちゃっていました。スイッチでLEDの制御という話題に体が先に反応してしまったようです(そういうの好きなのです)。
isida

2015/11/12 11:28

返信ありがとうございます。読み取った状態と前回読み取った状態を比較する方法がピンと来ていません。ちょっと時間がかかりそうです。
catsforepaw

2015/11/12 12:08

> 読み取った状態と前回読み取った状態を比較する方法 コード例を追加しました。
isida

2015/11/18 00:50

とても参考になりました。ありがとうございました。
guest

0

点いたり消えたりがコントロールできていないのは、SWを押している間、LEDの制御が動いて居るからです。変化があったときだけ、呼び出すように修正すればOKだと思います。

このプログラムではSWが押されている間、LEDが点いているように見えるかもしれませんが、実際は高速にON/OFFを繰り返していろ50%点灯で、SWが離された時のタイミングでLEDの状態が決まります。(とまった時についている場合は、100%点灯です。明るさに変化はありませんか?)

チャタリングについてはハードでカバーしている場合もありますので、問題をかくにんしてから対処されると良いでしょう。

投稿2015/11/12 10:30

T.Kanno

総合スコア915

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

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

isida

2015/11/12 11:32

返信ありがとうございます。ボタンを押したり離したりするとLEDが薄暗くなっています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問