AVR Урок 26. SPI. Подключаем LED индикатор



 

Урок 26

SPI. Подключаем LED индикатор

 

Продолжаем работать с шиной SPI. На прошлом занятии мы научились работать со сдвиговым регистром 74HC595.

Сегодня мы также продолжим работать с данным регистром, но сегодня мы попытаемся подключить к нему светодиодный семисегментный одноразрядный индикатор.

Я думаю, это будет выглядеть интереснее, чем бегущие огни по светодиодной планке.

Общий анод индикатора мы подключим к шине питания, а сегменты — к регистру через токоограничивающие резисторы вот таким вот образом

 

image00

 

Управляющие входы регистра остались без именения подключенными таким же образом, как и в прошлом занятии.

У моего индикатора, который я подключил, вот такая вот распиновка

 

image02

 

На практике всё выглядит приблизительно вот так

 

image04

 

Проект создан был с именем SPI_LED, код был полностью весь взят с прошлого занятия с целью, чтобы нам избежеть первоначальных настроек и настроек инициализации.

Если мы сейчас в протеусе включим наш проект на выполнение, то у нас будет работать прошлый код, только те сегменты, которые светились в прошлом занятии, наоборот светиться не будут, так подключены у нас светодиоды в обратном порядке и не на общую шину, а на шину питания

 

image01

 

До бесконечного цикла код в функции 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()

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);

}

 

 

Соберём код, посмотрим сначала в протеусе

 

image03

 

Если всё нормально работает, то прошьём контроллер и посмотрим результат на настоящем индикаторе

 

image05

 

Всё работает отлично!

Итог.

Благодаря нашим знаниям программирования, мы превратили вроде бы никому не нужный копеешный сдвиговый регистр в драйвер светодиодного индикатора (причём не важно, что у него общее — анод или катод), работающий по шине SPI, то есть практически по трем ножкам портов.

В следующем занятии мы попытаеся подключить два таких регистра, а к ним — четырёхразрядный светодиодный индикатор и применить динамическую индикацию, также пользуясь интерфейсом SPI.

Посмотрим, что у нас получится.

 

 

Предыдущий урок Программирование МК AVR Следующий урок

 

Исходный код

 

Техническая документация на сдвиговый регистр 747HC595

 

Программатор ,сдвиговые регистры и индикатор можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Сдвиговые регистры 74HC595N 10 шт

Семисегментный одноразрядный индикатор красный с общим анодом 10 шт

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

AVR SPI. Подключаем LED индикатор

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*