
HOME >> LED電子工作集 > PICマイコンとC言語の勉強 P-7 3桁の数字を表示させる
■ はじめに
今、PICマイコンとC言語の勉強に挑戦している。 そのいきさつは、鉄道模型工作実験室 の別室ブログ 「レイアウトに速度計を設置しよう」 ( 2019/2/22 )にて紹介しているので参照ください。
学習の第2ステップとして、測定データを表示させるための7セグメントLEDと、新しくPIC16F1827 マイコンの取り扱い方を学ぶことにする。 今回は、セグメントに3桁の数字を表示させよう。
■ 7セグメントLEDの注意点
使用している7セグメントLED C-533SR-A の回路図はカタログより抜粋して下記に示す。

この回路からも分かるように、一度の全部のセグメントを点灯させると大きな電流が必要となり、PICマイコンの許容電流を大きく上回ってしまうのだ。 ひと桁の表示であれば対応できるのだが、3桁では無理なので、それぞれ個別に素早く順番に点灯させるのである。 これをダイナミック点灯方式と呼ぶそうである。
点灯するセグメントを制御するには、上記のカソードコモン方式であれば、それぞれのカソードの回路をON/OFF制御すれば良いのである。 多数のLEDから流れた来た大きな電流を一つのスイッチでON/OFF させるために、トランジスタを使用してスイッチとしています。 このための回路を下に示す。

/*****************************************
* 7segLED Test 3
* 2019/2/28
* PIC16F1827 MPLAB X XC8
******************************************/
( 途中省略 )
int ct; //表示する数の更新間隔
long val; //表示する数の値
int digit; //表示する桁位置
int segment_data[]= {0xDE,0x42,0x5D,0x57,0xC3,0x97,0x9F,0xD2,0xDF,0xD7};
//表示する数字のパターンの行列
char st[3]; //表示する桁の数字、3個の行列
void main()
{
OSCCON = 0b01110010; //内部クロックを8MHzに設定
ANSELA = 0b00000000; //全てデジタルI/O
ANSELB = 0b00000000; //全てデジタルI/O
TRISA = 0b00000000; //全て出力
TRISB = 0b00000000; //全て出力
PORTA = 0b00000000; //出力ピンをすべてLOWにする
PORTB = 0b00000000; //出力ピンをすべてLOWにする
digit=0; //初期値の設定
ct=1;
val=0;
while(1){ //ループ処理
ct --; //更新間隔をカウントダウン
if(ct == 0){ //表示桁への振り分け
st[2]=val/100; //100の位の数字
st[1]=val/10-st[2]*10; //10の位の数字
st[0]=val%10; //1の位の数字
val ++; //表示する数をカウントアップ
if(val==1000) val=0; //999以上になったら0にする
ct=20; //更新間隔をリセット
}
if(digit==2){ //100の位の数字を表示させる
PORTA = segment_data[st[2]]; //出力ポートに指示
RB1 = 1;
__delay_ms(5); //5msec表示
RB1 = 0; //表示を消す
__delay_us(100);
}
if(digit==1){ //10の位の数字を表示させる
PORTA = segment_data[st[1]];
RB2= 1;
__delay_ms(5);
RB2 = 0;
__delay_us(100);
}
if(digit==0){ //1の位の数字を表示させる
PORTA = segment_data[st[0]];
RB3 = 1;
__delay_ms(5);
RB3 = 0;
__delay_us(100);
}
digit ++; //表示する桁をカウントアップ
if(digit ==3) digit=0; //3になったら0に戻す
}
}
■ プログラムの作成
今回は、「Maicommon.ciao.jp TOP」/「自学のページ」/PIC入門/表示回路/数字3桁表示のページを参考にしました。 さる大学のゼミに使用されていた資料と推察する。 使用しているPICマイコンも異なるし、コンパイラも CCS C であったので記述方法がかなり異なっていました。
しかし、記述の考え方は理解出来たので、小生が使用している状態に書き換えて記述し直しました。 実行している内容は同じであり、変数も同じ記号を使用しています。
● ロジックのポイント
作成したプログラムを右に示す。 コンフィグ等の設定は先回と同じなので省略しています。
◆ お詫びと訂正
プログラムの一部に間違いがありました。 点灯させるLEDの指定方法がトライ時に実施したままのデータを流用してしまいました。
実際には右の様に修正ずみです。 お詫びして訂正いたします。
■ 動作状態
ブレッドボードに構成した回路状態と動作状況を紹介します。
ジャンパー線がジャングルの様になってしまいました。 動作状態を動画で紹介します。
電源は5ボルトのACアダプタから供給しています。 表示はスムースの実行されていますが、セロの数字が先頭にくる場合は表示しないように工夫する必要がありますね。
これで数字の表示方法まで学習しましたので、次は最大の難関である時間計測に取り掛かります。 以前に報告した「レイアウトに速度計を設置する」では、Arduino を使用しましたが、その場合では、
t1 = millis();
while (slit2 == HIGH) {
slit2 = digitalRead(SLIT2_PIN) ;
}
t2 = millis();
tt = t2 - t1 ;
V =108000 / tt ;
これだけの記述で、二つのスリットを通過する時間を計測し、スケールスピード V を計算することが出来たのですが・・・・・・・・。