さくらのジャンク箱ロゴ

Sakura87がほぼ月刊でお届けするPCや電子工作と写真の備忘録てきなブログ @なんと20周年

Raspberry Pi 2 で複数桁の7セグLED制御(3) シフトレジスタを使用する

この記事は9年ほど前に投稿されました。内容が古くなっている可能性がありますので更新日時にご注意ください。

IMG_6911

前回シフトレジスタを使って7セグLEDの制御をしました。

コレで基本的なシフトレジスタの使い方はわかりましたが、今回はその応用として「シフトレジスタを連結する」という使い方をしてみたいと思います。

用意するもの

  • 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桁以内に収めておいたほうがいいでしょうね。

回路図

74hc7segs2

今回はカソードコモンのLEDを使用していますので、NPNのトランジスタで制御しています。
4桁以上ならトランジスタアレイを使うともう少し簡単にできるでしょう。

各部の抵抗は、トランジスタ側は4.7kΩを使う場合が多いようですが、何らかの抵抗が入っていればOKらしいです。LED側の抵抗は、使用する7セグLEDの仕様に合わせて、欲しい明るさが出せるように抵抗値を決定してください。

ちなみにコレはダイナミック点灯ですが、とほぼおなじ部品で「スタティック点灯」も作れます。
回路はこんな感じ↓ですが、基本的には前回のものをつなげただけとなります。

hc74595_7segstatic

ただしスタティック表示の場合は消費電力が大きいので、4桁程度におさめておくといいかもしれません。(もしくは別電源を取るか。)なお、この回路図ではトランジスタは省いていますが、上のようにトランジスタを付け、ICに繋いでいるピンをVccにつなぐことで数字による輝度変化がありません。

制御

IMG_6911

※ブレッドボード用部材の都合上、右の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);
	}
	
	

 

総閲覧数:543 PV

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください