Урок 26
SPI. Подключаем LED индикатор
Продолжаем работать с шиной SPI. На прошлом занятии мы научились работать со сдвиговым регистром 74HC595.
Сегодня мы также продолжим работать с данным регистром, но сегодня мы попытаемся подключить к нему светодиодный семисегментный одноразрядный индикатор.
Я думаю, это будет выглядеть интереснее, чем бегущие огни по светодиодной планке.
Общий анод индикатора мы подключим к шине питания, а сегменты — к регистру через токоограничивающие резисторы вот таким вот образом
Управляющие входы регистра остались без именения подключенными таким же образом, как и в прошлом занятии.
У моего индикатора, который я подключил, вот такая вот распиновка
На практике всё выглядит приблизительно вот так
Проект создан был с именем SPI_LED, код был полностью весь взят с прошлого занятия с целью, чтобы нам избежеть первоначальных настроек и настроек инициализации.
Если мы сейчас в протеусе включим наш проект на выполнение, то у нас будет работать прошлый код, только те сегменты, которые светились в прошлом занятии, наоборот светиться не будут, так подключены у нас светодиоды в обратном порядке и не на общую шину, а на шину питания
До бесконечного цикла код в функции main() будет вот таким
int main(void)
{
DDRB |= ((1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5)); //ножки SPI на выход
PORTB &= ~((1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5)); //низкий уровень
SPCR = ((1<<SPE)|(1<<MSTR));//¬ключим шину, объ¤вим ведущим
SPDR = 0b00000000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
while(1)
То есть мы здеь оставим отправку всех нулей в регистр, и задержку оставим 500. То есть у нас должны будут зажечься все задействованные сегменты индикатора, так как он с общим анодом и активное состояние у него низкое.
А в бесконечном цикле мы будем отравлять инверсные коды различных цифр по порядку.
Чтобы нам не морочить головы с кодами, мы все их возьмём из проекта по сборке часов на светодиодном четырехразрядном индикаторе из функции segchar().
Начнём с единицы
while(1)
{
//1
SPDR = 0b11111001;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
Затем мы можем код скопировать несколько раз и подправить в нём значения, заносимые в регистр SPDR.
Вот полный код бесконечного цикла (код под спойлером, нажмите «+«)
while(1)
{
//1
SPDR = 0b11111001;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//2
SPDR = 0b10100100;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//3
SPDR = 0b10110000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//4
SPDR = 0b10011001;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//5
SPDR = 0b10010010;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//6
SPDR = 0b10000010;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//7
SPDR = 0b11111000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//8
SPDR = 0b10000000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//9
SPDR = 0b10010000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//0
SPDR = 0b11000000;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//.
SPDR = 0b01111111;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//-
SPDR = 0b10111111;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//С
SPDR = 0b11000110;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
//пустое место
SPDR = 0b11111111;
while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
//сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
PORTB |= (1<<PORTB2); //высокий уровень
PORTB &= ~(1<<PORTB2); //низкий уровень
_delay_ms(500);
}
Соберём код, посмотрим сначала в протеусе
Если всё нормально работает, то прошьём контроллер и посмотрим результат на настоящем индикаторе
Всё работает отлично!
Итог.
Благодаря нашим знаниям программирования, мы превратили вроде бы никому не нужный копеешный сдвиговый регистр в драйвер светодиодного индикатора (причём не важно, что у него общее — анод или катод), работающий по шине SPI, то есть практически по трем ножкам портов.
В следующем занятии мы попытаемся подключить два таких регистра, а к ним — четырёхразрядный светодиодный индикатор и применить динамическую индикацию, также пользуясь интерфейсом SPI.
Посмотрим, что у нас получится.
Предыдущий урок Программирование МК AVR Следующий урок
Техническая документация на сдвиговый регистр 747HC595
Программатор, сдвиговые регистры и индикатор можно приобрести здесь:
Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером
Сдвиговые регистры 74HC595N 10 шт
Семисегментный одноразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий