【STM32串口】使用状态机接收HEX数据包的编程思维

【STM32串口】使用状态机接收HEX数据包的编程思维

1.HEX数据

1.HEX模式/十六进制模式/二进制模式:以原始数据的形式显示文本模式/字符模式:以原始数据编码后的形式显示

image-20240707165700754

2.数据包

  1. 固定包长,含包头包尾

image-20240707165700754

  1. 可变包长,含包头包尾

image-20240707165730367

可变包长,若是接收的数据包中的数据与帧头帧尾一致,则可能会造成误判,数据发送错乱(这就需要加校验位,CRC校验),,如果采用固定包长则可以避免这一问题。

3.状态机

一个字节等于8位(0000 0000)uint8_t,0xFF

串口每收到一个字节,程序都会进一遍中断,在中断函数里我们可以拿到这个字节,但拿到之后,我们就退出了中断,对于上面数据包中的每个数据,都是独立的,很明显它具有前后关联性,包头、数据、包尾三种状态。此时我们需要有不同的处理逻辑,所以在程序中我们需要设计一个能记住不同状态的机制,在不同的状态执行不同的操作,同时还要进行状态的转移,这种程序思维就是状态机

image-20240707165150468

4.程序

关于使用if语句之后为什么是else if

程序是自上而下运行的,如果我们并列两个if的话,就会导致在状态1切换完之后,还没等到下一个数据到来,立马转到了状态2,这是我们不希望出现的一个状况。当然,如果使用switch case同样也可以实现

uint8_t Serial_TxPacket[4];				//FF 01 02 03 04 FE
uint8_t Serial_RxPacket[4]; 

void USART1_IRQHandler(void)
{
    //接收状态位,初始值为0,接收帧头,接收完后变为1,开始接收数据,接收完四个数据之后,变为2,开始等待帧尾
	static uint8_t RxState = 0; 
	static uint8_t pRxPacket = 0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		uint8_t RxData = USART_ReceiveData(USART1);
		
		if (RxState == 0)
		{
			if (RxData == 0xFF) //帧头来了
			{
				RxState = 1;
				pRxPacket = 0;
			}
		}
		else if (RxState == 1)
		{
			Serial_RxPacket[pRxPacket] = RxData;//把接收到的数据放到数组里面
			pRxPacket ++;
			if (pRxPacket >= 4)//接收的数据个数
			{
				RxState = 2;
			}
		}
		else if (RxState == 2)
		{
			if (RxData == 0xFE)
			{
				RxState = 0;
				Serial_RxFlag = 1;//接收完一个完整数据标志位
			}
		}
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
u16 USART_RX_STA = 0;       //接收状态标记
u8  RxFlag = 0, USART_RX_Total;

//id + x + y 240 * 160
void USART2_IRQHandler(void)                	//串口2中断服务程序
{
	u8 Res, FlagSt;

    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        Res =USART_ReceiveData(USART2);	//读取接收到的数据
        
        switch(RxFlag)
        {
            case 0:
                if(Res == 0xaa)
                    RxFlag = 1;		
                break;
            case 1:			
                if(Res == 0x55)
                    RxFlag = 2;
                else
                    RxFlag = 0;
                break;
            case 2:
                USART_RX_Total = Res;
                RxFlag = 3;
                break;
            case 3:
                USART_RX_BUF[USART_RX_STA ++] = Res;
                if(USART_RX_STA>(USART_RX_Total-1))
                {
                    USART_RX_STA=0;
                    RxFlag = 0;
                }
                break;
            default:break;
        }
    } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘猫.exe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值