понедельник, 10 января 2022 г.

SPI master на stm32f103c8, Си и CMSIS

 Как уже было рассказано в статье - "USI в режиме SPI slave на ATtiny2313" SPI - это простой, быстрый и надежный способ обмена данными между устройствами. Поэтому интерфейс SPI имеется в большинстве современных микроконтроллеров, в том числе и микроконтроллерах stm32. В большинстве таких микроконтроллеров этих интерфесов даже больше одного. Чаще всего SPI в них работает в режиме master вместе со специализированными микросхемами с интерфейсами SPI которые работают в режиме slave. Микроконтроллеры также могут обмениваться данными между собой по SPI. В таких случаях микроконтроллер slave может работать в составе какого нибудь специализированного модуля. Как уже было рассказано, в статье по ссылке выше, устройства с по SPI соединяются друг с другом одноименными пинами т.е. MISO мастера с MISO слейва, MOSI мастера с MOSI слейва и т.д. Микроконтроллер stm32f103c8 (а точнее отладочную плату с ним которую называют "blue pill") можно соединить с микроконтроллером ATtiny2313 по SPI например так как на схеме:

Рисунок 1 - Соединение "blue pill" c ATtiny2313 по SPI

Резисторы R2..R4 - нужны для ограничения тока на случай неправильного конфигурирования пинов GPIO. Если все пины сконфигурированы правильно то в них нет необходимости и их можно и даже лучше не ставить. Светодиод VD1 остался от предыдущей схемы (см. ссылку в верху данной статьи) он может пригодиться для отладки но в нем также нет необходимости. Пины A5, A6, A7 (на схеме на рисунке 1) соответствуют SPI1 микроконтроллера stm32f103c8:

Т.к. микроконтроллер будет мастером то пин PA5 SCK надо настроить на выход, PA6 MISO на вход а PA7 MOSI на выход. NSS можно не трогать т.к. подключение есть только к одному слейву.
Также надо настроить uart и включить тактирование всей используемой периферии (подробнее см. предыдущие уроки). Для упрощения можно создать две переменные для приема и отправки байта данных по SPI а также вспомогательную функцию для отправки байта данных по UART.
Для минимальной настройки SPI1 в режим мастера, в данном случае, достаточно использовать регистр SPI1->CR1:

Битом 2, этого регистра, устанавливается режим мастера, битами 3...5 предделитель частоты шины от которой тактируется SPI1 (а он тактируется от APB2) так чтобы получилась нужная частота работы SPI. При установке этих битов следует иметь в виду то что SPI1, в данном микроконтроллере, не может работать на частоте более 12 МГц. Частота шины от которой тактируется SPI1, по умолчанию, равна 36 МГц (на такю частоту её настраивает CMSIS). Битами 8 и 9 устанавливаем внутреннее программное управление слейвом (чтобы SPI1 мог работать без пина SS). Битом 6 включается SPI, сделать это следует в последнюю очередь. В функции main осталось настроить UART для приема и передачи байта данных, чтобы можно было проверить SPI через монитор последовательного порта (например такой что есть в Arduino IDE) а также основной цикл в котором можно сделать проверку прихода байта данных по UART прежде чем забрать этот байт из регистра данных USART1 для записи в регистр данных SPI. В используемом микроконтроллере при записи байта данных в регистр данных, происходит помещение этого байта сначала в буферный регистр а уже потом в регистр сдвига. Прежде чем записать байт данных в регистр данных нужно подождать освобождения буфера передатчика о чем свидетельствует бит 1 регистра SPI1->SR:
После записи в регистр данных байта данных для передачи слейву нужно ждать заполнения буферного регистра приемника прежде чем принимать забрать байт данных из регистра данных. О заполнении буферного регистра приемника свидетельствует бит 0 регистра SPI1->SR:

После приема байта данных от слейва, можно сделать отчет с выводом принятого байта данных в монитор последовательного порта. Полный код программы можно скопировать из текстового поля:
Видео:

воскресенье, 9 января 2022 г.

