[Home] [< Prev: UART и USART. COM-порт. Часть 1] [Next: Измерение температуры. Цифровой датчик DS18B20 >]

UART и USART. COM-порт. Часть 2

Введение
Использование USART для обмена данными
Прерывание
Передача байта
Приём байта
Пример 1 (обмен байтами)
Пример 2 (обмен строками)



Введение

В этой части статьи рассмотрим подключение компьютера к микроконтроллеру и пример программы для обмена данными между ними. Для подключения будем использовать COM-порт компьютера и UART/USART интерфейс микроконтроллера. Подробнее об UART, USART, COM говорилось в первой части.

Подключение будем осуществлять с использованием схемы для гальванической развязки COM-порта.

Простая схема гальванической развязки для COM-порта

В качестве микроконтроллера, как и раньше, будем использовать STM32F100RBT6B в составе оценочной платы STM32VLDISCOVERY. Возможности, функционирование USART в микроконтроллерах STM32, использование USART, набор регистров USART - всё это подробно описывается в руководстве пользователя для микроконтроллеров STM32. Наиболее важные вопросы обсуждаются в первой части статьи.

Использование USART для обмена данными

USART предоставляет возможность гибкой настройки конфигурации: можно в широком диапазоне изменять скорость передачи; изменять количество битов в передаваемом одним фреймом слове; использовать один из нескольких возможных вариантов контроля чётности или отключать контроль; настраивать количество стоп-битов; можно использовать или не использовать линии CTS/RTS. Безусловно, богатство возможностей по настройке придаёт USART большую гибкость и универсальность, но с другой стороны, создаёт определённые трудности при обмене данными. Ведь для того, чтобы обмен данными был возможным, подключённые между собой устройства должны иметь одинаковые настройки по всем параметрам.

После конфигурирования USART можно приступать к обмену данными. У микроконтроллера есть два варианта работы с USART: побайтная передача и приём или с использованием DMA. В первом случае, для приёма и передачи каждого байта процессор должен выполнить последовательность определённых действий. Так, он может обрабатывать прерывание, возникающие, когда опустошается регистр передаваемых данных или заполняется регистр принимаемых данных; установив причину прерывания, записать в регистр данных очередной байт для передачи или считать из регистра принятый байт и обработать его. Если используется режим работы с DMA, то процессору необходимо задать расположение буферов для приёма и передачи, их размер. USART и DMA далее будут осуществлять передачу и приём самостоятельно, не требуя затрат вычислительных ресурсов процессора.

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

Прерывание

Если требуется обрабатывать прерывания от устройства USART, то следует определить функцию-обработчик. Независимо от причины прерывания от USART, используется один и тот же обработчик

extern "C" void USARTx_IRQHandler()
{
    // Код обработчика исключения.
}

Здесь символом "x" в имени USARTx_IRQHandler обозначен номер устройства USART: 1, 2, ...

Причина прерывания определяется внутри обработчика путём анализа регистра состояния USARTx->SR.

Не следует забывать включать генерацию прерывания при установке интересующих флагов путём настройки устройства USART, а также требуется настроить контроллер прерываний NVIC - задать приоритет и разрешить обработку - функциями

NVIC_SetPriority (USARTx_IRQn, PRIORITY);
NVIC_EnableIRQ(USARTx_IRQn);

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

Передача байта

Для передачи байта через устройство USART достаточно выполнить запись в регистр USART_DR, но предварительно необходимо выполнить ряд действий для конфигурирования устройств. Алгоритм действий будет примерно следующий.
0. Включить тактирование для устройства USART и используемых GPIO (как обычно, иначе невозможно будет даже выполнить запись в регистры устройств).
1. Включить USART: USART_CR1.UE=1.
2. Задать длину слова с помощью бита USART_CR1.M (0 - 8 бит, 1 - 9 бит). Нужно учитывать, что бит чётности, если он используется, считается битом данных.
3. Задать количество стоп-битов с помощью битового поля USART_CR2.STOP (00 - 1 стоп-бит; 01 - 0.5; 10 - 2; 11 - 1.5 стоп бита).
4. Если используется DMA, установить бит USART_CR3.DMAT и сконфигурировать регистр DMA.
5. С помощью регистра USART_BRR выбрать скорость обмена данными.
6. Включить USART передатчик: USART_CR1.TE=1, в результате на выходе TX устройства USART появиться сигнал с уровнем лог. 1, "линия свободна" (если соответствующий вывод микроконтроллера настроен как выход для альтернативной функции).
7. Настроить вывод микроконтроллера, к которому привязан выход TX данного устройства USART как выход для альтернативной функции.
8. Записать байт посылаемых данных в регистр USART_DR для того, чтобы начать передачу. Запись в регистр сбрасывает флаг USART_SR.TXE (регистр передаваемых данных пуст). Когда байт будет помещён в передающий сдвигающий регистр, флаг будет снова установлен в 1 и если разрешены прерывания при установке флага (установлен бит USART_CR1.TXEIE), будет сгенерировано прерывание. Это означает, что можно записать следующий байт в USART_DR. Следует повторять действие для каждого байта предназначенных для передачи данных (записывать очередной байт данных после установки флага TXE).
9. После записи последнего байта нужно дождаться установки флага USART_SR.TC, который сигнализирует о том, что последний фрейм отправлен и передача завершена. После этого можно отключить USART или остановить процессор без риска нарушения передачи последнего фрейма.

