STM32 (1) - Простая реализация приемопередатчика последовательного порта и связи

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


Предисловие
В STM32 связь через последовательный порт представляет собой USART, и STM32 может передавать параллельные данные через последовательный порт и другие устройства.Это полный дуплекс, асинхронное управление часами и двухточечная передача между устройствами. Соответствующие контакты STM32 — это клеммы RX и TX соответственно. Ресурсы последовательного порта STM32: USART1, USART2, USART3.

Несколько важных параметров последовательного порта:

Скорость передачи в бодах, скорость передачи данных через последовательный порт.
Простой, обычно высокий уровень
Стартовый бит, отмечающий начало кадра данных, фиксируется на низком уровне. Спадающий фронт генерируется, когда данные начинают отправляться. (ожидание -> стартовый бит)
бит данных, кадр данных отправки, 1 — высокий уровень, 0 — низкий уровень. Сначала низкий уровень.
Например, отправка фрейма данных 0x0F в фрейме данных — это линейность младшего разряда, то есть
контрольная цифра 1111 0000, которая используется для проверки данных и вычисляется по битам данных. Есть нечетность, четность и отсутствие четности.
Стоповый бит, используемый для интервала данных, фиксируется на высоком уровне. После отправки кадра данных генерируется нарастающий фронт. (передача данных -> стоповый бит)

1. Создайте файлы заголовков и исходные файлы последовательного порта

Откройте keil5, здесь я выбираю исходный код эксперимента Brother Atom в качестве основы для расширения:

Добавьте файлы .c и .h в раздел «Оборудование» слева, адрес /hardware, подтвердите добавление.
вставьте сюда описание изображения

2. Напишите исходные файлы

Сначала напишите функцию для инициализации последовательного порта 2:
1. Настройте RCC часов, чтобы открыть порт GPIO, соответствующий USART и TX/RX.

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//USART2挂载APB1总线
  RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOA挂载APB2总线
  //对于哪个应用挂载哪个APB总线,可以根据代码自动补全功能快捷判断

2. Инициализируйте
соответствующие контакты порта GPIO usart2 как PA2 и PA3. Режим вывода RX должен быть сконфигурирован как плавающий вход или вход pull-up. Режим контакта TX настроен как мультиплексированный двухтактный выход.
Сначала вам нужно настроить структуру: обратите внимание на структурную переменную GPIO:
вставьте сюда описание изображения
затем выполните различные настройки для TX/RX. следующее:


	GPIO_InitTypeDef  GPIO_InitStructure;//声明一个结构体对象
	//TX端口-PA2
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//这个对象的成员变量GPIO_Pin取值为pin2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//模式为复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHZ速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//RX端口-PA3
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//这个对象的成员变量GPIO_Pin取值为pin3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//模式为浮空输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHZ速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);

3. Инициализация последовательного порта
Выше приведена инициализация портов отправляющей и принимающей сторон, здесь необходимо инициализировать последовательный порт, чтобы активировать функцию последовательного порта. Как и в случае с GPIO, сначала создайте экземпляр объекта структуры последовательного порта, а затем настройте информацию о переменных-членах.

Его переменные-члены включают:
USART_BaudRate: Скорость передачи данных, используемая для последовательной связи, обычно составляет 9600 или 115200, здесь 9600
USART_HardwareFlowControl: Следует ли выбирать аппаратный триггер потока, обычно это не выбрано, поэтому не выбирайте аппаратный триггер потока.
USART_Mode: Режим последовательного порта, режим отправки или режим приема, или оба варианта
USART_Parity: Бит четности, вы можете выбрать проверку четности или отсутствие проверки. Если нет требований, нет прямой проверки
USART_StopBits: есть 1, 0,5 и 2 стоповых бита Здесь мы выбираем 1 стоповый бит
USART_WordLength: есть 8 и 9 бит данных на выбор

USART_InitTypeDef  USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//收发模式并存
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//八位数据位
USART_Init(USART2,&USART_InitStructure);

4. Знакомство с механизмом прерывания
Целью прерывания инициализации последовательного порта является гарантия того, что когда последовательный порт получает данные, он может своевременно ответить и обработать их. Если прерывание не инициализировано, программа может только определить, поступают ли данные на последовательный порт в режиме опроса, что займет больше ресурсов ЦП и может привести к потере данных. После прерывания инициализации, когда последовательный порт получает данные, система немедленно войдет в процедуру обработки прерывания для обработки, что повысит эффективность обработки и точность данных последовательного порта.
Когда данные получены, срабатывает прерывание приема, и основная программа приостанавливает выполнение. После получения данных основная программа возобновляет выполнение. При получении данных срабатывает прерывание.
Инициализируйте прерывание и настройте переменные-члены:

	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启串口2的中断接收
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel =USART2_IRQn;//选择串口2的中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级
	NVIC_Init(&NVIC_InitStructure);

