Главная » Микроконтроллеры
Призовой фонд
на март 2017 г.
1. UNI-T UT-39C
Паяльник
2. Тестер компонентов LCR-T4
Паяльник
3. 100 руб.
От пользователей

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

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

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

Теги:

Опубликована: 0 1
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (1) | Я собрал (0) | Подписаться

0
Публикатор #
На форуме автоматически создана тема для обсуждения статьи.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Pickit 2 - USB-программатор PIC-микроконтроллеров
Pickit 2 - USB-программатор PIC-микроконтроллеров
USB осциллограф DSO-2090 Набор 4WD Kit Bluetooth
вверх