Если Вы хотите обучаться программированию микроконтроллеров, но попали, сюда не прочитав предыдущих уроков, то советую начать изучение материала с самого начала.
На прошлом занятии мы с вами научились пользоваться прерываниями и разобрали работу таймера/счетчика Т0. А сегодня мы разберем как работает интерфейс SPI и подключим к нашему контроллеру небольшой ЖК дисплей. |
---|
В микроконтроллерах семейства Mega имеются три интерфейса с помощью которых его можно подключать к различной периферии, микропроцессорным устройствам или компьютерам. UATR/USART – в основном используют для соединения с компьютерами, TWI – используют для объединения большого количества разных устройств с целью их совместной работы. Ну и остается еще последовательный периферийный интерфейс SPI который используют для управления другими контроллерами или периферийными устройствами.
Полную структурную схему модуля SPI можно посмотреть в даташите, но если ее сильно упростить, то останется только сдвиговые регистры, тактовый и управляющий сигналы.
На схеме показан один из вариантов обмена данными между двумя микроконтроллерами. Обмен данными по SPI происходит одновременно в обоих направлениях как от ведущего (Master) устройства к ведомому (Slave), так и обратно с помощью сдвиговых восьмибитовых регистров по линиям MISO (ведущий вход, ведомый выход) и MOSI (ведущий выход, ведомый вход). Сдвиги происходят в устройствах одновременно в такт управляющему сигналу SCK генерируемому ведущим микроконтроллером. В результате передачи сдвиговые регистры обмениваются своими данными. Все легко и просто, но есть нюансы. Линия SS (Slave Select) очень важна для ведомых устройств. Когда на ней низкий потенциал, ведомое устройство готово к приему/передачи, а когда высокий потенциал устройство позволяет производить необходимые действия со сдвиговым регистром. Например, чтение или запись новых данных. Еще раз. Запись данных для передачи в сдвиговый регистр ведомого микроконтроллера возможна только при высоком потенциале на линии SS, а передача данных только при низком потенциале на этой линии. У ведущего МК работа линии SS определяется пользователем и должна работать как линяя вывода общего назначения. Если ведомых устройств больше одного, то у ведущего МК линий управления должно быть столько, сколько устройств к нему подключено (последовательное подключение ведомых устройств мы сейчас не рассматриваем).
Для управления и контроля работы модуля отведено три регистра: SPCR, SPSR и SPDR.
SPDR – регистр данных для записи передаваемых/принимаемых данных.
SPSR – регистр состояния модуля: 0 разряд (SPI2X) – удвоение скорости обмена. Актуален только для ведущего контроллера. Установка «1» удваивает частоту SCK; 6 разряд (WCOL) – флаг конфликта записи. Устанавливает «1» в случае попытки записи в регистр данных во время процесса приема/передачи данных; 7 разряд (SPIF) – флаг прерывания от SPI. Флаг устанавливается «1» по окончании процесса передачи данных, а также при переводе МК в режим ведомого с помощью лини SS.
SPCR – регистр управления SPI: 0, 1 разряды (SPR1 и SPR2) – управление скоростью передачи; 2 разряд (CPHA) – Фаза тактового сигнала. «0» - запись принимаемых данных происходит по переднему фронту тактового сигнала SCK. «1» - запись данных происходит по заднему фронту SCK; 3 разряд (CPOL) – Полярность тактового сигнала. «0» - перед началом тактирования на выводе CSK будет низкий уровень. «1» - перед началом тактирования на выводе CSK будет высокий уровень; 4 разряд (MSTR) – выбор режима работы. «1» – Master, «0» – Slave; 5 разряд (DORD) – Порядок передачи данных. «1» - первым передается младший бит, «0» - старший бит; 6 разряд (SPE) – «1» - включение, «0» - выключение модуля SPI; 7 разряд (SPIE) – «1» - разрешение, «0» - запрещение прерывания от SPI.
Перед тем как мы рассмотрим алгоритм работы модуля необходимо сказать еще пару слов о нюансах его работы. Во-первых, при включении модуля некоторые выводы МК автоматически переходят в состояние «вход». В режиме «Ведущий» это выход MISO, а в режиме «Ведомый» MOSI, CSK, SS. И если в режиме «Ведомый» всё логично, то в режиме «Ведущий» в случае если вам не нужно принимать данные от ведомого МК, использовать вывод MISО (PB3) в качестве вывода общего назначения становится затруднительно. Во-вторых, и это касается больше режима «Ведомый», при работе с модулем SPI необходимо самостоятельно настраивать работу подтягивающих резисторов для всех выводов модуля.
Теперь перейдем непосредственно к работе модуля. Перед началом передачи/приема данных необходимо разрешить работу модуля установив «1» в разряд SPE. А также настроить работу модуля определив значения в разрядах регистра SPCR. Если выводы МК не используются кроме как для работы модуля, то настройку SPI можно провести всего один раз при инициализации МК в начале его работы. При необходимости передачи данных ведущему на линии SS необходимо установить «0» после чего записать передаваемое число в регистр SPDR. Как только в регистр SPDR будет помещено число автоматически запускается генератор тактовых импульсов и произойдет передача данных. По окончании передачи поднимается флаг SPIF регистра SPSR. После чего можно извлечь переданные данные из регистра SPDR или записать в него новые данные для пересылки.
Более подробный разбор работы SPI можно посмотреть по этим ссылкам (Интерфейс SPI), (Atmega8 интерфейс SPI).
Ну а теперь давайте применим полученные знания о работе SPI на практике и подключим к нашему МК дисплей Nokia_5110. Описание к нему я надеюсь вы уже изучили, а значит можно переходить непосредственно к подключению.
Здесь я коснусь подключения дисплея вкратце, а более полную информацию можно получить, почитав статьи «Подключение LСD дисплея Nokia 5110 к микроконтроллеру ATmega8.», а также «Подключение LСD дисплея Nokia 5110 к микроконтроллеру ATtiny25».
Ничего сложного при подключении дисплея к МК нет. Для подсветки используем имеющийся у нас транзистор кт815 и сопротивления близкие по значению. В виду того, что этот дисплей будет с нами до окончания курса, то лучше его расположить так как сделал это я. Таким образом он не будет мешать дальнейшей работе.
Так как мы подсоединяем дисплей по упрощенной схеме то линия MISО и SS нам не нужны. С другой стороны, для управления дисплеем необходимо организовать линию сброса RESET и линую данные/команда D/C. Для сброса мы используем линию SS (PB2), а для определения передаваемых данных линию PB1. Необходимая библиотека для работы с этим дисплеем находится в приложенных файлах (Lib_Nokia_5110_ATmega.c). Ее необходимо использовать с библиотекой основных макросов (lib_macro.c).
Отдельно хотелось бы остановиться на основной подпрограмме пересылки данных из МК в дисплей. Из-за того, что этот дисплей не использует все возможности SPI, а только ту часть, которая отвечает за прием данных от МК, то и подпрограмма пересылки будет усеченной. К тому же в нее включен элемент управления, который указывает дисплею как распорядиться входящими в него данными.
//Подпрограмма пересылки данных через SPI для дисплея nokia_5110 void send_data (unsigned char data, unsigned char dc){ LCD_PORT.LCD_DC = dc; //Устанавливаем флаг данные/команда SPDR = data; //записываем в регистр данные для передачи while (!(SPSR & (1<<SPIF))); //Ждем завершение передачи данных }//END Подпрограмма пересылки данных через SPI
В подпрограмму мы отправляем два байта. Первый это данные для пересылки (data), а второй статус данных (dc). После чего мы, устанавливая на выводе МК статус передаваемых данных (0) – команда, (1) – дата, указывая дисплею как интерпретировать пересылаемые данные. Да. Если вы пользуетесь средой разработки, которая не понимает прямое обращение к биту порта, то строку
LCD_PORT.LCD_DC = dc;
Необходимо заменить на
if (ds) LSD_PORT |= (1<<LSD_DC); else LSD_PORT &= ~(1<<LSD_DC);
После того как мы установили статус передаваемых данных, в регистр SPDR записываем данные для пересылки. Как только данные попали в регистр. Автоматически включается генератор и происходит передача данных. Передача данных происходит с частотой меньшей чем частота работы МК и для того, чтобы данные прошли без проблем последней строчкой мы ждем поднятия флага прерывания от SPI. Он будет означать, что данные переданы и интерфейс готов к приему новых данных для дальнейшей работы.
Теперь, давайте напишем простенькую программу, которая выведет на дисплее небольшую полоску. Которая будет означать, что данные были успешно переданы по SPI из МК в дисплей.
#include//Общие макросы #include "lib_macro.c" #define DATA 255 //данные для заполнения линии #define MAX_LINE 80 //Длинна отображаемой линии //Процедуры и функции #include "Lib_Nokia_5110_ATmega.c" void main(void) { unsigned char temp; //инициализация переменной lcd_init(); //инициализация дисплея //Рисуем полоску for (temp=ZERO;temp<MAX_LINE;temp++) { send_data (DATA, LCD_DAT); //пересылка данных }; LED_ON; //включаем светодиод while (1) {} } //END void main(void)
Если вы все сделали правильно, то должна включиться подсветка, а на дисплее должна отобразиться вот такая картинка.
Ну вот, как в песни поется – «всё просто и легко в этом мире». Безусловно, что интерфейс SPI хранит в себе много нюансов с которыми вы, будете разбираться во время своих экспериментов, но на данный момент программа минимум выполнена.
Возможно, что с первого раза у вас не отобразиться ничего на экране. Не отчаивайтесь. Поиграйтесь с настройками дисплея. Такими как: Смещение напряжения и Генератор повышенного напряжения.
К следующему уроку необходимо достать ручной энкодер и парочку сопротивлений на 10 кОм. Про энкодер надо будет найти информацию в сети и изучить их классификацию и режимы работы.
На следующим уроке мы подключим энкодер к нашему контроллеру, а также научимся выводить символы на дисплей. Из-за того, что этот дисплей не имеет встроенной библиотеки символов ее необходимо помещать в память контроллера и писать специальную программу для вывода символов на экран.
А на сегодня всё. Удачи.
17.06.19
Если вдруг найдете в статье неточности или заблуждения. Напишите мне об этом. Я подправлю.
Приложение: Библиотека Lib_Nokia_5110_ATmega.c Программа к уроку 17