Module 74HC595

74HC595 thuộc dòng 74xx595 (xx là ký hiệu có thể khác nhau giữa các hãng) là IC ghi dịch 8bit chốt dữ liệu, đầu vào nối tiếp, đầu ra song song. Dùng để mở rộng cổng ra của MCU (Vi điều khiển) sử dụng giao tiếp SPI. Chúng ta có thể mắc nối tiếp các IC 595 với nhau để mở rộng tùy thích.

74HC595 Pinout

Giao tiếp SPI với IC 595 gồm 3 đường:

VD: Bạn dịch 3bits vào IC, khi có tín hiệu chốt, dữ liệu sẽ được đưa ra ở Qa - Qb - Qc. Chiều dịch dữ liệu là từ Qa đến Qh. Vì vậy nên cần chú ý chiều dịch dữ liệu.

Một số chân chức năng khác trên IC 595:

Sơ đồ vào ra của IC 74HC595

Code tham khảo giao tiếp với 74HC595 trên MSP430 điều khiển led chạy qua chạy lại. Các bạn có thể nhìn trong phần khai báo để nối mạch cho đúng chức năng của từng chân với MCU.

#include <msp430.h>

//Define our pins
#define DATA BIT2 //DS (SER) - P1.2
#define CLOCK BIT4 // SH_CP (SCK) - P1.4
#define LATCH BIT3 // ST_CP (RCK) - P1.3
#define ENABLE BIT6 // OE (G) - P1.6
// The OE pin can be tied directly to ground, but controlling
// it from the MCU lets you turn off the entire array without
// zeroing the register

// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut ( unsigned char );
void enable ( void );
void disable ( void );
void pinWrite ( unsigned int, unsigned char );


int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= (DATA + CLOCK + LATCH + ENABLE);  // Setup pins as outputs
  enable(); // Enable output (pull OE low)

  int i;
  //Do a "ping-pong" effect back and forth
  for(;;){
    for ( i = 0 ; i < 8 ; i++ ){
      shiftOut(1 << i);
      delay(50);
    }
    for ( i = 7 ; i >= 0 ; i-- ){
      shiftOut(1 << i);
      delay(50);
    }
  }
}

// Delays by the specified Milliseconds
void delay(unsigned int ms)
{
 while (ms--)
    {
        __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
    }
}

// Writes a value to the specified bitmask/pin. Use built in defines
// when calling this, as the shiftOut() function does.
// All nonzero values are treated as "high" and zero is "low"
void pinWrite( unsigned int bit, unsigned char val )
{
  if (val){
    P1OUT |= bit;
  } else {
    P1OUT &= ~bit;
  }
}

// Pulse the clock pin
void pulseClock( void )
{
  P1OUT |= CLOCK;
  P1OUT ^= CLOCK;

}

// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut(unsigned char val)
{
  //Set latch to low (should be already)
  P1OUT &= ~LATCH;

  char i;

  // Iterate over each bit, set data pin, and pulse the clock to send it
  // to the shift register
  for (i = 0; i < 8; i++)  {
      pinWrite(DATA, (val & (1 << i)));
      pulseClock();
  }
  // Pulse the latch pin to write the values into the storage register
  P1OUT |= LATCH;
  P1OUT &= ~LATCH;
}

// These functions are just a shortcut to turn on and off the array of
// LED's when you have the enable pin tied to the MCU. Entirely optional.
void enable( void )
{
  P1OUT &= ~ENABLE;
}

void disable( void )
{
  P1OUT |= ENABLE;
}

Khi muốn gửi dữ liệu có độ dài lớn, trong khi thanh ghi của MSP430G2xxx chỉ là 16bits, vì vậy bạn cần cắt dữ liệu thành các đoạn 16bits để gửi đi. Khi tôi gửi 32bits tới 4 IC 74HC595, tôi sẽ phải gửi 2 lần:

#include <msp430.h>

//Define our pins
#define DATA BIT2 // DS
#define CLOCK BIT4 // SH_CP
#define LATCH BIT3 // ST_CP
#define ENABLE BIT6 // OE

// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut(unsigned long, unsigned long);
void enable ( void );
void disable ( void );
void pinWrite ( unsigned int, unsigned char );

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= (DATA + CLOCK + LATCH + ENABLE);  // Setup pins as outputs
  enable(); // Enable output (pull OE low)

  while(1)
  {
    shiftOut(0x0000, 0x003c); //split value from 0x0000003c (32bits)
  }
}

// Delays by the specified Milliseconds
void delay(unsigned int ms)
{
 while (ms--)
    {
        __delay_cycles(1000);
    }
}

void pinWrite( unsigned int bit, unsigned char val )
{
  if (val){
    P1OUT |= bit;
  } else {
    P1OUT &= ~bit;
  }
}

// Pulse the clock pin
void pulseClock( void )
{
  P1OUT |= CLOCK;
  P1OUT ^= CLOCK;

}

//LSB to MSB
void shiftOut(unsigned long val2, unsigned long val1)
{
  //Set latch to low (should be already)
  P1OUT &= ~LATCH;
  char i;
  
  for (i = 0; i < 16; i++)  {
    pinWrite(DATA, ((val1 >> i) & 0x01));
    pulseClock();
  }
  
  for (i = 0; i < 16; i++)  {
    pinWrite(DATA, ((val2 >> i) & 0x01));
    pulseClock();
  }
  P1OUT |= LATCH;
  P1OUT &= ~LATCH;
}

void enable( void )
{
  P1OUT &= ~ENABLE;
}

void disable( void )
{
  P1OUT |= ENABLE;
}