Напишите функцию обслуживания прерывания
Когда последовательный порт получает данные, он запускает процедуру обслуживания прерывания USART2. Внутри этой функции сначала оцените, установлен ли флаг RXNE, если он установлен, это означает, что данные получены, сохраните данные в переменной RX_Data и установите для флага значение 1. Затем очистите бит флага RXNE, вызвав функцию USART_ClearITPendingBit, чтобы она могла правильно определить, будут ли новые данные поступать на последовательный порт в следующий раз.

void USART2_IRQHandler(void){
    
    
	if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)   //RXNE 标志位为1 表示可以接收数据
	{
    
    
		u8 RX_Data=USART_ReceiveData(USART2);
		u8 Flag=1;
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);  //清除RXNE标志位
	}
	}
	

Кроме того, функция последовательного порта USART1, написанная Atomic Brother, выглядит следующим образом:

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
    
    
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
    
    
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
    
    
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
    
    
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{
    
    	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
    
    
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 

Этот код является функцией обработчика прерываний USART1. Когда последовательный порт получает данные, он запускает процедуру обработки прерывания USART1. Внутри этой функции сначала оцените, установлен ли флаг RXNE, если да, то это означает, что данные получены, и данные сохранены в переменной Res. Затем с помощью бита флага состояния USART_RX_STA оценивается, был ли получен и сохранен в буфере USART_RX_BUF полный кадр данных. При этом также необходимо обратить внимание на ситуацию с получением ошибок, при возникновении ошибки прием необходимо перезапустить. Наконец, если операционная система поддерживается, функции OSIntEnter и OSIntExit необходимо вызывать в начале и в конце функции, чтобы операционная система могла правильно управлять обработкой прерываний.

Также обратите внимание, что при создании экземпляра структуры ее следует размещать в начале функции, иначе будет сообщено об ошибке. Более того, прерывание в основном используется для приема данных, а последовательный порт не нужно прерывать для отправки данных.

Напишите функцию отправки данных последовательного порта

void USART2_SendByte(USART_TypeDef * USARTx,uint8_t data){
    
    //串口收发每次都是一个字节,即8位数据
	
		USART_SendData(USARTx,data);
	//0 表示数据还未转移到移位寄存器 循环等待 1 数据已经被转移到了移位寄存器可以发送数据
	while(!USART_GetFlagStatus(USARTx,USART_FLAG_TXE)); 
	}

Этот код представляет собой функцию, используемую для отправки байта данных в последовательный порт USARTx. В функции сначала вызовите функцию USART_SendData, чтобы записать данные в регистр USARTx. Затем проверьте, установлен ли флаг USART_FLAG_TXE с помощью циклического ожидания, если он был установлен, это означает, что данные были успешно переданы в сдвиговый регистр, и можно выполнять следующую передачу. В противном случае вам нужно продолжать ждать, пока не будет установлен флаг TXE. Функция этой функции заключается в реализации простой функции отправки через последовательный порт.

3. Основная программа

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "usart2.h"
/************************************************
 ALIENTEK精英STM32开发板实验1
 跑马灯实验
 技术支持:www.openedv.com
 淘宝店铺:http://eboard.taobao.com 
 关注微信公众平台微信号:"正点原子",免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者:正点原子 @ALIENTEK
************************************************/
 int main(void)
 {
    
    	
	delay_init();	    //延时函数初始化	  
	LED_Init();		  	//初始化与LED连接的硬件接口
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	Init_USART2();
	while(1)
	{
    
    
		USART2_SendByte(USART2,0x08);
	}
 }
 

Видно, что на последовательный порт постоянно отправляется 8.

Подведем итог

В этой статье кратко представлены соответствующие методы stm32 для записи последовательной связи, но не затрагиваются более сложные приложения.В следующей статье будет подробно рассмотрено применение последовательных портов с использованием stm32 и esp8266 для завершения связи через последовательные порты.

Supongo que te gusta

Origin blog.csdn.net/qq_53092944/article/details/130154861
Recomendado
Clasificación