アプリ版:「スタンプのみでお礼する」機能のリリースについて

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){}
}
////
以上宜しくお願いいたします。

A 回答 (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つだけという状態になってます。
    • good
    • 0
この回答へのお礼

評価に則したご回答頂き、ありがとうございます。
もう一度ハード側をじっくり眺めていると、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桁同じ表示のまま。
と言う風に自分で解釈一応溜飲が下がり完結となりましたので
ありがとうございました。

お礼日時:2010/04/29 11:11

タイマー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つインクリメントとなる事に、
どうしても、合点がいきません!
ここのところが、疑問のままでは、これでスッキリとはいきません。
どうか、愚な私に、お許しの範囲で結構ですので、もう少しアドバイス頂けるなら幸いに思います。

補足日時:2010/04/25 22:15
    • good
    • 0

ソフトウェア的には問題なさそうですが、ハードウェア側はどうなっていますか?



質問のような状況からすると、LEDが3桁ともC2で駆動されてるように見受けられます。
    • good
    • 0
この回答へのお礼

お目に留めていただき、ご回答ありがとうござました。
ハードウェア的には、問題ない、とは言い切れませんが
delay()関数を使った3桁表示テストでは、プログラムどおり
動作できましたので、ハードは問題ないのではと判断しています。
3桁同時表示の問題が今一つ解決出来ていません。

お礼日時:2010/04/25 22:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!