STM32. 4. Последовательный порт (UART)

STM32. 3. Порты ввода-вывода (GPIO)

Одним из самых универсальных и распространенных портом в наше время является последовательный порт – UART. Хоть самая известная его реализация всё менее и менее сейчас популярна – COM порт (Rs-232), то остальные его реализации, и сам чистый UASRT, всё ещё очень популярны и востребованы.

Пример использование UART в STM32

Пример использование UART в STM32

В статье пойдёт речь об использование UART на микроконтроллерах STM32 с помощью Standard Peripheral Library библиотеки.

Подключаться к UART STM контроллера будем по средствам старого доброго преобразователя USB-UART cp2102 , кому больше нравиться, или есть под рукой, ft232 , RS-232 🙂 , или любой другой преобразователь или способ – пожалуйста.

Преобразователь USB-UART на cp2102

Преобразователь USB-UART на cp2102

На ARM’мах обычно бывает много различных портов и не по одному, не исключение и UART. На STM32F100RB их может быть до 3-х штук. В примере задействуем первый.

Схема будет выглядеть следующим образом:

Схема

Схема

Детали перечислять смысла нет, т.к. контроллер установлен на STM32vlDiscovery, а устройство преобразователя можно посмотреть в соответствующей статье — USB-UART на cp2102 .

Перейдём к коду.

Первым делом нужно UART инициализировать. Начнём с конфигурирования выводов порта. Но с самого начала объявим структуры для работы с портами ввода-вывода и самим UART’ом:

GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

Подадим питание и тактирование:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

Приступим к конфигурированию выводов:

//Configure GPIO pin 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;	//	Tx
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	//	Rx
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);

9 вывод порта A будет альтернативным выходом для линии Tx, а 10 вывод – входом Rx.

Теперь сможем перейти к настройке последовательного порта:

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);

Порт настроен на скорость 9600 бод. Применена стандартная 8-ми битовая посылка с одним стоп битом и без контроля чётности (8N1). Т.к. порт асинхронный – не управляем передачей данных. И использована двухсторонней связь. Подробнее о настройках смотрите далее.

Основные настройки порта:

USART_BaudRate – задаём скорость в бодах;
Самые распространённые скорости: 9600, 19200, 38400, 57600, 115200
USART_WordLength – длина посылки, может быть

  • USART_WordLength_8b – 8 бит (стандартная)
  • USART_WordLength_9b – 9 бит

USART_StopBits – стоп бит

  • USART_StopBits_0_5 – половина стоп бита
  • USART_StopBits_1 – 1 (стандартная)
  • USART_StopBits_1_5 – 1,5
  • USART_StopBits_2 – 2

USART_Parity – чётность

  • USART_Parity_No – нет контроля чётности (стандартная)
  • USART_Parity_Even – чётный (в посылке чётное количество единиц или нулей)
  • USART_Parity_Odd – нечётный (в посылке нечётное количество единиц)

USART_HardwareFlowControl – аппаратное управление передачей данных

  • USART_HardwareFlowControl_None – не используется (стандартная)
  • USART_HardwareFlowControl_RTS – использовать линию запроса на передачу
  • USART_HardwareFlowControl_CTS – использовать линию готовности приёма
  • USART_HardwareFlowControl_RTS_CTS – использовать обе линии

USART_Mode – режимы работы порта, а точнее указываем, как он будет работать:

  • USART_Mode_Rx – разрешить приём данных
  • USART_Mode_Tx – разрешить передачу данных

(Помечена самая распространённая настройка порта.)

Из SPL библиотеки доступны следующие основные функции для работы с портом:
USART_SendData(USARTx, c) – отправка байта
USART_ReceiveData(USARTx) – приём байта
Где:
USARTx – используемый порт
с – отправляемый байт
вторая функция возвращает прочитанный байт.

Для корректной работы во время отправки и приёма данных следует контролировать флаги готовности портов. Для запроса флага служит функция
USART_GetFlagStatus(USARTx, flag)
Которая, для указанного порта USARTx, проверяет наличие флага flag и возвышает значение SET или RESET.

  • USART_FLAG_CTS – обнаружены входные данные с помощью линии CTS (для синхронного режима)
  • USART_FLAG_LBD – обнаружен разрыв
  • USART_FLAG_TXE – регистр передачи данных пуст
  • USART_FLAG_TC – передача окончена
  • USART_FLAG_RXNE – приняты данные
  • USART_FLAG_IDLE – линия свободна
  • USART_FLAG_ORE – переполнение
  • USART_FLAG_NE – ошибка принятых данных (шум в принимаемом кадре)
  • USART_FLAG_FE – ошибка кадров (первый стоп-бит = 0)
  • USART_FLAG_PE – ошибка чётности

Добавив контроль основных флагов можно получить следующие функции для общения через последовательный порт:

void send_Uart(USART_TypeDef* USARTx, unsigned char c) // отправить байт
{
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){}
	USART_SendData(USARTx, c);
}

unsigned char getch_Uart(USART_TypeDef* USARTx)  //  получить байт
{
	while(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE) == RESET){}
	return USART_ReceiveData(USARTx);
}

Для отправки строк через UART можно использовать следующею функцию:

void send_Uart_str(USART_TypeDef* USARTx, unsigned char *s)
{
	while (*s != 0) 
		send_Uart(USARTx, *s++);
}

Пример её использования:

