Управление текстовыми командами (USART на STM32)

В процессе изучения микроконтроллеров STM32 многие могут заметить (а многие по этой причине и выбрать эти микроконтроллеры), что в отличие от привычных для нас AVR, PIC они имеют по несколько модулей USART, I2C, SPI. Так микроконтроллер STM32F103C8T6 имеет два модуля SPI, два модуля I2C и три модуля USART. И если, например, к интерфейсу I2C можно подключить без проблем несколько устройств одновременно, то иметь больше одного модуля USART иногда очень полезно, а в нашем примере их даже три (Medium-density device), а вообще может быть и пять, если взять другой более крупный микроконтроллер STM32 (High-density device).

Сегодняшнее устройство не слишь полезное, сколько обучающее, потому что полезного делает не много. Задача, представленной ниже, схемы управлять светодиодом на минимальной отладочной плате посредством текстовых команд, поступающих по UART с персонального компьютера (ноутбука).

Прежде чем приступить к программной части необходимо собрать аппаратную часть, а именно подготовить схему. При использовании отладочных плат необходимый минимальный набор радиоэлементов должен присутствовать, поэтом в этом случае можно просто подсоединить LCD дисплей, блок питания, программатор и переходник USB-UART.

Если же Вы собираете схему на собственной плате, обязательно должны присутствовать конденсаторы по питанию. Резистор R5 подтягивает вывод BOOT0 к земле, что обеспечивает выполнение программы из flash памяти, при этом уровень на выводе PB2 (BOOT1) не учитывается и может быть как нулем, так и единицей (при комбинации нулей и единиц на BOOT0 и BOOT1 обеспечивается выполнение программы из разных областей памяти при включении питания – flash, SRAM, ISP). Кнопка S1 необходима лишь для удобства – после прошивки микроконтроллера его необходимо перезапустить, что и делается при нажатии на эту кнопку. Для обеспечения заданного режима по питанию используется стабилизатор напряжения AMS1117-3,3. LCD дисплей используется на базе микроконтроллера HD44780, в моем варианте это 2004а – четыре строки по двадцать символов. В данной ситуации микроконтроллер STM32 питается от напряжения 3,3 вольта, а LCD дисплей от напряжения 5 вольт и при этом взаимодействуют друг с другом. Дело в том, что большинство выводов микроконтроллера толерантные к уровням напряжения 5 вольт. Подключение LCD  дисплея к микроконтроллеру осуществляется по стандартной 4-х битной схеме. Резистор R1 ограничивает ток подсветки дисплея, подстроечный резистор R2 задает контраст символов на экране. Светодиод в данном случае является исполнительным элементом, резистор R6 ограничивает ток, протекающий через светодиод, чтобы он не вышел из строя. Вариант подключения светодиода взят в соответствии с подключением на отладочной плате, которую я буду использовать. Логическая единица будет выключать светодиод, а логический ноль будет включать светодиод.

Дополнительно к схеме нам понадобится программатор (ST-link v2) и преобразователь USB-UART.

Собранная схема на минимальной отладочной плате:

Начнем с использования одного модуля USART (USART1). Модуль USART1 подключается к выводам PA9 (TxD) и PA10 (RxD) (CK, CTS, RTS не трогаем, нет необходимости). Кроме этого модуль USART1 можно переназначить на другие выводы – PB6 (TxD) и PB7 (RxD) с помощью ремапа – для этого необходимо обозначит альтернативные функции для этих выводов. Могут случаться ситуации, когда это может облегчить трассировку печатной платы.

Итак, чтобы запустить модуль USART1 (или любой другой аналогично), необходимо провести инициализацию с заданными настройками, для этого нам необходимо настроить выводы микроконтроллера для модуля USART1 и сам модуль USART1.

В первую очередь необходимо определить на каких шинах тактируется USART который мы хотим использовать.

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

void init_usart() {

GPIO_InitTypeDef PORT; //Структура содержащая настройки порта
USART_InitTypeDef USART; //Структура содержащая настройки USART

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //Включаем тактирование порта USART1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Включаем тактирование порта A

//Пины PA9 и PA10 в режиме альтернативных функций – Rx и Tx USART’а
GPIO_StructInit(&PORT);
// задаем параметры выводов
PORT.GPIO_Pin = GPIO_Pin_9;
PORT.GPIO_Mode = GPIO_Mode_AF_PP;
PORT.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA , &PORT);

PORT.GPIO_Pin = GPIO_Pin_10;
PORT.GPIO_Mode = GPIO_Mode_IN_FLOATING;
PORT.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA , &PORT);

//Настройка USART
USART_StructInit(&USART);
USART.USART_BaudRate = 9600; //Скорость обмена 9600 бод
USART.USART_WordLength = USART_WordLength_8b; //Длина слова 8 бит
USART.USART_StopBits = USART_StopBits_1; //1 стоп-бит
USART.USART_Parity = USART_Parity_No ; //Без проверки четности
USART.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Без аппаратного контроля
USART.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //Включен передатчик и приемник USART2
USART_Init(USART1, &USART);

USART_Cmd(USART1, ENABLE); //Включаем UART

}

Функции отправки данных достаточно простые

void send(char chr) {
while(!(USART1->SR & USART_SR_TC));
USART1->DR = chr;
}

void send_str(char* str) {
int i=0;
while(str[i])
send(str[i++]);
}

