Рано или поздно у каждого разработчика появляется необходимость подключить свое устройство к компьютеру. Для этого можно использовать LPT, COM или USB порты. Если первый морально устарел и зачастую отсутствует на материнских платах, а последний слишком сложен для начинающего, то COM порт является наиболее подходящим. Он все ещё есть на материнских платах, и он относительно прост в использовании. Как и раньше, я не буду очень сильно углубляться в теоретические дебри, которых уйма на просторах интернета, а постараюсь максимально доступно объяснить основы работы на практике.
Постановка задачи:
1) Подключить STM32F4Discovery к компьютеру через COM порт;
2) Реализовать режим echo;
3) Набираемые символы должны сохраняться в текстовую переменную, по нажатию Enter в консоль должна вернуться полная строка;
4) При отправки строки “led” должны загореться 4 светодиода на плате.
Подключение к компьютеру является наиболее сложной частью задачи. У UART есть 2 основных вывода: Rx (Received Data) и Tx (Transmitted Data). Главная проблема – согласование уровней напряжения, потому что в порте компьютера оно составляет 12В, а в порте микроконтроллера — 3,3В. Для решения этой проблемы используется микросхема MAX3232. Схема переходника показана на рисунке.
Диод VD1 – индикатор питания, светодиод в корпусе 0805, VD2 – защита от переполюсовки, можно взять любой маломощный. Микросхема – MAX3232 в корпусе SO16.
К статье прилагается проект платы в Sprint Layout.
Плата выполнена на одностороннем стеклотекстолите толщиной 2мм. Ответная часть для COM порта берется для монтажа на провод и одевается на текстолит, получается компактно и аккуратно.
Заранее отмечу, что я не изготавливал этот переходник для урока, потому что у меня уже есть платка с аналогичной микросхемой, но такие переходники мною делались ранее.
У переходника 4 вывода:
1) Vcc – подключается к 3В питанию на отладочной плате;
2) Rx – подключается к Rx UART2 (PA3) микроконтроллера;
3) Tx – подключается к Tx UART2 (PA2);
4) GND – подключается к «земле» на плате.
Для связи с компьютером используется программа-терминал Putty.
Настройка:
Во вкладке Session выбираем Serial.
В строке Serial line пишем номер порта, к которому вы подключили плату.
В строке Speed пишем 9600 – это скорость работы.
Переходим во вкладку Serial.
Data bits ставим 8.
Stop bits – 1.
Parity и Flow control надо выставить None.
Нажимаем Open и получаем консоль.
Если подключить переходник к COM порту, выводы Vcc и GND подключить к плате, а Tx и Rx соединить, тогда то, что вы будете писать в консоли, будет возвращаться в нее же. Если при нажатии клавиш ничего не происходит и консоль остается чистой – ищите и исправляйте ошибку.
Итак, с подключением вроде справились. Теперь начинаем писать программу.
Первым делом нужно инициализировать UART, для этого создается функция:
//Инициализируем USART2
void usart_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //Структура содержащая настройки порта
USART_InitTypeDef USART_InitStructure; //Структура содержащая настройки USART
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Включаем тактирование порта A
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //Включаем тактирование порта USART2
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); //Подключаем PA3 к TX USART2
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); //Подключаем PA2 к RX USART2
//Конфигурируем PA2 как альтернативную функцию -> TX UART. Подробнее об конфигурации можно почитать во втором уроке.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Конфигурируем PA3 как альтернативную функцию -> RX UART. Подробнее об конфигурации можно почитать во втором уроке.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_StructInit(&USART_InitStructure); //Инициализируем UART с дефолтными настройками: скорость 9600, 8 бит данных, 1 стоп бит
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE); //Включаем UART
}
Готово, теперь для инициализации достаточно написать usart_init() в main.
В этой функции UART настраивается по дефолтным значениям. Для более тонкой настройки вместо:
USART_StructInit(&USART_InitStructure);
Пишем:
USART_InitStructure.USART_BaudRate = 9600; //Скорость обмена 9600 бод
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Длина слова 8 бит
USART_InitStructure.USART_StopBits = USART_StopBits_1; //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; //Включен передатчик и приемник USART2
Теперь надо научится отправлять в COM порт байты, а потом и строки.
//Функция отправляет байт в UART
void send_to_uart(uint8_t data)
{
while(!(USART2->SR & USART_SR_TC));
USART2->DR=data;
}
//Функция отправляет строку в UART, по сути пересылая по байту в send_to_uart
void send_str(char * string)
{
uint8_t i=0;
while(string[i])
{
send_to_uart(string[i]);
i++;
}
}
Принцип работы прост: send_to_uart отправляет в COM порт байт, а send_str пересылает строку по байту в send_to_uart.
Теперь нужно включить прерывание по приему сообщений от COM порта:
usart_init(); //Инициализируем UART
//Настраиваем прерывания по приему
__enable_irq(); //Глобальное включение прерывания
NVIC_EnableIRQ(USART2_IRQn); //Включаем прерывания от UART
NVIC_SetPriority(USART2_IRQn, 0); //Прерывание от UART, приоритет 0, самый высокий
USART2->CR1 |= USART_CR1_RXNEIE; //Прерывание по приему
Установка приоритета актуальна при использовании нескольких прерываний во избежание конфликта.
Теперь инициализируем порты, на которых висят светодиоды, как во втором уроке.
GPIO_InitTypeDef GPIO_InitStructure; //Структура содержащая настройки порта
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //Включаем тактирование порта D
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; //Выбераем нужные вывод
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //Включаем режим выхода
GPIO_Init(GPIOD, &GPIO_InitStructure); //вызов функции инициализации
И самое главное – функция обработки прерываний UART:
void USART2_IRQHandler (void)
{
char uart_data;
if (USART2->SR & USART_SR_RXNE) //Проверяем, прило ли чтонибудь в UART
{
USART2->DR = USART2->DR; //Echo по приему, символ отправленный в консоль вернется
uart_data=USART2->DR; //Считываем то что пришло в переменную…
uart2_rx_buf[uart2_rx_bit]=USART2->DR; //Помещаем принятый байт в буфер.
uart2_rx_bit++; //Наращиваем счётчик байтов буфера.
if(uart_data==’r’) //Если пришло сообщение о нажатии Enter…
{
GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //Сбрасываем все пины в «0»
if(strcmp(uart2_rx_buf,»led0r»)==0) //Если пришла команда «led0″
{
GPIO_SetBits(GPIOD, GPIO_Pin_12); //Подаем «1» на PD12
}
else if(strcmp(uart2_rx_buf,»led1r»)==0) //Если пришла команда «led1″
{
GPIO_SetBits(GPIOD, GPIO_Pin_13); //Подаем «1» на PD13
}
else if(strcmp(uart2_rx_buf,»led2r»)==0) //Если пришла команда «led2″
{
GPIO_SetBits(GPIOD, GPIO_Pin_14); //Подаем «1» на PD14
}
else if(strcmp(uart2_rx_buf,»led3r»)==0) //Если пришла команда «led3»
{
GPIO_SetBits(GPIOD, GPIO_Pin_15); //Подаем «1» на PD15
}
else
{
send_str(«n»); //Переходим на новую строку
send_str(«String: «);
send_str(uart2_rx_buf); //Отправляем ее обратно в консоль
}
memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); //Очищаем буфер
uart2_rx_bit=0; //Сбрасываем счетчик
send_str(«n»);
}
}
}
Вот и все, теперь запускаем консоль, прошиваем плату, подключаем и набираем строку, а далее жмем Enter и наслаждаемся результатом. Команды led0, led1, led2, led3 управляют светодиодами на плате. Как это все работает видно на видео. Исходники и плата прикреплены к статье.
Хочется отметить, что все наработки по данным урокам будут реализованы в плате расширения для STM32F4discovery о разработке которой можно почитать в этой теме
Прикрепленные файлы:
- COM_to_UART.rar (11 Кб)
- Урок_3.rar (171 Кб)