STM32串口中断接收一个完整的数据帧

代码运行条件:
(1) 大端发送;
(2) 上位机发送一帧数据的时间间隔不能大于主循环周期;
spa

(3)数据帧知足下面格式: code

帧头部(Head)ip

类型(Type)ci

长度(Length)it

值(Value)io

CRC校验table

2字节class

1字节循环

1字节im

X字节

2字节

     0xaa  0x55

 

       X

 

 

void USART6_Init (void) 
{
	GPIO_InitTypeDef	GPIO_InitStructure;
	USART_InitTypeDef	USART_InitStructure;
	NVIC_InitTypeDef	NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //修改

	GPIO_InitStructure.GPIO_Pin	= GPIO_Pin_6|GPIO_Pin_7;//修改
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType	= GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd	= GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);//修改
	
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6);//修改
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6);	//修改

	NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	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;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART6,&USART_InitStructure);
	
	USART_ITConfig(USART6,USART_IT_RXNE,ENABLE);//打开接收中断
	USART_Cmd(USART6,ENABLE);
}
void USART6_IRQHandler()
{
	unsigned char rCh;
	static char rCnt = 0;
	if(USART_GetITStatus(USART6,USART_IT_RXNE) != RESET)
	{
    	    rCh = USART_ReceiveData(USART6);
	    COM6_RecvBuf[rCnt] = rCh;
	    if(rCnt == 0)     //帧头0xAA    
	    {
       		rCnt = (0xAA != rCh)?0:rCnt+1;
	    }
	    else if(rCnt == 1) //帧头0x55  
	    {
		rCnt = (0x55 != rCh)?0:rCnt+1;
	    }
	    else if(rCnt == 2) //类型type
	    {
		//这里能够根据类型的范围进行如上的处理
		rCnt++;
            }
	    else if(rCnt == 3) //长度len
	    {
		rCnt++;
            }			
	    else if(rCnt > 3) //值value
	    {
		rCnt++;
		if(rCnt == 6+COM6_RecvBuf[3])
		{             
		    rCnt = 0;
		    memcpy(COM6_RecvBufBck,COM6_RecvBuf,RECV_BUF_SZ);//缓冲
		     COM6_RecvFin = 1;  //通知主循环处理
  		}
	     }
    }
}
int  main(void)
{
    int i;
    //代码段1
    while(1)//该循环不能太慢,不然数据缓冲区会被部分修改
    {
	//代码段2
        if(COM6_RecvFin == 1)
	{
	    COM6_RecvFin = 0;
	    CMD_Analysis();//分析接收到的这帧数据
	}
        //代码段3
    }
    return  0;
}
//在之后再仔细分析数据接收较快而处理较慢的问题吧,本课题主要讨论的是如何完整的接收一个数据帧,在数据源正确的状况下不丢帧