STM Урок 161. LL. USART. Передача данных. Часть 2

В предыдущей части нашего занятия мы познакомились с блок-схемой шины USART в контроллере STM32F1, а также познакомились с регистрами данной шины и с их битами по-отдельности.

 

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

Начнем со схемы. Контроллер у нас будет STM32F103C8T6, расположенный на недорогой отладочной плате. Также для мониторинга мы подключим к нему индикатор с драйвером MAX7219, которым мы также постоянно пользуемся. Подключим мы его к шине SPI2, ножки мы увидим, когда будем настраивать шину в Cube MX

 

 

Для работы с интерфейсом USART мы подключим переходник USB-TTL к шине USART1, не забывая, что ножка RX переходника подключается к ножке TX контроллера, а ножка TX, наоборот, — к RX

 

 

Также для оценки процесса обмена подключим к шине USART логический анализатор

 

 

Подключим к ПК, анализатор, переходник и программатор

 

 

Перейдём к проекту. Создадим новый проект в Cube MX и выберем наш контроллер

 

 

Выберем программатор

 

 

Подключим кварцевый резонатор

 

 

Произведём настройки тактирования в Clock Configuration

 

 

 

Включим USART1 для работы в асинхронном режиме, настройки все оставим по умолчанию

 

 

Посмотрим, какие ножки у нас включились для шины USART1

 

 

Для работы с драйвером индикатора включим шину SPI2 произведём её некоторые настройки

 

 

Посмотрим, какие ножки контроллера работают с шиной SPI2, а также включим ещё одну на выход для линии SS

 

 

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

 

 

Далее перейдём в раздел Project Manager и задействуем на всё библиотеку LL

 

 

Придумаем имя нашему проекту и выберем среду программирования

 

 

Соберём проект и откроем его в Keil. Файлы для работы с драйвером индикатора max7219.c и max7219.h возьмём, например из проекта прошлого урока LL_SPI_MASTER_DMA и скопируем их в соответствующие папки нового проекта.

Подключим файл max7219.c к дереву проекта, настроим программатор на автоперезагрузку и уберём оптимизацию.

Подключим библиотеку для драйвера индикатора, а также ещё одну стандартную библиотеку, в файле main.c

 

 

А теперь в соответствии с традицией посмотрим, как нам проектогенератор сгенерировал инициализацию шины USART1.

Для этого зайдём в тело функции MX_SPI2_Init и посмотрим, что там происходит.

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

Далее уже вызывается более низкоуровневая функция LL_USART_Init, параметрами которой служат USART1 и вышеназванная структура.

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

В условие включения 9-битного режима передачи мы не попадаем, а попадаем в ELSE. где сначала отключаются биты M, PCE, PS, TE и RE регистра CR1 с помощью второго параметра макроса MODIFY_REG, а в третьем параметре мы настраиваем биты с помощью полей нашей переданной структуры. В нашем случае включатся только биты TE и RE, так как мы включаем шину и на передачу и на приём, хотя приёмом пользоваться пока не будем.

Далее с помощью функции LL_USART_SetStopBitsLength настраивается количество стоповых бит. Так как у нас 1 стоповый бит, то у нас соответствующее битовое поле STOP регистра CR2 будет нулевое.

Затем с помощью функции LL_USART_SetHWFlowCtrl настраиваются биты RTSE и CTSE регистра CR3, отвечающие за управление аппаратным потоком, а так как мы им не будем управлять, то данные биты просто сбросятся.

 

 

Затем идёт настройка скорости обмена по шине.

Сначала с помощью функции LL_RCC_GetSystemClocksFreq заполняются поля структуры rcc_clocks типа LL_RCC_ClocksTypeDef, в которые заносятся частоты тактирования различных видов периферии контроллера. Так как у нас включен USART1, то нас будет интересовать поле PCLK2_Frequency, которое заполнится значением частоты PCLK2. Значение данного поля затем присваивается переменной periphclk, которой мы затем и пользуемся в расчётах делителя. Значение данной переменной затем передаётся в качестве параметра функции LL_USART_SetBaudRate, которой в качестве третьего параметра также передаётся и значение битрейта, которое нам желательно получить.

Войдём в тело этой функции и посмотрим, как настраивается битрейт.

Здесь регистру BRR присваивается возвращённое значение ещё одной функции (а вернее макроса) __LL_USART_DIV_SAMPLING16, преобразованный в 16-битное значение. В данную функцию передаются те же параметры.

Здесь стоит задача — получить значение делителя — его целую и дробную часть и уложить в регистр BRR.

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

 

 

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

На этом наша функция LL_USART_Init заканчивается, поэтому вернёмся в функцию MX_USART1_UART_Init, в которой дальше с помощью функции LL_USART_ConfigAsyncMode сбрасываются биты LINEN и CLKEN в регистре CR2, а также сбрасываются биты SCEN, IREN и HDSEL, назначение которых мы теперь уже знаем.

Затем при помощи функции LL_USART_Enable устанавливается бит UE регистра CR1, который включит нашу шину.

На этом инициализация закончена. Можно приступать к написанию кода.

Объявим глобальный строковый массив

 

 

В функции main() произведём инициализацию драйвера индикатора, проверим его, выведя на него число, подождём 2 секунды и очистим индикатор

 

 

Добавим функцию. которая будет заниматься передачей в шину USART байтов в определённом количестве

 

 

Займёмся телом функции. Добавим целочисленную переменную для перемещения указателя по массиву

 

 

Добавим цикл, в котором будем следить за окончанием массива

 

 

В данном цикле дождёмся установки флага TXE в регистре SR

 

 

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

 

 

Вот, в принципе, и вся функция.

Вернёмся в функцию main() и добавим переменную для счёта

 

 

В бесконечном цикле сначала сбросим счётчик по достижению какого-нибудь порога

 

 

Сформируем строку со значением счётчика и передадим её в шину USART

 

 

Отобразим значение счётчика на индикаторе, немного подождём и увеличим значение счётчика на 1

 

 

Вот и весь наш код. Зная теорию, намного легче его писать.

Соберём код, прошьём контроллер. Посмотрим сначала результат работы кода на светодиодном индикаторе

 

 

Индикатор исправно отсчитывает циферки.

Далее настроим терминальную программу, и посмотрим, как приходят строки в ПК

 

 

Также давайте посмотрим, как отображается трафик в программе логического анализа. Для этого включим 2 канала. Затем добавим следующий анализатор

 

 

Настроим анализатор

 

 

Добавим ещё один такой анализатор, то только на другой канал, настроив его аналогичным образом

 

 

Установим триггер на канал 0

 

 

Вот так передаётся наша строка

 

 

Также мы видим, что передача байтов идёт непрерывно, без каких-либо пропусков

 

 

Итак, на данном уроке мы изучили подробно аппаратную реализацию шины USART в контроллере STM32, и, используя библиотеку LL закрепили свои знания на практике.

Всем спасибо за внимание!

 

 

 

 

Исходный код

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Переходник USB-TTL

Индикатор светодиодный семиразрядный с драйвером MAX7219

Логический анализатор 16 каналов можно приобрести здесь

 

 

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

STM LL. USART. Передача данных

 

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

STM LL. USART. Передача данных

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

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

*