PICによる7セグLED3桁制御
度々こちらに、お世話になっております。
今回は、3桁のLEDを1から999までカウント表示する
プログラムに取組んでいるところ希望通りに、動いてはくれません。
このソースのベースは2桁(1から99までカウントUP)の
ソースコードを変更して、3桁表示させる様にしてみました。
コード概要はtimer0割込みで3.2msのインターバルタイムの間、
LEDをダイナミック点灯させ、timer1では、100msのインターバルタイムを
10回繰り返し(1秒毎に)counterを1プラスしてLEDの表示を1ずつ
増して999まで表示後、また000から繰返すと言う単純な動作のものです。
main()関数内はtimer0とtimer1の割込み設定及び
割込み開始、許可を繰返すだけです。
問題の#timer0,#timer1割込み関数処理部分における実行結果は、
000から111と言う具合に3桁が同時にカウント表示されてしまい、
しかも繰り上がる時間は1秒毎の筈が、100秒毎になります。
このコードはCCS-Cコンパイラに準拠していて、
標準Cとは多少異なる部分があり解りにくいと思いますが
どうかどなた様からも検証より不具合コード部分のご指摘と修正を
頂くことが出来るなら、大変光栄に思います。
そこで、PICにおけるconfigu部分は省き、概ねのコードを記します。
////
1:static long int number;
2:static int counter;
3:int const LED_SEG[11]= {0x7E,0xCC,...略}
4:#int_timer0
5:void isr()
{
6:static int a,b,c = 0;
7:int x;
8:out_low(PIN_C0); // LED 1桁目off
9:out_low(PIN_C1); // LED 2桁目0ff
10:out_low(PIN_C2);// LED 3桁目0ff
11:a = number % 10;
12:x = number/10;
13:b = x % 10;
14:c = x / 10;
15:output_b(LED_SEG[a]);
16:output_high(PIN_C0);//1桁目ON
17:output_b(LED_SEG[b]);
18:output_high(PIN_C1);//2桁目ON
19:output_b(LED_SEG[c]);
20:output_high(PIN_C2);//3桁目ON
}
21:#int_timer1
22:void isr()
{
23:set_timer1(0x0BDC);//100ms再設定
24:counter++;
25:if(counter>9)//10回か
{
26:counter = 0;
27:number++;
}
28:if(number>1000)
{
29:number = 0;
}
}
30:void main()
{
略
31:setup_timer0(3.2msセット)
32:setup_timer1(100msセット)
33:timer0割り込み許可
34:timer1割り込み許可
35:GLOBAL全体割り込み許可
36:while(1){}
}
////
以上宜しくお願いいたします。
No.3ベストアンサー
- 回答日時:
回答1の者です。
的はずれな回答をしてしまってすみません。> なぜ割込みを抜けると3桁目の表示のままになるのでしょうか?
1桁目・2桁目を消灯させずに、3桁とも表示した状態にしてしまっているからです。
質問者さんのコードの実行結果を順を追って説明すると、
> 15:output_b(LED_SEG[a]);
> 16:output_high(PIN_C0);//1桁目ON
ここで、1桁目のLEDのみONになり、1桁目のLEDに、aが表示されます。
> 17:output_b(LED_SEG[b]);
ここで、1桁目のLEDの表示内容がbに変わります。
> 18:output_high(PIN_C1);//2桁目ON
ここで、2桁目もONになり、1桁目もONにしたままですから、1桁目と2桁目に、bが表示されます。
> 19:output_b(LED_SEG[c]);
ここで、1桁目と2桁目の表示内容がcに変わります。
ここまで、15~19は、μ秒オーダで起こりますから、まず視認できません。
> 20:output_high(PIN_C2);//3桁目ON
ここで、3桁目もONになり、1桁目・2桁目もONにしたままですから、1桁目・2桁目・3桁目、全てのLEDにcが表示されます。
以上で、割り込みルーチンが終わりますから、次の割り込みまでの3.2m秒間はこの状態が続きます。
以上のながれで、「3桁めの数字だけが全桁表示された」状態が続くことになります。
一方、回答2のコードでは、
割り込みルーチン冒頭で全桁をOFFにしたあと、状態に応じて「1つだけをONに」していますから、
割り込みを抜けた時点では、点灯しているLEDは1つだけという状態になってます。
評価に則したご回答頂き、ありがとうございます。
もう一度ハード側をじっくり眺めていると、7セグLED3個は
マイコン側とは8本線で3桁が共通線として接続されている事に、今更気づきました。
ここが今回の、ポイントでした。
3個がそれぞれ8本ずつ、独立してマイコンに接続されているのなら
1ルーチン内でも、それぞれ違う表示が同時に可能になりますが、
ダイナミック点灯方式では、1つの表示方法をONとOFFより瞬時に切り替えて
それぞれの桁を使い分けるところが、ミソのはず。
考えではダイナミック方式になっていると思っていたのですが、
実際には3.2msの一瞬に最後行までを実行、ルーチンを抜ける時
PIN_C2(3桁目)値の信号が1桁目、2桁目へも反映させた状態でルーチンを抜ける。
ということで、1桁目と2桁目が9・9までは0・0・0表示のままで、桁上がりで
1・0・0になると1・1・1になる。したがって
その間のカウント時間は100秒になる事が、理解できました。
つぎにPIN_C2が変化するまで100秒間は3桁同じ表示のまま。
と言う風に自分で解釈一応溜飲が下がり完結となりましたので
ありがとうございました。
No.2
- 回答日時:
タイマー0の割り込みルーチンが駄目です。
このままでは一回の割り込みの中で1桁目、2桁目、3桁目の表示を行っていて、
割り込みから抜けると3桁目の表示のままになってしまいます。
下記のように一回の割り込みでは一桁だけ表示するようにしましょう。
コンパイルはしていないのでエラーが有るかもしれません。
なお、全角スペースを使用しているのでタブか半角スペースに修正してください。
4:#int_timer0
5:void isr()
{
6:static int a,b,c = 0;
static int state=0 ;
7:int x;
8:out_low(PIN_C0); // LED 1桁目off
9:out_low(PIN_C1); // LED 2桁目0ff
10:out_low(PIN_C2);// LED 3桁目0ff
11:a = number % 10;
12:x = number/10;
13:b = x % 10;
14:c = x / 10;
switch( state ){
case 0 : state++ ;
15:output_b(LED_SEG[a]);
16:output_high(PIN_C0);//1桁目ON
break ;
case 1 : state++ ;
17:output_b(LED_SEG[b]);
18:output_high(PIN_C1);//2桁目ON
break ;
default : state=0 ;
19:output_b(LED_SEG[c]);
20:output_high(PIN_C2);//3桁目ON
break ;
}
}
この回答への補足
早速、検証からご回答いただきましてありがとうございました。
switch文の判定により、caseの処理へと、ご教示のとおりコード追加修正後
評価いたしましたところ、見事に、1ずつカウントアップ動作表示する事ができ
大変感激いたしております。
該当のcase定数式をプラス1して、break;よりルーチンを抜けることで、
1回の割込み毎に1桁のみ表示すると言う風に、理解いたしました。
ところが、問題は解決したのですが、自分の中ではまだ、疑問が残ります。
ご回答の中で、修正前のコードでは、なぜ割込みを抜けると3桁目の表示
のままになるのでしょうか?timer1では1秒間のcounterアップよりnumberを1つ変化させるまで、
timer0の方は3.2ms毎の割込み処理を繰返し続けていて、その後number値の変化に対して桁表示式より
各桁を表示するものと考えるのですが、100秒毎に3桁同時に1つインクリメントとなる事に、
どうしても、合点がいきません!
ここのところが、疑問のままでは、これでスッキリとはいきません。
どうか、愚な私に、お許しの範囲で結構ですので、もう少しアドバイス頂けるなら幸いに思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スーパーのレジで並んでいたら...
-
USJでの割り込み
-
PICによる7セグLED3桁制御
-
IRQって何ですか?
-
PIC18F2550の割り込み処理について
-
PICのSleepからの復帰に関して
-
定周期での割り込み
-
PIC 入力端子の監視?
-
電車乗車時、並んでいるのに割...
-
プリントスクリーンの自動化
-
pic 複数の割り込み関数 切り分...
-
一定時間操作がなかったら、と...
-
PICで内部タイマーを使わずカウ...
-
特殊なパターンの人見知りに悩...
-
ストップウォッチ
-
PCの割り込み処理とはなんでし...
-
PIC(MOVFで何故、STATUS Zフラ...
-
PICマイコン 割り込み実行時間...
-
Macターミナルで実行中のプログ...
-
大容量のメモリ確保をスワップ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
スーパーのレジで並んでいたら...
-
電車で待機列の割り込みについ...
-
CPU負荷率の安全な上限と計...
-
駅のトイレでナイチンに邪魔さ...
-
pic 複数の割り込み関数 切り分...
-
CPUの処理量を減らすコーデ...
-
【組込み】割り込み中のstatic...
-
irqbalance って
-
このレジの並び方は間違ってま...
-
VB6でSendKeyを利用したTab移動...
-
USJでの割り込み
-
割り込みのカウントの仕方
-
PICのPWMの正しい使い方につい...
-
マイコン C言語 割り込み処理...
-
VB.net 割り込みの禁止
-
一定時間操作がなかったら、と...
-
電車のドアの前での並び方
-
PIC24F C言語プログラミングに...
-
H8SX/1655のタイマー割り込みに...
-
PICマイコン 割り込み実行時間...
おすすめ情報