一帧数据接收方法

最近在做485数据通讯,遇到一些通讯问题,特意去查找资料,一帧数据接收有三种方法,现分享如下:
第一种方法:根据帧头和帧尾进行校验,
串口发送2字节例如(AA ,BB),然后程序对每2个字节进行判断,例如设定一个起始位例如AA,当程序收到AA,起始条件成立,开始接收数据,在设定一个终止位BB,当程序收到BB,终止条件成立,程序停止接受数据,然后把收到的数据放到一个数组里面,对收到的数据进行CRC校验,校验成立,则对收到的数据进行处理
程序如下:

if(USART_GetITStatus(RS485_USART_SOURCE, USART_IT_RXNE) != RESET)
	{
		USART_ClearITPendingBit(RS485_USART_SOURCE, USART_IT_RXNE);
		
		if(USART_GetFlagStatus(RS485_USART_SOURCE, USART_FLAG_ORE) != RESET) //Òç³ö´íÎó±ê־λ
		{
			USART_ClearFlag(RS485_USART_SOURCE, USART_FLAG_ORE);
		}
		
		temp_rec = USART_ReceiveData (RS485_USART_SOURCE);
	
		switch(temp_rec)
		{		
			case __Start://ÊÕµ½Æðʼ룬½ÓÊÕÊý¾Ý¿ªÊ¼
				if(!CommuSta.bRecOn)
				{
					CommuSta.bRecOn = SET;// ±íʾÕýÔÚ½ÓÊÕÊý¾Ý
					len = 0;
					aRxBuf[len++] = temp_rec;
				}
				break;

			case __Stop://ÕÒµ½ÖÕֹ룬½ÓÊÕÊý¾Ý½áÊø
				if(CommuSta.bRecOn)
				{
					CommuSta.bRecOn = RESET; // ½ÓÊÕÊý¾Ý½áÊø
					CommuSta.bRecEnd = SET;  // Ò»Ö¡Êý¾ÝÊÕÍê

					aRxBuf[len] = temp_rec;
					gRecBufLen = ++len;
					len = 0;
				}
				break;

但是程序出问题了,原因是发送过来的指令起始位与终止位之间有字节与起始位或终止位相同,l例如7E(起始位) 01 B4 03 +CRC校验(CD 7E)+7F(终止位),CRC校验的7E与起始位相同,程序接收数据又重新开始,所以出错,因为是一个字节一个字节的接收数据,所以对帧头和帧尾进行判定有时会出错。
第二种方法:使用串口帧空闲中断
使能串口帧空闲中断,当接收一帧数据后,串口会产生一次中断,根据是否产生中断来判断是否接收一串完整的数据,这种方法不存在方法1的问题,推荐使用
第三种方法:根据接收到的字符之间的间隔进行判断
串口数传输都是使用标准波特率,因此串口传输一帧数据时,字符与字符之间的时间间隔是一个固定值,我们可以根据串口的波特率去计算串口每个字符的间隔时间,在数据接收的过程中判断接收的两个字节之间间隔大于3.5个字符间隔时间,则认为当前数据帧传输完毕

### 回答1: HAL库提供了许多关于串口的函数,可以通过串口完成一帧数据接收,具体步骤如下: 1. 定义接收缓冲区和接收计数器。缓冲区的大小至少应该是一帧数据的大小,接收计数器用于统计已经接收了多少字节。 2. 配置串口,设置波特率、奇偶校验等参数。可以使用HAL库提供的函数来完成串口配置。 3. 开启串口中断。在接收数据过程中,串口会不断产生中断,通过中断处理函数来处理接收数据。 4. 编写中断处理函数。在中断处理函数中,首先读取接收寄存器中的数据,然后将数据存储到接收缓冲区中。接着判断是否接收一帧完整的数据,如果数据接收完整,则对数据进行处理,否则继续等待数据。 5. 在主函数中循环检测数据是否接收完成。当接收计数器等于一帧数据的大小时,认为数据接收完整,可以进行下一步操作。 总之,在使用HAL库进行串口接收一帧数据时,需要定义接收缓冲区和接收计数器,配置串口,开启串口中断,编写中断处理函数和在主函数中循环检测数据是否接收完成。 ### 回答2: HAL库是基于STM32标准固件库的一个高级抽象层,提供了丰富的功能接口,方便了开发者针对STM32微控制器开发应用程序。下面我将介绍使用HAL库串口接收一帧数据的步骤。 1. 配置串口:首先我们需要配置串口接口,确定波特率、数据位、停止位等参数。 ``` /* UART7初始化设置 */ huart7.Instance = UART7; huart7.Init.BaudRate = 115200; huart7.Init.WordLength = UART_WORDLENGTH_8B; huart7.Init.StopBits = UART_STOPBITS_1; huart7.Init.Parity = UART_PARITY_NONE; huart7.Init.Mode = UART_MODE_RX; huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart7.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart7) != HAL_OK) { Error_Handler(); } ``` 2. 等待数据:使用`HAL_UART_Receive()`函数等待数据,当有数据到达时会调用中断处理函数。 ``` /* 在主函数中调用 */ HAL_UART_Receive_IT(&huart7, rx_buffer, 10); // 接收10字节 ``` 3. 中断处理函数:数据到达时会调用中断处理函数,在中断处理函数中读取数据。 ``` /* 在stm32f4xx_it.c中实现中断处理函数 */ void UART7_IRQHandler(void) { /* 判断是否是接收中断 */ if(__HAL_UART_GET_FLAG(&huart7, UART_FLAG_RXNE) != RESET) { HAL_UART_IRQHandler(&huart7); } } /* 重新定义HAL库中的回调函数 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* 在此处读取数据 */ } ``` 这样,我们就可以使用HAL库串口接收一帧数据了。需要注意的是,串口使用时需要根据实际情况进行配置,同时在中断处理函数中读取数据时需要特别小心,防止丢失数据。 ### 回答3: HAL库是一种使嵌入式系统的开发更容易的库。HAL库的串口接收函数包括如下几个步骤: 1. 创建串口句柄。首先,需要定义一个USART_HandleTypeDef的结构体,在结构体中设置串口的参数(波特率、数据位数、停止位数等),然后调用HAL_UART_Init函数,创建一个串口句柄。 2. 在串口中断回调函数中获取数据。HAL库的串口接收是通过中断来完成的。每当有数据到达串口寄存器时,就会触发一个中断。HAL库中已经提供了中断回调函数,在其中获取数据。当数据成功接收到后,会调用USARTx_IRQHandler回调函数。 3. 在中断回调函数中读取数据。通过句柄中的Instance属性,能够轻易地找到所对应的串口,并从中读取数据。通常情况下,我们从串口缓冲区中获取数据,并将其存储在一个缓存数组中,直到接受完毕。在获取数据的时候,需要考虑到数据可能会分帧接收,因此需要作出相应的操作,以区分数据帧的开始和结束。 4. 对数据帧进行解析。在帧数据中,需要解析出数据的有效负载,并对其进行相应的处理。处理的方式因应用而异,通常情况下可以通过协议完成这一操作。 5. 结束串口接收。一旦一个数据帧被接收并处理,需要清空缓存区并准备接收一帧。当所有的数据都被接受完毕后,应该调用HAL_UART_Receive_IT函数重新开启串口接收中断。 需要指出的是,串口接收并不总是一帧一帧地进行,可能会出现部分帧或多帧数据同时到达串口,此时需要在中断回调函数中分析数据的完整性,对数据进行处理,确保正在处理的是一完整帧数据,避免出错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值