STM Урок 162. LL. USART. Приём данных



Продолжая освоение возможностей библиотеки LL, немного усложним задачу по работе с шиной USART контроллера STM32F1. На данном уроке мы помимо передачи данных из контроллера в ПК попробуем также и принять данные из ПК. Причём, прерываниями мы пока также пользоваться не будем. Будем прорабатывать шину постепенно.

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

Практическая схема урока осталась прежняя

 

 

И, прежде чем перейти к проекту, мы должны придумать, как и что мы будем посылать нашему контроллеру из ПК.

Думаю, для этого нам подойдёт возможность работы со скриптами терминальной программы Terminal v1.9b, тем более мы уже работали со скриптом в уроке 116.

Откроем данную терминальную программу, выберем наш порт, настроим скорость 115200 бпс и зайдём в редактор скриптов

 

 

Напишем там вот такой скрипт

 

 

Сложного в данном скрипте ничего нет. Код похож на Pascal. С помощью данного кода с интервалом в 100 милисекунд в контроллер передаются строки, состоящие из строки «String» и значением инкрементирующегося циклически от 0 до 1023 счетчика, преобразованном также в четырёхсимвольную величину с дописанными слева нулями, если значение меньше четырёх знаков. Сохраним наш скрипт.

Пока ничего не запускаем.

Проект был сделан из проекта прошлого урока с именем LL_USART_TX и получил новое имя, соответственно, LL_USART_RX.

Откроем наш проект в Cube MX и, ничего там не трогая, сгенерируем проект и откроем его в Keil.

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

 

 

Откроем файл main.c и добавим ещё парочку стандартных библиотек, так как нам придётся из строки извлекать число в символьном виде и преобразовывать его в числовой, чтобы показать затем на индикаторе, а также чтобы ответить на него другим числом компьютеру

 

 

Удалим объявление строкового массива

 

char str1[30];

 

Вместо него добавим целых три

 

 

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

 

 

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

Первым делом подождём наполнения приёмного буфера и заберём из него байт

 

 

Затем подождём опустошения буфера передачи и передадим байт, записав его в буфер

 

 

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

 

 

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

 

 

 

Аналогично первому, примем следующий байт и передадим в ответ свой

 

 

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

 

 

Из функции main() удалим вот этот код

 

LL_mDelay(2000);

Clear_7219();

 

В бесконечном цикле удалим пока весь пользовательский код и подготовим строку для передачи её в ПК. В данную строку мы включим символьное значение величины принятого счётчика из ПК, вычтенного из 1023. В самый первый раз это будет 0, так как мы ещё ничего не приняли

 

 

Примем строку из шины и передадим свою при помощи написанной нами функции

 

 

Извлечём из принятой строки 4 последних символа, это и будет значение счётчика ПК

 

 

Преобразуем строковое значение счётчика в числовое

 

 

Отобразим оба значения (и принятое и отправляемое) на индикаторе

 

 

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

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

 

 

На индикаторе слева у нас показания постоянно убывают на 1, а справа — прибавляются

 

 

Также поподробнее посмотрим обмен данных на шине с помощью логического анализатора

 

 

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

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

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

 

 

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

 

Исходный код

 

 

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

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

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

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

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

 

 

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

 

STM Name

3 комментария на “STM Урок 162. LL. USART. Приём данных
  1. хотелось бы примеры с usart c DMA и в прерывании

  2. я имею ввиду приём данных по usart да и код попроще и понятнее.

  3. Aleksey Pugachev:

    80 строчка: rx_dt[ind] = (uint8_t)(USART1->DR & 0x00FF);
    Что за поле такое DR? Может RDR регистр, если перед этим ждали флаг RXNE?

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

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

*