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 с адаптером USBASP USBISP 3.3 с адаптером

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

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

 

 

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

 

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

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

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

*