STM32. 4. Последовательный порт (UART)
STM32. 3. Порты ввода-вывода (GPIO)
Одним из самых универсальных и распространенных портом в наше время является последовательный порт – UART. Хоть самая известная его реализация всё менее и менее сейчас популярна – COM порт (Rs-232), то остальные его реализации, и сам чистый UASRT, всё ещё очень популярны и востребованы.
Пример использование UART в STM32
В статье пойдёт речь об использование UART на микроконтроллерах STM32 с помощью Standard Peripheral Library библиотеки.
Подключаться к UART STM контроллера будем по средствам старого доброго преобразователя USB-UART cp2102 , кому больше нравиться, или есть под рукой, ft232 , RS-232 🙂 , или любой другой преобразователь или способ – пожалуйста.
Преобразователь 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
Alex_EXE | 03.09.2013 | STM32 |
Алексей пишет 11.10.2015 в 21:44 #
Отличная статья. Долго мучился с тем чтобы отправить в терминал цифры содержащиеся в переменной так как перепробовал мною терминалы понимают только ASCII соответственно когда в терминал приходили цифры содержащиеся в переменной вместо одыкватных данных бала либо тарабарщина либо вобщем-то ничего. В общем функция send_int_Uart просто спасение. Причём за два дня интенсивного поиска в интернете ничего похожего не нашёл. Виду чего удивляет что при количестве просмотро 10 898 никто так и не обмолвился добрым словом в адрес автора. Ну да ладно. Ещё раз огромная благодарность автору статьи. И ещё вопрос к автору и всем кто может чем либо помочь в том как писать свои библиотеки для STM32 что почитать по этой теме. В интернете нечего по этому поводу не нашёл.
Dima пишет 02.07.2016 в 20:52 #
Спасибо! Наконец у меня запустился uart ).
Дмитрий пишет 17.07.2016 в 02:29 #
Спасибо автору!
действительно, очень хорошая статья, хороший пример кода, а комментариев хороших — мало. Неправильно это…
Сайт много раз заинтересовывал своими статейками: все описано ёмко, кратко, с примерами и картинками. Автор, продолжай пожалуйста:)
Prtro пишет 01.03.2017 в 18:55 #
Статья отличная! автор молодец.
Vasya пишет 02.05.2017 в 01:52 #
А вот как бы написать свою программку под винду для сбора информации с ком-порта не используя визуалстудио, которая весит 20 ГБ?
Alex_EXE пишет 04.05.2017 в 19:25 #
Есть к примеру Bulder, установщик весит до гига. Можно поставить на Win7/8, т.к. сам времён Win98/XP.
Есть другие языки и среды программирования, на визуал студии мир клином не сошёлся.
Slava пишет 17.06.2018 в 14:41 #
Спасибо автору, инфа полезная.
Александр пишет 22.09.2018 в 16:08 #
А куда выводится результат?
Alex_EXE пишет 23.09.2018 в 23:47 #
Обратно в порт.
Александр пишет 29.09.2018 в 20:13 #
Почему то у меня ничего не появляется
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 отправку какого-нибудь сообщения с интервалом примерно в секунду и проверить получаете ли Вы его.
За более подробной консультацие пишите через обратную связь.
ivan rusev пишет 15.07.2019 в 10:02 #
почему по отправке строки пишет ошибку программирую в Atolica truestudio в cubemax в кубе.У вас библиотека spl я перевожу на LL.пишет ошибку
Альберт пишет 26.08.2019 в 10:14 #
Здравствуйте!
Запускаю Ваш пример, в окно терминала(AL-terminal) выдает белеберду, но в терминале Termit 3.4 вроде все нормально, но дальше этой строки
alex-exe.ru
Enter string
не идет, Keil 5.26, в чем может проблема?