AVR Урок 31. Связь ATtiny2313 и Atmega8 по SPI. Часть 2

 

 

 

 

Урок 31

Часть 2

 

Связь ATtiny2313 и Atmega8 по SPI

 

 

В прошлой части занятия мы познакомились с реализацией SPI в контроллере ATtiny2313, тем самым подготовив данный МК к соединению посредством шины SPI и передачи данных контроллеру ATmega8.

Теперь начнём работать с контроллером ATmega8, чтобы он сумел данные, посланные ему, принять. Данные мы уже принимали, но с той разницей, что контроллер наш был ведомым, теперь он уже будет ведущим, что конечно внесёт определённые коррективы в написание исходного кода.

Откроем проект и добавим функцию инициализации выше функции main(), в имя которой мы ещё добавим определённый суффикс, чтобы было видно что мы подключаем устройство как ведомое (Slave)

 

//—————————————-

void SPI_init_SL(void)

{

}

//—————————————-

 

Сначала в теле данной функции мы инициализируем задействованные ножки портов

 

void SPI_init_SL(void)

{

  DDRB |= (1<<PORTB4);//ножки SPI на выход

  DDRB &= ~((1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5));//ножки SPI на вход

 

Как мы видим, что теперь большинство ножек у нас настраивается на вход, что и логично, у нас же ведомый контроллер, поэтому на выход мы включаем только ножку MISO.

Теперь включим шину, настроив управляющий регистр

 

  DDRB &= ~((1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5));//ножки SPI на вход

  SPCR = ((1<<SPE)|(1<<SPIE));//включим шину, включим прерывания

}

 

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

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

 

По прерываниям от шины SPI мы используем вот такой вот вектор

 

Image15

 

Добавим обработчик прерывания над функцией main()

 

//—————————————-

ISR(SPI_STC_vect)//прерывание SPI прием байта

{

}

//—————————————-

 

Добавим переменную и занесём в неё байт из регистра

 

ISR(SPI_STC_vect)//прерывание SPI прием байта

{

  unsigned char n;

  n = SPDR;

 

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

И затем аналогично тому, как мы делали на ATTiny, мы данный принятый байт преобразуем в строку и отобразим на дисплее, не забывая его перед этим очистить

 

  n = SPDR;

  clearlcd();//очистим дисплей

  setpos(0,0);

  itoa(n,str,10);

  str_lcd(str);

  SPDR = n;

}

 

Объявление переменной str мы из функции main() перенесём вверх и сделаем её глобальной, немного добавив количество элементов

 

#include "main.h"

//—————————————-

char str[10];

 

Также функцию инициализации шины SPI мы должны вызвать в main(), а также включить глобальные прерывания

 

LCD_ini(); //»нициализируем дисплей

SPI_init_SL();//инициализируем SPI

sei();

 

Ну, в принципе можно проверить наш код на деле.

Соберём наш код и запустим его в протеусе

 

Image16

 

Всё у нас хорошо передаётся и принимается.

Прежде чем нам полюбоваться, как это всё происходит на практике, давайте посмотрим нашу конструкцию

 

Image17

 

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

 

 

Сначала прошьём контроллер ATmega8

 

Image18

 

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

Так как другой контроллер у нас уже прошит, то мы не будем в него подключать программатор, а просто подведём от отладочной платы с ATmega к нему плюс и общий провод

 

Image19

 

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

 

Image20

 

Казалось бы, на этом можно и завершить, но мы ещё не пробовали принимать байты на ведущем контроллере, а также передавать с ведомого.

Давайте и этим заодно займёмся, благо контроллеры наши это делать позволяют. То есть обмен у нас пойдёт полнодуплесный и сдвиговые регистры наши будут работать на полную.

Сначала давайте, сделаем всё для контроллера ATtiny, раз уж у нас все равно программатор воткнут в его гнездо.

Первым делом по эстетическим соображением назовём и функцию передачи байтов по-другому, так как она будет работать в обе стороны, а также добавим ей возвращаемый тип

 

char SPI_ChangeByte(char byte)

 

И в конце тела данной функции вернём байт

 

  return USIDR;

}

 

 

Добавим ещё одну переменную в main() для принимаемого байта

 

unsigned char n=0,m=0;//переменная для случайного числа

 

Также изменим имя и в вызове функции обмена в бесконечном цикле и добавим возврат значения

 

m = SPI_ChangeByte(n);

 

То есть здесь мы передадим n, а примем m.

Ну, и приблизительно таким же образом мы отобразим на дисплее ещё и принятый байт, а чтобы циферки между собой не соединились, мы спозиционируем перед этим курсор дисплея в другое место

 

str_lcd(str);

itoa(m,str,10);

setpos(0,1);

str_lcd(str);

 

Теперь перейдём к проекту с контроллером ATmega8 и подумаем, как же нам оттуда отправить байт.

Оказывается это сделать ещё проще. В обработчике прерывания в момент, когда принялся байт, то у нас регистр SPDR очищается. Поэтому давайте мы в него обратно запишем значение нашей переменной n

 

  str_lcd(str);

  SPDR = n;

}

 

И записанный в SPDR байт в следующем цикле обмена байтами в регистре уйдёт обратно в контроллер ATtiny2313.

Соберём сначала наши оба проекта.

Посмотрим результат в протеусе

 

Image21

 

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

Теперь нам нужно проверить всё на практической схеме.

Опять разъединим межконтроллерное питание и прошьём сначала контроллер ATtiny2313, затем, не соединяя питание, переключим разъём программатора в отладочную плату с контроллером ATmega8 и прошьём его. Затем отключим общее питание, соединим провод питания и общий провод между обеими схемами, подадим общее питание и посмотрим результат

 

Image22

 

У нас всё отлично работает и передаётся. Всё идёт по циклу. Теперь я думаю мы очень неплохо проработали знания по программированию шины SPI, причём на нескольких контроллерах.

Но не успокаивайтесь! Мы обязательно к этой шине ещё вернёмся, так как устройств работающих по данной шине, очень немало.

 

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

 

Исходный код

 

Программатор и дисплеи можно приобрести здесь:

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

Дисплей LCD 16×2

Дисплей LCD 20×4

 

 

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

 

AVR Связь ATtiny2313 и Atmega8 по SPI

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

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

*