USI в режиме SPI slave на ATtiny2313

 SPI - это полнодуплексный последовательный синхронный интерфейс передачи данных. Полнодуплексный означает что прием данных и их передача может происходить одновременно. Для этого в данном интерфейсе есть 2 провода один из которых называется MOSI (M-мастера O-выход S-слейва I-вход) а второй MISO (M-мастера I-вход S-слейва O-выход). Если по SPI соединяются два устройства то один из них является мастером а другой слейвом. Мастер управляет процессом передачи и приема а также генерирует синхроимпульсы. Синхроимпульсы нужны для того чтобы точно задавать моменты времени в которые на проводах MOSI и MISO замеряются уровни напряжений чтобы быть записанными. Синхронные интерфейсы надежнее асинхронных т.к. в асинхронных приемник и передатчик должны работать с одинаковой (чего практически никогда не бывает) или очень близкой частотой чтобы приемник записывал 0 или 1 именно тогда когда это нужный по счету 0 или 1. Неточность частот также влияет на скорость передачи данных в худшую сторону. Поэтому синхронные интерфейсы также быстрее асинхронных. Из за полного дуплекса и синхронности возможно что это самый быстрый последовательный интерфейс который только можно придумать. Быстрее могут быть только параллельные интерфейсы. Синхроимпульсы идут по проводу CSK. Итого, как минимум и не учитывая земли, для данного интерфейса нужно 3 провода. Если необходимо соединить по SPI более 2х устройств то задействуются дополнительные провода SSx где x-номер слейва. Из за этого количество проводов увеличивается на 1 при добавлении одного нового устройства на шину. Т.е. количество проводов SS равно количеству слейвов если оно больше 1. Если слейв 1 то провод SS можно не использовать. Поэтому SPI плох в плане экономии проводов. Если требуется передача, с небольшой скоростью, данных по небольшому количеству проводов то лучше использовать например I2C. Если нужна большая скорость передачи данных с небольшим количеством устройств то SPI лучше подойдет чем I2C. Из за того что данный интерфейс синхронный, стабильность частоты его работы не важна, настолько что если например микроконтроллер является слейвом то мастером может быть человек с кнопкой подключенной к SCK, переключателем подключенным к MOSI и светодиодом подключенным к MISO. С таким подключением человек-мастер может протестировать слейва. Чтобы подключить два устройства по SPI нужно соединить MOSI вывод мастера с MOSI выводом слейва, MISO мастера с MISO слейва а также CSK мастера с CSK слейва. Мастер и слейв имеют внутри себя сдвиговые регистры и после соединения, их описанным выше способом, получается кольцевой сдвиговый регистр при сдвиге битов столько раз сколько битов в одном из регистров (мастера или слейва) происходит обмен данными между мастером и слейвом:




Рисунок 1 - Диаграмма обмена данными межу слейвом и мастером по SPI

Сдвиг на один бит происходит при переднем фронте синхроимпульса или при и заднем спаде синхроимпульса. В микроконтроллерах обычно можно настроить данный параметр. Обычно обмен по SPI происходит по 8 бит но в микроконтроллерах часто имеется возможность настроить обмен на другое количество бит за раз, однако чаще всего используется 8 бит т.е. 1 байт. После того как обмен произошел мастер может забрать байт данных данных из регистра и поместить новый для обмена. Слейв может поступить аналогично. В обоих устройствах д.б. счетчик который указывает на то когда можно забирать байт данных и записывать новый и отсчитывать он должен одинаковое количество раз т.е. 8 если передается 1 байт за раз. Обычно в микроконтроллерах имеются специальные флаги сигнализирующие об окончании обмена. Схема со ATtiny2313 слейвом для взаимодействия с человеком мастером м.б. например такой:
Рисунок 2 - Схема SPI слейва на ATtiny2313 для взаимодействия с человеком

Кнопка S2 обязательно должна быть бездребезговой т.к. иначе одно нажатие на такую кнопку может создать (а скорее почти наверняка создаст) количество синхроимпульсов больше одного. О бездребезговой кнопке есть статья -> https://electe.blogspot.com/2019/04/blog-post.html практика показала (см. видео ниже) что такая кнопка может успешно работать как источник синхроимпульсов. В микроконтроллере ATtiny2313 на SPI. Зато есть USI (универсальный синхронный интерфейс) который может работать в режиме SPI мастера или слейва. Для настройки USI на режим SPI slave есть регистр USICR. Но прежде нужно настроить пины микроконтроллера соответствующим образом. Т.е. Пин SCK д.б. настроен на вход (т.к. если микроконтроллер слейв то синхроимпульсы на него подаются от мастера),  пин MOSI тоже на вход а пин MISO на выход. На входные пины также следует поставить внутреннюю подтяжку к плюсу питания. Режим SPI настраивается битами 4 и 5 регистра USICR, битами 1...3, этого регистра, настраивается источник тактирования сдвигового регистра а также счетчика. Если сделать источником тактирования сдвигового регистра внешний сигнал то микроконтроллер будет работать как слейв. Для счетчтка также нужно установить внешний сигнал. В общем чтобы настроить USI как SPI slave нужно установить биты 3 и 4 регистра USICR:

Чтобы мастер смог забрать байт данных от слейва, нужно поместить этот байт в регистр USIDR. после того как обмен произойдет, из этого регистра можно извлечь байт данных пришедший от мастера. Об окончании обмена свидетельствует бит 6 регистра USISR. Его можно проверять в цикле прежде чем забирать байт от мастера но прежде его нужно программно сбросить записав в регистр число 0b01000000 т.е. именно присвоить это число этому регистру а не выполнить операцию побитового или с данным числом. На схеме на рисунке 2 есть светодиод VD1. Этот светодиод нужен для того чтобы сигнализировать об окончании обмена с мастером т.к. если считать синхроимпульсы слишком долго то можно сбиться со счета а данный светодиод упрощает тестирование слейва вручную. Полный код программы приведен в текстовом поле ниже:


