Pages

CD74HC595 8-BIT SHIFT REGISTER SEVEN SEGMENT DISPLAY UYGULAMASI (STM32/ARDUINO)


Bu yazımda yapmış olduğum uygulamamda kullandığım shift register hakkında biraz bilgi verdikten sonra Arduino ve Discovery tarafında yazmış olduğum örnek kodları aktaracağım.


74HC595 Entegresi

Yukarıda ve başlıkta yazıldığı üzere hc595 entegresi bir shift register entegresidir. Peki shift register nedir ve ne işe yarar ? 

Shift register'lar mikrodenetleyicilerde bulunan sınırlı sayıdaki giriş / çıkış (I/O) pinlerini çoğaltmak amacı ile kullanılırlar. Giriş ve çıkış çoğaltmak için çeşitleri bulunmakta olan bu entegreler mikrodenetleyici üzerinde daha az sayıda pin harcayarak daha fazla giriş veya çıkış pinine sahip olmamızı sağlar. 8 bitlik bu entegre bize 8 farklı çıkış pini sağlar.

-    8 Bit Serial-In, Parallel-Out Shift (SIPO)
-    2V - 6V voltaj aralığı. (Önerilen 5V - gürültü bağışıklılığı)
-    ±6-mA çıkış (5V)

Nasıl Çalışır ?

Shift register'a saat sinyali gönderdiğimizde shift register'daki bitler birer adım kayar ve bunu çıkışta gözlemlemek için arkasından latch pinini düşükten yüksek konuma çekmemiz gerekir. Darbenin yükselen kenarında veri pini yüksekse, shift register'ın bitine 1 gönderilir ve diğer bitler birer bit kayar. Aksi durumda 0 iletilir ve bitler yine kayma işleminni gerçekleştirir.

Latch pini yüksek konuma çekildiğinde, shift register'ın içeriği Storage/latch Register adı verilen ikinci kayıt birimine taşınır. Storage Register'ın her bir biti entegrenin çıkış aldığımız pinlerinden birine bağlıdır. Buradaki değerler değiştiğinde çıkıştaki değerler de değişir.







KiCad üzerinde yapmış olduğum, entegrenin display ile bağlantısı ve mikrodenetleyiciye giden bacakların bağlantılarını yukarıdaki şematikte görebilirsiniz. Dokuzuncu bacak iki entegrenin birbirine bağlanmasını sağlamaktadır.  Bu sayede çıkış sayısını 8'den 16'ya çıkarma imkanı vardır. SRCLR bacağı ise register'ı temizleme bacağıdır. 10k'lık bir direnç ile 5V'a çekilmesi gerekir. Aksi takdirde bağlantı yapılmadığı durumda çıkışta herhangi bir şey gözlenemez.

  • GND : Mikrodenetleyici kartının toprağına bağlanmalıdır.
  • VCC : Mikrodenetleyicinin 3.3V veya 5V pinine bağlanmalıdır.
  • SER : Seri data'nın birer bit olarak yüklenmesi sağlanır.
  • SRCLK : Verilerin saatin yükselen kenarında register'a aktarılmasının sağlar.
  • RCLK : (Register Clock / Latch) : Yüksek konuma geçtiğinde shift register'ın içeriği storage/latch register'ına kopyalanır yani çıkışa aktarılmış olur. Çıkış almanın son adımı olarak değerlendirilebilir.
  • SRCLR : Register'daki tüm bitleri sıfırlamaya yarar. Sıfırlama için düşük konuma çekilmesi gerekir. Sıfırlama gerekmediğinde yüksek konumda olmalıdır.
  • OE : Negatif logic bir pindir. Üzerindeki voltaj yüksek olduğunda, çıkış pinleri devre dışı bırakılır. Çıkış pinlerini kullanmak için düşük konumda tutulmalıdır.
  • QA - QH : Çıkış alınan pinlerdir. İstenilen çıkışlara bağlanacak pinlerdir.
  • QH' : Shift register'ın 7. bitini çıkarır. Entegrelerin birbirine bağlanmasını sağlar. İki ile sınırlı değildir, yeterli besleme ile istenildiği kadar çok sayıda entegre birbirine bağlanabilir.

