суббота, 14 сентября 2013 г.

74HC595 (сдвиговый регистр) через SPI в C

В этом посте будет рассмотрено сразу две темы: программирование последовательного интерфейса SPI, а также подключение сдвигового регистра 74HC595.
Прежде чем приступать к программированию последовательного интерфейса SPI и подключению сдвигового регистра 74HC595, рекомендую ознакомиться со следующей информацией:
 Итак, нам необходимо подключить к микроконтроллеру ATmega328p семисигментный индикатор, используя всего 3 вывода. Делается это очень просто, при использовании сдвигового регистра 74HC595. Схема подключения представлена на рисунке 1.

Рисунок 1 - Подключение ATmega328p, 74HC595 и семисегментного индикатора 
В данном примере используется индикатор с общим катодом, и подключен по упрощенной схеме, с одним ограничивающим резистором. Минус данной схемы подключения семисегментного индикатора в том, что при увеличении количества светящихся сегментов, их яркость уменьшается. 
Между микроконтроллером и сдвиговым регистром три линии:
  • SCK -> SHCP - сигнал синхронизации
  • MOSI -> DS - данные
  • PB0 -> STCP - сигнал выдачи принятых данных регистром на семисегментный индикатор
Пока на ножке STCP сдвигового регистра присутствует сигнал низкого уровня, на семисигментном индикаторе отображается ранее принятая информация и посылаемые данные в сдвиговый регистр накапливаются в буфере. Как только на ножку HTCP поступает импульс положительной полярности, данные из буфера выводятся на семисегментный индикатор и сдвиговый регистр готов к приему новой информации.

Стоит обратить внимание на то, чтобы младший бит передаваемых в сдвиговый регистр данных D0, соответствовал младшему биту выхода сдвигового регистра Q0, необходимо передавать старший бит первым. В данном примере для простоты, наоборот, старший бит передается последним.
Также хочу обратить внимание на то, что подавать сигнал на ножку HTCP сдвигового регистра стоит только после того, как полностью закончится передача данных, иначе на семисегментный индикатор будет выводится неверная информация.

Приведенная ниже программа, выводящая в цикле цифры 1 и 2, меняющая их каждую секунду.

Текст программы:

#include <avr/io.h> //подключение стандартной библиотеки ввода/вывода 
#define F_CPU 8000000 //частота тактирования 
#include <util/delay.h> //подключение стандартной библиотеки задержки 

void SPI_out(char data);

int main(void)
{
//PORT
DDRB=0xFF; //порт B работает как выход
//SPI
SPCR=0b01110011; //прерывания запрещены, SPI включен, младший бит передается первым, МК ведущий, импульсы положительной полярности, скорость CLK/128
    while(1)
    {
//        abcdefgh (цифра 1)
        SPI_out(0b01100000); //вывод цифры
_delay_ms(1000); //ждем 1с
//        abcdefgh (цифра 2)
SPI_out(0b11011010);
_delay_ms(1000);
    }
}

void SPI_out(char data) //функция вывода цифры на индикатор
{
SPDR=data; //запись в регистр данных SPI
while(!(SPSR & (1<<SPIF))) //ждем окончания передачи по SPI
PORTB |= 0x01; //подаем импульс положительной полярности на вход SHCP сдвигового регистра
_delay_us(100); //ждем 100мкс
PORTB &= ~0x01; //снимаем импульс положительной полярности со входа SHCP сдвигового регистра
}