最近在做电赛,发现一些同学在解决STM32和OpenMV通信或者其他模块串口通信时,不会写串口通信的数据处理代码,我今天就分享一下我常用的串口通信数据处理代码(主要是思路)

[TOC]

一、串口通信第一步—配置双方串口初始化

stm32 串口初始化我就不详细说了,因为在许多地方都能找到配置源码,而且今天主要讲的是串口通信处理数据的思路,了解了之后,不论什么板子(51 or 430)都可以使用这个逻辑

二、接收中断配置

以下是一段我使用到的stm32和接收蓝牙数据的接收中断

下面的代码是: 串口接收代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
u8 USART1_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.(一般给200,接收数据量大就增加)
u16 USART1_RX_STA; //接收状态标记

void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART1_RX_STA&0x8000)==0)//接收未完成
{
//上次数据未处理则退出
if(Res==0x0a)
{
USART1_RX_STA|=0x8000;
}
else
{
USART1_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART1_RX_STA++;
if(USART1_RX_STA>(USART_REC_LEN-1))
USART1_RX_STA=0;
}
}
}
}

分开讲解代码:

u8 USART1_RX_BUF[USART_REC_LEN];
这句是接收缓存,暂时存放你所接收到的信息,他的长度必须要大于串口每次接收到完成数据的长度

u16 USART1_RX_STA;
接收状态:RX STATE 这个是很重要的一个点,他的最高一位或者几位用来保留接收数据的状态,剩下的用来保留接收数据的长度信息。一般最高1位保存结尾信息,默认置0,在接收到我们定义的结尾标志码的时候把他置1(表示接收完成一组数据,等待处理),然后在每次进入到接收中断里面的时候先判断这个位是不是已经置位了,如果已经置位了表示缓存里面已经有一组数据未处理,则不会继续接收下面的数据。

具体的判断代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if((USART1_RX_STA&0x8000)==0)//判断缓存是否为空
{
//首先判断本次接收的内容是不是结尾码0x0a
if(Res==0x0a)
{
USART1_RX_STA|=0x8000;//如果是把最高位置1表示接收完成一组数据
}
else
{
//不是则把当前的数据按照顺序放入缓存里面
//记录数据长度,判断是否超出长度,超出则清除最高位,缓存重新接收
USART1_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART1_RX_STA++;
if(USART1_RX_STA>(USART_REC_LEN-1))
USART1_RX_STA=0;
}
}

三、接收完成后数据的处理

数据处理放在主函数里面处理,可以设定一个扫描周期,判断STA的最高位是不是被置位,置位了之后就执行数据处理函数。
代码如下

1
2
3
4
5
6
7
8
if(USART1_RX_STA&0x8000)
{
//处理数据的函数(用户自定义)
X=(USART2_RX_BUF[1]-'0')*100+(USART2_RX_BUF[2]-'0')*10+(USART2_RX_BUF[3]-'0');
J=(USART2_RX_BUF[5]-'0')*100+(USART2_RX_BUF[6]-'0')*10+(USART2_RX_BUF[7]-'0');
//清除接收完成状态位,等待下一次接收完成
USART1_RX_STA=0;
}

串口接收的处理函数基本上就这些内容,按照这个方式来写,基本上所有的串口通信都可以套用,稳定又方便!!!

wechat