Arduino'da hazır bulunan shiftOut fonksiyonu ile gerekli pin tanımlamalarını yaparak hc595 rahatlıkla kullanılabiliyor. STM32 Discovery kartında ise hazır bir fonksiyon bulunmadığı için Arduino'daki shiftOut fonksiyonunu uygun şekilde yazarak aynı örneği STM32 mikrodenetleyicisi ile de gerçekleştirmiş oldum. Her ikisinin de kodunu aşağıda görebilirsiniz. STM32 tarafında HC595_Init fonksiyonu harici pin makrolarını dikkate alarak birebir kendi kodunuza direkt kopyalayabilirsiniz. Init kısmında kendi kartınıza göre uygun registerlar ile veya CubeMX üzerinden çıkış ayarlarını yapılandırıp sizde uygulayabilirsiniz. 

Arduino Kodu

const int serialData = 6;
const int shiftClock = 7;
const int latchClock = 8;

int Common_Cathode[10] = {0x3F, 0x06, 0x5B, 
          0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void setup() {
  pinMode(shiftClock, OUTPUT);
  pinMode(latchClock, OUTPUT);
  pinMode(serialData, OUTPUT);
}

void loop() {

  for (int i = 0; i < 10; i++)
  {
    shiftOut(serialData, shiftClock, MSBFIRST, Common_Cathode[i]);
    digitalWrite(latchClock, HIGH);
    delay(1000);
    digitalWrite(latchClock, LOW); 
 
  }
}


STM32 Kodu 

#include "main.h"
#include "hc595.h"


void SystemClock_Config(void);
static void MX_GPIO_Init(void);


int main(void)
{

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  HC595_Init();


  while (1)
  {

	  for (int i = 0; i < 10; i++)
	  {
		  shiftOut(MSBFIRST, Common_Cathode[i]);
		  toggleLatch();
		  HAL_Delay(500);
		  toggleLatch();
	  }


  }

}
#include "hc595.h"


uint8_t Common_Cathode[10]  = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 
				0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void HC595_Init(void)
{

	RCC -> APB2ENR |= (1<<2);
	GPIOA -> CRL   |= (1<<24) | (1<<25) | (1<<28) | (1<<29);
	GPIOA -> CRL   &= ~(1<<26) & ~(1<<27) & ~(1<<30) & ~(1<<31);
	GPIOA -> CRH   |= (1<<0) | (1<<1);
	GPIOA -> CRH   &= ~(1<<2) & ~(1<<3);

}


void shiftOut(uint8_t bitOrder, uint8_t data)
{
	uint8_t shifter;

	for(shifter = 0; shifter < 8; shifter++)
	{

		if(bitOrder == LSBFIRST)
		{
			if( (data & (1<<shifter)))
			{
				GPIOA->BSRR = DATA_PIN;
			}
			else
			{
				GPIOA->BSRR = (uint32_t)DATA_PIN << 16;
			}
		}
		else
		{
			if((data & (1<<(7 - shifter))))
			{
				GPIOA->BSRR = DATA_PIN;
			}
			else
			{
				GPIOA->BSRR = (uint32_t)DATA_PIN << 16;
			}
		}


		GPIOA->BSRR = CLOCK_PIN;
		GPIOA->BSRR = (uint32_t)CLOCK_PIN << 16;

	}
}

void toggleLatch(void)
{
	if(GPIOA -> IDR & LATCH_PIN)
	{
		GPIOA->BSRR = (uint32_t)LATCH_PIN << 16;
	}
	else
	{
		GPIOA->BSRR = LATCH_PIN;
	}

}
#ifndef INC_HC595_H_
#define INC_HC595_H_

#include "stm32f1xx_hal.h"


#define		DATA_PIN		GPIO_PIN_6
#define		CLOCK_PIN		GPIO_PIN_7
#define 	        LATCH_PIN		GPIO_PIN_8

extern uint8_t Common_Cathode[10];


typedef enum{

	LSBFIRST = 0,
	MSBFIRST =1

}Bit_Order;

void HC595_Init(void);
void shiftOut(uint8_t bitOrder, uint8_t data);
void toggleLatch(void);



#endif /* INC_HC595_H_ */

Emre Aytur

Gömülü Sistemler, Elektronik, Teknoloji