Теперь вся суть заключается в приеме и обработке полученной информации. Мы принимаем некоторое количество символов, которые образуют понятное для нас слово (компьютеру все равно что понимать, если это прописано в коде), далее строка обрабатывается и сравнивается со строкой привязанной к той или иной команде, заложенной в микроконтроллере. Строки могут быть разной длины, поэтому так же необходимо определять, что это конец. Один из способов в конце строки ставить какой-то заключительный символ, например, как в этом материале символ слэш, имеющий код 47 по таблице ASCII. Таким образом, можно формировать строки-команды различной длины, понятные любому человеку — написал «зажги, пожалуйста, светодиод» и светодиод горит. Либо формировать пароль при включении устройства, либо ещё много различных способов применения. Данные принимаются в прерывании.

// обработчик прерывания юарт1
void USART1_IRQHandler()
{
//Проверяем, действительно ли прерывание вызвано приемом нового байта
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
//USART1->DR = USART1->DR; //эхо
usartData = USART_ReceiveData(USART1);

// послений символ строки должен быть заведомо известный, чтобы корректо обрабатывать данные (энтер или другой символ)
if (usartData == 47) // если принимаем последний символ строки или команды, то совершаем действие
{
// при этом последний принятый байт не заносится в строку
usart_buf[usart_bit++] = 0; // делаем нуль-терминированную строку
usart_bit=0; // обнуляем счетчик символов строки
//————————————
send_str(«String: «); send_str(usart_buf); send(13); // отзыв обратно в терминал и символ энтера

// здесь задумка такая, чтобы выводить в 4 строчки экрана команды или сообщения
// последнее сообщение всегда на 4й строке, при появлении нового все принятые строки поднимаются вверх
// таким образом, наблюдаем текущую строчку и 3 предыдущих
for(t=0;t<32;t++) {buf1[t]=buf2[t];} // при приеме новой строки передвинуть вверх предыдущие и вывести все далее на экран lcd
for(t=0;t<32;t++) {buf2[t]=buf3[t];}
for(t=0;t<32;t++) {buf3[t]=buf4[t];}
for(t=0;t<32;t++) {buf4[t]=usart_buf[t];}
lcd_clear();
lcd_set_xy(0,0);
lcd_out(«> «);
lcd_out(buf1);
lcd_set_xy(0,1);
lcd_out(«> «);
lcd_out(buf2);
lcd_set_xy(0,2);
lcd_out(«> «);
lcd_out(buf3);
lcd_set_xy(0,3);// выводим на экран принятую строку
lcd_out(«> «);
lcd_out(buf4);

com_exe(usart_buf); // проверка на наличие команды и ее выполнение
//————————————
usartData=0; // очищаем последний принятый байт
memset(usart_buf, 0, sizeof(usart_buf)); /*Очищаем буфер*/
}
else
{
// если строка или команда все ещё не принята
// Складываем символ в приёмный буфер
usart_buf[usart_bit++] = usartData; //Помещаем принятый байт в буфер.
//usart_bit++; //Наращиваем счётчик байтов буфера.
}

}
}

В данном случае LCD дисплей используется для визуализации принятой информации, некоторое подобие терминала.

В прерывании присутствует функция com_exe, в которой и прописана обработка и выполнение команд, которые закладываются в микроконтроллере. В данном случае это простые команды управления светодиодом.

// функция обработчик команд, поступаемых по уарт, сравнивает строки буфера и выполняет действие
void com_exe (char *cmd)
{
if(strcmp(usart_buf,»led_on»)==0) //Если пришла команда
{GPIO_WriteBit(GPIOA,GPIO_Pin_1,Bit_RESET);}
if(strcmp(usart_buf,»led_off»)==0) //Если пришла команда
{GPIO_WriteBit(GPIOA,GPIO_Pin_1,Bit_SET);}
if(strcmp(usart_buf,»blink»)==0) //Если пришла команда
{for(t=0;t<10;t++) {GPIO_WriteBit(GPIOA,GPIO_Pin_1,Bit_RESET); delay(250); GPIO_WriteBit(GPIOA,GPIO_Pin_1,Bit_SET); delay(250);}}
if(strcmp(usart_buf,»clear»)==0) //Если пришла команда
{lcd_clear();
memset(buf1, 0, sizeof(buf1));
memset(buf2, 0, sizeof(buf2));
memset(buf3, 0, sizeof(buf3));
memset(buf4, 0, sizeof(buf4));
lcd_set_xy(0,0);
lcd_out(«> «);
lcd_set_xy(0,1);
lcd_out(«> «);
lcd_set_xy(0,2);
lcd_out(«> «);
lcd_set_xy(0,3);
lcd_out(«> «);}

}

Пример очень простой, но при желании таким способом можно выполнять действия любой сложности. Данный материал может быть очевидным для опытного программиста, но для новичка это не всегда очевидно.

К статье прилагается исходный код и небольшое видео работы представленного алгоритма.


Список радиоэлементовОбозначение
Тип
Номинал
Количество
ПримечаниеМагазинМой блокнот

IC1
МК STM32STM32F103C81
VR1
Линейный регуляторAMS1117-3.31
HG1
LCD-дисплей2004a1
R1
Резистор22 Ом1
R2
Переменный резистор10 кОм1
R3, R5, R6
Резистор10 кОм3
R4
Резистор100 Ом1
R7
Резистор390 Ом1
C1, C3, C7-C10
Конденсатор100 нФ6
C2
Электролитический конденсатор220 мкФ1
C4
Электролитический конденсатор10 мкФ1
C5, C6
Конденсатор22 пФ2
Z1
Кварцевый резонатор8 МГц1
S1
Тактовая кнопка1
HL1
СветодиодЗеленый1
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

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

Ваш адрес email не будет опубликован.