STM32的串口通讯协议

简单理解一下正点原子的串口通讯的协议代码,代码如下

void USART1_IRQHandler(void)
{
	u8 res;
	u16 USART_RX_STA=0;       //接收状态标记	
	u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节
	
	if(USART1->SR&(1<<5))	//接收到数据
	{	 
		res=USART1->DR; //接受到的数据给临时变量
		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;//接收数据错误,重新开始接收	  
				}		 
			}
		}  		 									     
	}

首先声明两个全局变量,1、extern u8 USART_RX_BUF[USART_REC_LEN],其中USART_REC_LEN为宏定义的最大字节数,USART_RX_BUF数组为数据接受缓冲器,将一次协议过程接受到的数据放入此数组,可用于主函数调用分析。2、extern u16 USART_RX_STA为接受状态标记,此变量为16位。当接受到的一个数据0x0d时bit14置1。当bit14为1且接受到的下一个数据为0x0a时,bit15置1,此时即可认为完成了一次通讯协议。

bit15bit14bit13~0
接受完成标志接受预完成标志接受有效数据个数
0x0a(ASCII码中的换行符)0x0d(ASCII码中回车符)最多16382个字节

临时变量u8 res用于存放接受到的每个数据。
if(USART1->SR&(1<<5))即每接收到一个字节就产生中断,把每个字节进入协议分析。
if((USART_RX_STA&0x8000)==0)“接受完成标志位“”为0也即未完成数据接收,那么进入协议,若此位为1则表面已经完成一次协议跳过之后分析,当主函数完成相应功能后,需要再次接收数据时置0。

if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了
			}

“接受预完成标志“为0则是还在正常接收数据中,即继续进行协议。若“接受预完成标志“为1,则是已经接收了0x0d,那么判断这次接收到的数据是否为0x0a,若不是那么说明数据接收发生错误,至此重新接收,将数据重头放入缓冲数据接收器覆盖之前的数据。若这次接收的数据是0x0a,那么接收完成标志置1,代表此次协议完成。

	
	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;//接收数据错误,重新开始接收	  
		}		 
			

若接收到的数据为0x0d则将“接受预完成标志“置1之后等待接收下一个字节。若接收到的数据不是0x0d则此数据为有效数据,将它放入“数据缓冲器“,[USART_RX_STA&0X3FFF]代表这是接收的第n个数据。if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;当接收到超过设置的最大字节数,代表接收错误则重新开始接收。

最后简单总结一下:每接收到一个字节便产生中断,将此接收到的数据进行协议分析,接收到的有效数据放入接收缓冲器(这是声明的外部数组),并且给USART_RX_STA即接受状态标志位加1,USART_RX_STA的0~13位代表这是接受到的第几个数据,若接收到的数据是0x0d则将bit14置1,此数据不是有效数据,有效数据位不会增加。之后的情况1、若下一个接收的数据是0x0a,则将bit15置1且代表此协议完成,在bit15未置0之前不再接收数据2、若下一个接收的数据是不是0x0a,则代表此次数据传输错误,则将USART_RX_STA清0,再次重新接收数据。
注意:
1、每次正常传输的数据必须以0x0d,0x0a为结尾
2、接收完成标志位也即USART_RX_STA第15位必须由主函数置0,在置0前不会再接收到数据
3、传输了0x0d未传输0x0a和传输的字节数超过设定数目都会发生传输错误,这会导致重新接收数据且重新的数据又从0开始覆盖接收缓冲器数组里(即之前的数据会被覆盖)
4、USART_RX_STAUSART_RX_BUF[USART_REC_LEN]必须声明外部变量才能在主函数使用

此协议可获得:
1、接收到了多少个字节的数据(也即USART_RX_STA里0~13bit的数量,在主函数可通过USART_RX_STA&0x3FFF表示)
2、接收到的数据(存放在接收缓冲器数组里,在此代码里为USART_RX_BUF[USART_REC_LEN] ,可在主函数里通过此数组进行处理)

### STM32 UART Communication Protocol Overview STM32微控制器系列广泛应用于嵌入式系统开发中,其UART(通用异步收发传输器)接口用于实现串行数据通信。通过配置USART外设模块可以轻松设置波特率、字长、停止位以及校验方式等参数[^3]。 对于基于STM32平台的开发者而言,在进行UART编程时通常会涉及到以下几个方面: - **初始化**:利用HAL库函数`MX_USARTx_UART_Init()`完成硬件资源分配及基本属性设定。 - **发送接收操作**:调用诸如`HAL_UART_Transmit()`, `HAL_UART_Receive_IT()`之类的API来执行同步或中断驱动的数据交换过程。 - **错误处理机制**:当发生溢出或其他异常情况时能够及时响应并采取相应措施恢复通讯链路正常工作状态。 下面给出一段简单的C语言代码片段展示如何向指定端口写入字符串消息: ```c #include "stm32f4xx_hal.h" UART_HandleTypeDef huart1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); char *msg = "Hello World!\r\n"; HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); while (1){} } // 配置USART1的具体参数... static void MX_USART1_UART_Init(void){ huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK){ Error_Handler(); } } ``` 此段程序实现了启动后自动发送一次问候语句至连接于USART1上的设备的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值