7セグメントLEDを使う
ワンセグというのが流行(はやり)ですが、こちらは7セグです
一般の、あのワンセグとは何の関係もありません)
棒状のLEDが7コ、 8の数字に配置された、数値を表示するための表示器 です。
この7本の棒状LEDの、どれかを点灯させ、どれかは点灯させない ことで 数値の形を作り出す表示器です。
今やLCDの液晶表示器が安価になったので、数値だけの表示でもこれが使われるここが多いです。できるなら配線が少ないのでLCDを使いたいところです^^
それでも7セグLEDを使う理由として
やはりLEDで作り出す文字は、なんとなくイイ!
バックライト付きのLCDを使っても、7セグ表示の感じはなんか違っていて、
数値の表示 : 時計、温度、回転数など
数値の表示はやっぱりこれにしたい!と思ってしまいます。
LCD液晶 も 7セグLEDも同じ、数値が表示できる表示器ですが、マイコンなどで表示器として利用を考えると一長一短です
●LCD液晶
- 【長所】
- 字もアルファベットもいっぱい表示できる。
配線が簡単
表示器に外部回路も込みになっているので簡単 - 【短所】
- 文字が小さい、見にくい
最初の表示のルーチンを作るまで労力がかかる。
●●7セグメントLED
- 【長所】
- 長所が少ないんですが、
やっぱり数値はこれでないと
IOポートの簡単な処理だけで数値表示できる。
かなり大きな表示もできる
(大きな7セグ表示器はあるので)
数値が発光するので遠くからでも見やすい - 【短所】
- ほとんど数字だけしか表示できない
配線が大変、外部回路もなかなか作るの大変。
(外部回路込みの7セグもありますが、あまりみかけません)
7セグ1つで1桁の表示(何桁かつながった7セグもありますが)
ネットでもあちこちに解説記事があり、今更という感じですがH8を使い7セグで数値表示をしました。
基本はLEDを点灯、消灯させる操作なので、いままでで実験済みですが、配線やピンを減らす工夫などの方法を使っています。
7セグLED
7セグLEDは 単に棒状のLEDが7本(ついでに小数点の .(DF) が付いていたりもする)を点灯、消灯させるだけです。
共通端子が 電源部かGND部かで
アノードコモン、カソードコモンといわれるタイプがあります。
図のA~G 7本全部を点灯させれば、8 の数値になる、
各ピンと各部LEDをつなぎ、いくつかを点灯させれば数値に見えるので、LEDの点灯操作と同じです。
ただ、そのままやると
1桁で7本の I/Oピンが必要。。。2桁になると14本 、 3桁で・・・・・
H8/3664F、3694F などはマイコンとしてはPICなどよりIOピン数が多い方ですが、数値の表示だけにこれだけのピンを取られるとキビシいです。
1桁ぐらいなら7本なのでなんとか、、、でも
数値3桁ぐらいの表示は通常必要なので 7本×3桁= 21本ちかくのピンが。。。
こんなピン数を使った配線でやることは実際はそうないです、そこで以下の方法でマイコンからのピン数を減らす工夫をします。
★ ピンを減らす工夫 ★
7本を4本に減らす デコーダIC
1桁は9までなので、それを2進数で表すと、4桁の2進数になります
つまり 4桁 → 4ビット → 4本のIOピン使用
4ビットで0~9までの数値が表せるので、マイコンでは4本のIOピンを使いH,Lの出力をだし、途中で、デコーダICを使い0~9までの数値用に変換して、7セグを光らせる各ピンの信号にするという方法です。
2進数→10進数に変換することをデコード(その逆がエンコード)と呼ばれるので、デコーダICを使用します。
74LS47を使用しました。
(デコードと難しそうですが、、実際はピン節約するだけなので 4ビットのH,Lの組み合わせで表示に必要な7本のLEDのどれかを光らせるH,L信号になったらいいんです。PICとかでも、4ビットの入力を受けて足から7ビットH,L出力するだけなので出来ます)
- アノードコモンの7セグでは 74LS47、247のようなIC
- カソードコモンでは4511 のようなICが使われることが多いです。
★ 桁数での工夫 ★
ICを間に使うと、1つの7セグで4本(4ビット)のピンで数値が出来るようになりました。
でも、桁数が増えると 4×桁数で なかなかの数のピン数が必要になります。
そこで 桁数が増えても、IOピンを減らす工夫として
ダイナミック点灯
ダイナミック点灯 といわれる方法がよく使われています。
これは全部の桁表示器をつないでしまい、いっぺんに同じ数値を表示させる方法です。
ダイナミック点灯の説明
表示器を全部横につないでしまうと、全桁 同じ数値が表示されます
全部の桁 同じ数値を表示してどうするんだ? と思いますが、
例えば
”21” という2桁の数値なら
それぞれ、 2 1 と 各桁違う表示でなく、表示器を全部つなげているので
まず1を表示させると 全桁 同じ数値
1,1 と全部の桁が表示になる。
そこで、通電で 最初の桁しか表示しないように、1桁目だけ表示されるようにします。
2桁目 1桁目 1
次に 2を表示させると 全桁 同じ数値
2,2 と全部の桁が表示になるが、2桁目だけを表示させる。
すると
2桁目 1桁目 2
これを瞬時に高速で切り替えて表示すると
2桁目 1桁目 2 1
連続した数値に見える という残像の表示方法です。
これだと、全桁つながっているので、数値の表示には デコーダICで節約して4本
そして、各桁を表示させられるように、各桁の通電のON、OFF制御に 1本 ×桁数
4本+桁数 だけのI/Oピン数だけで7セグでの数値ができます。(3桁だと 4+3で7本)
このダイナミック点灯は、桁数が増えるとピン数がドンと増えてくるので、必要度が高い方法です。
でも、途中のデコーダICで 7本→4本にへりましたが、3本減ってる(節約できた)だけですね。 (デコーダIC使わなくても 7本+桁数 だけのI/Oピン数でいける)
この 途中のデコーダIC回路を作るコト と 3本のピンが減らせるコト 天秤にかける必要があります
(もちろん、このICにも ちょっとした7セグ表示用の付加機能はありますが)
IOピンに余裕があるなら、デコーダICで数本だけ減らす回路は無くてもいいかもしれません
回路
LCD表示は、一度作れば多桁の数値なんて簡単に表示できるのに較べ、
さすがに配線作業がとても大変でした。
アノードコモンの7セグ
デコーダICに 74LS47
各桁通電ON,OFFに Tr 1085 を使用した回路
Trの通電切り替えは作ったテストボードで使用できるIOポートの関係から、とびとびの違うポートになってしまってます。
本来 入力の A0~A3 などは5k~10kΩ程度でプルアップすべきです。(お行儀よく、しておきましょう)
プログラム
まず、テストに簡単に数値を流すプログラム
FQ_7seg_TmA
/*タイマAの割り込み関数による 7セグLED点灯
タイマAの設定値を変えることで
TA.TMA.BYTE=0x09; 低速切替え
TA.TMA.BYTE=0x0B; 中速切替え
TA.TMA.BYTE=0x07; 高速切替え
ダイナミック点灯の切り替え速度体感
*/
#include <3664.h>
int f;
void int_timera (void){
switch(f){
case 0 : //1桁目通電 表示
IO.PDR2.BYTE = 0x00; //#0 →LOW吸い込み通電 0000 0000
//2桁目以降 非表示
IO.PDR1.BYTE = 0x30; //#4-5 →HIGH 0011 0000
f+=1;
break;
case 1 : //2桁目通電 非表示
IO.PDR2.BYTE = 0x01; //#0 →HIGH 0000 0001
//2桁目 表示
IO.PDR1.BYTE = 0x20; //#4 →LOW吸い込み通電 0010 0000
f+=1;
break;
case 2 : //3桁目通電 非表示
IO.PDR2.BYTE = 0x01; //#0 →HIGH 0000 0001
//2桁目 表示
IO.PDR1.BYTE = 0x10; //#5 →LOW吸い込み通電 0001 0000
f=0;
break;
}
IRR1.BIT.IRRTA=0; // 検知フラグを戻して再開
}
int main(){
IO.PCR8 =0xFF; // ポート出力に設定(#0-3だけ使用) 0000 1111
IO.PCR1 =0xFF; // ポート出力に設定(#4-5だけ使用) 0011 0000
IO.PCR2 =0xFF; // ポート出力に設定(#0だけ使用) 0000 0001
TA.TMA.BYTE=0x09; /* 低速切替え 時計用クロック 時間0.5s 0000 1001 */
// TA.TMA.BYTE=0x0B; /* 中速切替え 時計用クロック 時間0.31s 0000 1011 */
// TA.TMA.BYTE=0x07; /* 高速切替え 高速クロック 時間φ/8 0000 0111 */
IRR1.BIT.IRRTA=0; /* タイマーA割込みフラグのリセット */
IENR1.BIT.IENTA=1; /* タイマーA割込みを利用可能にする */
//数値
IO.PDR8.BYTE = 0x03;
f=0; //case値 初期化
EI; //割り込み許可
while (1) ;
}
同じ数値を各桁ごとにタイマーAの割り込みを使い、0.5秒ごとに流れる表示
(タイマーAの設定については 以前のタイマーALED点灯記事を参照してください)
単純ですが、数字が順に流れる・・・これだけでなんか楽しい!
数値表示というより、光りモノ工作なところが楽しめます。LCD液晶表示でこんなことをしてもおもしろいと感じませんが、これがLEDなところかもしれません。
わかりやすくcase分岐を使って0~2で、各桁の7セグの通電ON、OFFを切り替え、表示と非表示にしました。
【改良実験】
切り替え速度を早め
タイマAの時間設定を 0.5s → 0.3125S
TA.TMA.BYTE=0x0B; /* 時計用クロック 時間0.3125s 0000 1011 */
にすると表示がチラつきますが、ほぼ連続した数値になって見えるのがわかります。
さらにもっと高速に
高速クロック使用 φ/8 にすると
TA.TMA.BYTE=0x07; /* 高速クロック 時間φ/8 0000 0111 */
ちらつき無く表示されているのがわかります。
少しずつ切り替え速度を上げると、ダイナミック点灯がよくわかります。
3桁数値の表示
3桁の任意の数値を表示してみます。
Q_7seg_NumTmA
/*タイマAの割り込み関数による7セグLED点滅
_7seg_out(数値)で入力された 3桁の数値を
_7seg_out関数で各桁に分解し 各桁の数値を strtemp[0-2]へ入力
タイマーAのcase分岐0-2で 各桁をダイナミック点灯表示する
2桁目、3桁目の表示には 頭に不要なゼロがあるとき非表示にする処理
*/
#include <3664.h>
int f;
unsigned char strtemp[3]; // 各桁格納配列
unsigned char num[10]; // 7seg数値データ変数
void _7seg_out( short data ) // 数値データを各桁にする関数)
{
unsigned char temp; // 格納変数を定義
int i;
for(i=0;i<4;i++){ strtemp[i]=0; } // 各桁格納配列初期化
i=0;
do {
temp = data % 10; // 下位の桁から数字を抽出
strtemp[i++] = temp; // 配列へ格納
} while (( data /= 10 ) != 0); // 数値の桁数までループ
}
void int_timera (void){
switch(f){
case 0 :
//数値
IO.PDR8.BYTE = num[ strtemp[f] ];
//1桁目 表示
IO.PDR2.BYTE = 0x00; //#0 →LOW吸い込み通電 0000 0000
//2桁目以降 非表示
IO.PDR1.BYTE = 0x30; //#4-5 →HIGH 0011 0000
f+=1;
break;
case 1 : //数値
IO.PDR8.BYTE = num[ strtemp[f] ];
//1桁目 非表示
IO.PDR2.BYTE = 0x01; //#0 →HIGH 0000 0001
//2桁目 表示
if( (strtemp[f+1]==0) && (strtemp[f] ==0) ){ IO.PDR1.BYTE = 0x30;}
//#4,5 → HIGH 頭のゼロ 非表示
else{ IO.PDR1.BYTE = 0x20; } //#4 →LOW吸い込み通電 0010 0000
f+=1;
break;
case 2 : //数値
IO.PDR8.BYTE = num[ strtemp[f] ];
//1桁目通電 非表示
IO.PDR2.BYTE = 0x01; //#0 →HIGH 0000 0001
//3桁目 表示
if(strtemp[f] ==0 ){ IO.PDR1.BYTE = 0x30;}
//#4,5 → HIGH 頭のゼロ 非表示
else{ IO.PDR1.BYTE = 0x10; } //#5 → LOW吸い込み通電 0001 0000
f=0;
break;
}
IRR1.BIT.IRRTA=0; // 検知フラグを戻して再開
}
int main(){
long testI;
IO.PCR8 =0x0F; // ポート出力に設定(#0-3だけ使用) 0000 1111
IO.PCR1 =0x30; // ポート出力に設定(#4-5だけ使用) 0011 0000
IO.PCR2 =0x01; // ポート出力に設定(#0だけ使用) 0000 0001
TA.TMA.BYTE=0x07; /* 高速クロック 時間φ/8 0000 0111 */
IRR1.BIT.IRRTA=0; /* タイマーA割込みフラグのリセット */
IENR1.BIT.IENTA=1; /* タイマーA割込みを利用可能にする */
f=0; //case値 初期化
num[0] = 0x00; //数値データ
num[1] = 0x01;
num[2] = 0x02;
num[3] = 0x03;
num[4] = 0x04;
num[5] = 0x05;
num[6] = 0x06;
num[7] = 0x07;
num[8] = 0x08;
num[9] = 0x09;
EI; //割り込み許可
//表示数値
_7seg_out(719);
for(testI=0; testI<800000; testI++); //しばらく待つ
_7seg_out(3);
for(testI=1; testI<800000; testI++);
_7seg_out(90);
for(testI=1; testI<800000; testI++);
_7seg_out(361);
for(testI=1; testI<800000; testI++);
_7seg_out(842);
EI; //割り込み許可
while (1) ;
}
7seg_out(719) の部分に表示する数値を入れます。
各桁に分解して配列に入れ、通電on,off の操作をしています。
num[0] = 0x00; //数値データ
は16進数にしていますが、普通に10進数でも大丈夫
頭に不要なゼロがある場合
003 030 のような場合
003 → 3
030 → 30 のように
頭のゼロを非表示にする処理を加えてあります。
実行はテスト用に
for(testI=0; testI<800000; testI++); //しばらく待つ
_7seg_out(3);
・
・
と、違う数値をしばらく表示して、いくつかの数値が切り替わって表示されるようになってます。
- twtter
- google+
- hatena