作成日時:2015年11月01日 20時52分56秒
更新日時:2020年05月19日 08時33分35秒
この記事は9年ほど前に投稿されました。内容が古くなっている可能性がありますので更新日時にご注意ください。
コレで基本的なシフトレジスタの使い方はわかりましたが、今回はその応用として「シフトレジスタを連結する」という使い方をしてみたいと思います。
用意するもの
- 1つ以上の7セグLED もしくは 2桁以上の7セグLED(カソードコモン)
- NPNトランジスタ(2SC1815もしくは同等品) 桁数分
- 何らかの抵抗 8本+桁数分
- 74HC595 2個(今回は595のQH’端子を使うので必ず595を使う)
74HCはマスターとなる1つ目のICを7セグドライバとして使い、それに繋がるICを桁切り替え用として使います。よって、必ず2つ以上のICが必要になります。
解説
前回少し触れましたが、74HC595には、ビットをシフトする際に現在レジストされている最上位(QH)のビットを常に吐き出し続けるQH’というピンが有ります。このピンの入力を別の595のSIに流してやることで、IC1つ分のIOコネクタで幾つもの7セグLEDを制御できます。 「いくつも」と言っても多くすると切り替えに時間がかかりますし、データ処理も大変になりますので実用的には4バイト以内で制御できる24桁以内に収めておいたほうがいいでしょうね。
回路図
今回はカソードコモンのLEDを使用していますので、NPNのトランジスタで制御しています。
4桁以上ならトランジスタアレイを使うともう少し簡単にできるでしょう。
各部の抵抗は、トランジスタ側は4.7kΩを使う場合が多いようですが、何らかの抵抗が入っていればOKらしいです。LED側の抵抗は、使用する7セグLEDの仕様に合わせて、欲しい明るさが出せるように抵抗値を決定してください。
ちなみにコレはダイナミック点灯ですが、とほぼおなじ部品で「スタティック点灯」も作れます。
回路はこんな感じ↓ですが、基本的には前回のものをつなげただけとなります。
ただしスタティック表示の場合は消費電力が大きいので、4桁程度におさめておくといいかもしれません。(もしくは別電源を取るか。)なお、この回路図ではトランジスタは省いていますが、上のようにトランジスタを付け、ICに繋いでいるピンをVccにつなぐことで数字による輝度変化がありません。
制御
※ブレッドボード用部材の都合上、右のICがマスターとなっています。
今回は下位8bitで7セグLEDを制御し、上位8bitでどの桁を光らせるかを決めます。
1つめのIC | 2つめのIC | |||||||||||||||
ビット数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
595ピン名称 | QA | QB | QC | QD | QE | QF | QG | QH | QA | QB | QC | QD | QE | QF | QG | QH |
LEDの接続先 | A | B | C | D | E | F | G | DP | 1桁 | 2桁 | 3桁 | 4桁 | 5桁 | 6桁 | 7桁 | 8桁 |
上位ビットから転送しているのでこうなります。ドットを使わないのなら2つのICで最大9桁制御できますね。
また、DPを使わない場合、このICはQAが対岸にいるので7桁以内ならQAを使わなければ少し配線が楽になります。
転送の方法は基本的にはシフトレジスタの回と複数桁7セグ制御の回でお伝えしたとおりです。
プログラム
桁指定と7セグデータ、ドットの有無を統合して設定します。
計算式は
(0x0100<<dig)+(seg[num])+(0x80*dot);
digが桁、numが表示させたい数字、dotがドットの有無(0=なし1=あり)、
seg変数に7セグLEDのパターンを定義します。ちなみにカソードコモンのこの方法で行う場合は
int seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
(0x0100<<dig) は2バイト目の1bit目が1になる式をビットシフトしています。digはゼロから始めるべきなのでの数値は-1しておいてください。
(seg[num]) は実際の7セグデータを転送します。()で囲う必要はありませんが。
(0x80*dot)の部分は掛け算でドットの有無を代入しています。
例えば digが1、numが7、dotが1の場合は 0x0187
digが2、numが8、dotが0の場合は 0x027f という感じになります。
コレを前回、7セグにデータを転送した要領や、SPI命令を使用して転送します。
以下、完成コードを載せておきます。
#include <stdio.h>
#include <wiringPi.h>
#include <pthread.h> // マルチスレッド化
// データ転送用ピンの設定
// 12=MOSI 14=SCLK 10=CE.0 なのでこのピン指定なら
// SPIの命令で制御できる。
#define RegPut 12 // データ転送用ピン
#define RegClk 14 // クロック信号用ピン
#define RegCS 10 // ラッチ信号用ピン
#define DataLen 16 // データ長
int LedSend(char,char,char);
int n,send_num;
int seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void* LED_SND(void* args){
while(1){
int n=send_num,n1=0,n2=0,n3=0;
n3 = (n%10);n/=10;
n2 = (n%10);n/=10;
n1 = (n%10);n/=10;
LedSend(1,n3,1);
delay(1);
LedSend(2,n2,0);
delay(1);
LedSend(3,n1,0);
delay(1);
}
}
void main(void){
wiringPiSetup();
int i=16;
while(i--){pinMode(i,OUTPUT);delay(1);}
pthread_t led_th;
pthread_create(&led_th,NULL,LED_SND,(void *)NULL);
while(1){
delay(100);
send_num++;
if(send_num==1000)send_num=0;
}
}
int LedSend(char dig,char num,char dot){
dig--;
int data=(0x0100<<dig)+(seg[num])+(0x80*dot);
n=DataLen;
digitalWrite(RegCS,0);
while(n--){
digitalWrite(RegPut,(data>>n)&1);
digitalWrite(RegClk,0);digitalWrite(RegClk,1);
}
digitalWrite(RegCS,1);
}