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 закрепили свои знания на практике.

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

 

 

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

 

 

Исходный код

 

 

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

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

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

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

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

 

 

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

 

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

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

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

*