send_Uart_str(USART1,"alex-exe.ru\n");

Дополнительно могу представить ещё пару своих функции:
read_str_uart(USART_TypeDef* USARTx,unsigned char* s) – прочитать строку, функция читает до ввода [Enter]
unsigned long read_int_uart(USART_TypeDef* USARTx) – читает число, до ввода любого не цифрового символа, не более 8 цифр
send_int_Uart(USART_TypeDef* USARTx,unsigned long c) – отправить число
Где:
USARTx – порт
В первой функции s – ссылка на буфер приёма
В третьей функции c – отправляемое число
Пример использования

unsigned char Buffer[512];	//	Буфер
unsigned int a,b;
send_Uart_str(USART1,"alex-exe.ru\n");
send_Uart_str(USART1,"Enter string\n");
read_str_uart(USART1, Buffer);
send_Uart_str(USART1," Input string - ");
send_Uart_str(USART1, Buffer);
send_Uart(USART1,'\n');

send_Uart_str(USART1," Enter two numbers separated by a space\n");
a=read_int_uart(USART1);
b=read_int_uart(USART1);
send_Uart_str(USART1,"a + b = ");
send_int_Uart(USART1, a+b);
send_Uart(USART1,'\n');

Результат работы


alex-exe.ru
Enter string
qwerty
Input string – qwerty
Enter two numbers separated by a space
34 55
a + b = 89

Скачать файлы проекта

STM32. 5. Символьный дисплей HD44780

13 комментариев »

Alex_EXE | 03.09.2013 | STM32 |

13 комментариев на « STM32. 4. Последовательный порт (UART)»

  1. Алексей пишет 11.10.2015 в 21:44 #

    Отличная статья. Долго мучился с тем чтобы отправить в терминал цифры содержащиеся в переменной так как перепробовал мною терминалы понимают только ASCII соответственно когда в терминал приходили цифры содержащиеся в переменной вместо одыкватных данных бала либо тарабарщина либо вобщем-то ничего. В общем функция send_int_Uart просто спасение. Причём за два дня интенсивного поиска в интернете ничего похожего не нашёл. Виду чего удивляет что при количестве просмотро 10 898 никто так и не обмолвился добрым словом в адрес автора. Ну да ладно. Ещё раз огромная благодарность автору статьи. И ещё вопрос к автору и всем кто может чем либо помочь в том как писать свои библиотеки для STM32 что почитать по этой теме. В интернете нечего по этому поводу не нашёл.

  2. Dima пишет 02.07.2016 в 20:52 #

    Спасибо! Наконец у меня запустился uart ).

  3. Дмитрий пишет 17.07.2016 в 02:29 #

    Спасибо автору!
    действительно, очень хорошая статья, хороший пример кода, а комментариев хороших — мало. Неправильно это…
    Сайт много раз заинтересовывал своими статейками: все описано ёмко, кратко, с примерами и картинками. Автор, продолжай пожалуйста:)

  4. Prtro пишет 01.03.2017 в 18:55 #

    Статья отличная! автор молодец.

  5. Vasya пишет 02.05.2017 в 01:52 #

    А вот как бы написать свою программку под винду для сбора информации с ком-порта не используя визуалстудио, которая весит 20 ГБ?

  6. Alex_EXE пишет 04.05.2017 в 19:25 #

    Есть к примеру Bulder, установщик весит до гига. Можно поставить на Win7/8, т.к. сам времён Win98/XP.
    Есть другие языки и среды программирования, на визуал студии мир клином не сошёлся.

  7. Slava пишет 17.06.2018 в 14:41 #

    Спасибо автору, инфа полезная.

  8. Александр пишет 22.09.2018 в 16:08 #

    А куда выводится результат?

  9. Alex_EXE пишет 23.09.2018 в 23:47 #

    Обратно в порт.

  10. Александр пишет 29.09.2018 в 20:13 #

    Почему то у меня ничего не появляется

  11. Alex_EXE пишет 22.10.2018 в 01:34 #

    если ещё актуально:
    1. проверьте COM порт и Rs232-UART преобразователь или USB-UART преобразователь, или что используете.
    При замыкание линий Tx и Rx должен возвращаться отправленный символ.
    2. проверяйте распаян ли и пропаян ли UART на МК
    3. Используете ли Вы выбранный UART у МК или другой
    4. Проверяйте конфигурацию МК и работает ли он вообще, можно добавить в прошивку мигание светодиодом.
    5. Проверяйте конфигурацию выводов UART МК
    6. Проверяйте конaигурацию самого UART модуля и идёт ли на него тактирование
    7. можете добавить в main отправку какого-нибудь сообщения с интервалом примерно в секунду и проверить получаете ли Вы его.
    За более подробной консультацие пишите через обратную связь.

  12. ivan rusev пишет 15.07.2019 в 10:02 #

    почему по отправке строки пишет ошибку программирую в Atolica truestudio в cubemax в кубе.У вас библиотека spl я перевожу на LL.пишет ошибку

  13. Альберт пишет 26.08.2019 в 10:14 #

    Здравствуйте!
    Запускаю Ваш пример, в окно терминала(AL-terminal) выдает белеберду, но в терминале Termit 3.4 вроде все нормально, но дальше этой строки
    alex-exe.ru
    Enter string
    не идет, Keil 5.26, в чем может проблема?

Комментарии RSS

Оставьте отзыв