Приём байта

Для приёма данных по одному байту выполняют конфигурирование USART и используемых GPIO, после чего производится чтение из регистра USART_DR, если он содержит принятые данные (наличие данных определяем по флагу USART_SR.RXNE). Используется следующий алгоритм.
0. Включить тактирование для устройства USART и используемых GPIO.
1. Включить USART: USART_CR1.UE=1.
2. Задать длину слова с помощью бита USART_CR1.M (0 - 8 бит, 1 - 9 бит). Нужно учитывать, что бит чётности, если он используется, считается битом данных.
3. Задать количество стоп-битов с помощью битового поля USART_CR2.STOP (00 - 1 стоп-бит; 01 - 0.5; 10 - 2; 11 - 1.5 стоп бита).
4. Если используется DMA, установить бит USART_CR3.DMAR и сконфигурировать регистр DMA.
5. С помощью регистра USART_BRR выбрать скорость обмена данными.
6. Настроить соответствующий входу RX вывод микроконтроллера как цифровой вход.
7. Включить USART приёмник: USART_CR1.RE=1. Приёмник начинает ждать получения страт-бита на входе RX.
8. Когда байт будет получен, будет установлен USART_SR.RXNE флаг. Это сигнализирует о том, что получение фрейма в приёмный сдвигающий регистр завершено, данные из сдвигающего регистра переданы в регистр RDR и регистр RDR может быть прочитан путём чтения из USART_DR. Если установлен бит USART_CR1.RXNEIE, то будет сгенерировано прерывание.

При приёме данных могут устанавливаться флаги NF (при обнаружении шума в сигнале), FE (ошибка фрейма, например, если не получены стоп-биты), PE (ошибка чётности); контроль над наличием шума может быть отключён, контроль чётности отключён по умолчанию.

Установленный после получения данных, флаг USART_SR.RXNE сбрасывается при чтении из регистра USART_DR. Если используется DMA, то флаг RXNE также устанавливается при получении каждого байта и сбрасывается, когда DMA считывает байт из USART_DR.

Данные должны быть считаны из USART_DR до того, как завершится приём следующего фрейма, иначе произойдёт ошибка переполнения. В случае переполнения устанавливается флаг USART.ORE. Установленный флаг говорит о том, что, по меньшей мере, 1 байт был потерян. Если установлен флаг USART.RXNE, то RDR содержит действительные данные, которые должны быть считаны чтением из регистра USART_DR. Если же флаг RXNE сброшен, это означает, что данные уже считаны - это может произойти, если чтение происходит как раз в тот момент, когда получен (и тут же потерян) новый фрейм. Вообще, в случае переполнения, данные в регистре RDR не теряются, теряются данные в приёмном сдвигающем регистре.

Приём посылки Break воспринимается как ошибка фрейма, после получения Break требуется произвести считывание из USART_DR для сброса флага FE. Переход линии в состояние "свободна" (Idle) после приёма порции данных воспринимается как получение "символа" Idle; при этом устанавливается флаг USART_SR.IDLE, а если установлен бит USART_CR1.IDLEIE, то также генерируется прерывание. Для сброса флага USART_SR.IDLE требуется произвести считывание из USART_DR.

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

Пример 1

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

Здесь можно скачать исходные коды в виде проекта VC6.0 (для компьютера) и в виде проекта Atollic TrueSTUDIO (для микроконтроллера). Проект для VC6.0 также может быть импортирован, например, в IDE Code::Blocks и скомпилирован с помощью MinGW.

Исходный код 1 для компьютера

Показать

Исходный код 1 для MCU

Показать

Пример 2

В этом примере микроконтроллер в ответ на любую строку, полученную от компьютера, отвечает сообщением "Aha!", за исключением строки "Hello, MCU!", в ответ на которую микроконтроллер отправляет компьютеру строку "Hello, PC!". Имейте в виду, в строке после запятой идёт пробел.

Исходный код 2 для компьютера

Для работы с COM-портом в программе используется тот же самый класс, что и в первом примере. Он только вынесен в отдельный h-файл, чтобы не загромождать основной файл программы.

Показать

Исходный код 2 для MCU

Показать
author: hamper; date: 2016-01-24; modified: 2016-01-27
  @Mail.ru