Видео:

пятница, 7 января 2022 г.

Прием по UART на stm32f103c8, Си и CMSIS

Освоив прием данных по UART на микроконтроллере stm32f103c8 уже можно пытаться собирать например контроллер ЧПУ станка управляемого с компьютера через USB-UART переходник, а также другие устройства управление которыми возможно при использовании такого переходника. Рассмотрим например управление трехцветным светодиодом. Для этого можно собрать схему например как на рисунке:

Рисунок 1 - Подключение RGB светодиода с общим анодом и USB-UART переходника к отладочной плате с микроконтроллером stm32f103c8

О том как сделать передачу по UART см. предыдущий урок- https://electe.blogspot.com/2022/01/uart-stm32f103c8-cmsis.html

Далее в коде. Для начала, как всегда, надо включить тактирование периферийных устройств которые будут использоваться. В данном случае это USART1 и порт A:

Пин UARTа1 RX (A10) надо настроить на вход с подтяжкой:

А пины к которым подключен светодиод можно настроить на выход с открытым стоком, если он подключен также как на схеме на рисунке 1.


Для настройки скорости используется регистр USART1-BRR:
В данный регистр заноситься число на которое делиться частота шины от которой тактируется USART чтобы получилась нужная скорость. Т.е. если например нужна скорость 9600 бод а частота шины 72 000 000 Гц (по умолчанию) то в регистр нужно занести = 72 000 000 / 9600 = 7500. Для основной настройки UARTа есть первый управляющий регистр USART1->CR1:

Для приема по UART с прерыванием нужно установить биты 2, 5 и 13 данного регистра. А также надо указать вектор прерывания. Для данной задачи основной цикл можно оставить пустым. Функция которая вызовется при возникновении прерывания от USART1 называется USART1_IRQHandler().
В эту функцию надо поместить код обработки прерывания. Чтобы отреагировать именно на прием, в эту функцию следует поместить проверку флага приема который является битом 5 статус-регистра:

После данной проверки можно принять байт данных пришедший по UART:

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


понедельник, 3 января 2022 г.

Передача по UART на stm32f103c8, Си и CMSIS

 UART (универсальный асинхронный приемник передатчик) часто используется для связи микроконтроллера с другими устройствами. Например по UART в микроконтроллер stm32f103c8 может записываться программа. Для этого, в данном микроконтроллере, имеется аппаратная поддержка данного интерфейса. В stm32f103c8 есть некоторое количество UARTов на случай если одного не хватит. Но программируется данный микроконтроллер через UART1 (а точнее USART1). Режим программирования по UART1 есть тогда когда на BOOT0 есть напряжение логической единицы. Если нет то UART1 может использоваться как обычный UART для связи микроконтроллера с другими устройствами. Этот UART удобно использовать для связи микроконтроллера с компьютером через USB-UART переходник, который также используется для записи программы, т.к. при этом схему не придется чем либо ещё дополнять. Чтобы использовать USART1 нужно включить его тактирование а также тактирвание порта A т.к. пины этого USARTа находятся на данном порту.


Тактирование их включается установкой битов 2 и 14 регистра APB2ENR.


Через пин PA9 (TX) происходит передача поэтому его надо настроить на push-pull выход с альтернативной функцией.



Пин PA10 (RX) можно не настраивать т.к. изначально он уже настроен как надо для данного случая. В регистр USART1->BRR надо записать число которое определит скорость передачи данных. В данный регистр заноситься число на которое делиться частота шины от которой тактируется USART чтобы получилась нужная скорость. Т.е. если например нужна скорость 9600 бод а частота шины 72 000 000 Гц (по умолчанию) то в регистр нужно занести = 72 000 000 / 9600 = 7500.

Чтобы разблокировать UART и передачу по нему, нужно установить биты 3 и 13 регистра USART1->CR1.


Для начала, по традиции, можно передать на компьютер строку "Hello World!". Для этого нужно создать массив символов с данной строкой а также счетчик для обнаружения конца строки.
Массивы и переменные следует объявлять в начале функции а не в середине и конце а также в коде не следует применять "магические цифры" но для простоты в целях образования при первом изучении можно этим пренебречь однако всё же стоит иметь в виду что пренебрежение данными правилами может приводить к трудноуловимым "багам" (на языке Си) и снижать удобочитаемость кода. 
 Чтобы отправить символ по UART его надо записать в регистр данных выбранного UARTа. Но сделать это следует только тогда когда регистр для приема байта данных с целью его последующей отправки свободен. Чтобы определить занятость данного регистра есть специальный флаг который является битом 7 статусного регистра выбранного UARTа.

Если данный бит установлен то все старые биты данных переданы и можно записывать в регистр данных новый бит.

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


А также добавить небольшую задержку чтобы символы не слишком быстро появлялись в терминале. Виде по данной теме:


КАРТА БЛОГА (содержание)