×
单片机 > 单片机程序设计 > 详情

基于STM32的CRC校验说明

发布时间:2020-06-15 发布时间:
|

 

 

 

 

 

 

 

 


///*****************************************************************************

//下面是test.c里面的函数

///*****************************************************************************

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//串口猎人用的程序                                                        //////////

//值得说明的是,CRC协议同样适用于串口猎人适用,也就是”协议”是通用的        ////////

//    USART1->DR=num;                                                    ////////

//串口猎人只能发送hex值,即只能发送16进制的数据,才能显示出波形            /////////

//    while((USART1->SR&0X40)==0);                                          ////////

//    delay_ms(500);                                                        ////////

//    num-=1;                                                            ////////

//    if(num==0x00)                                                        ////////

//    num=0xff;                                                            ///////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//值得说明的是,CRC协议同样适用于串口猎人适用,也就是”协议”是通用的        ////////

//串口助手用的程序                                                        ////////

//    printf("%d ",0XA5);                                                    ////////

//    printf("%d ",t);                                                        ////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//    Visualscope串口示波器的程序                                            ////////

                                                                        ////////

    for(i=0;i<4;i++)//先装载数据                                            ////////

    {                                                                    ////////

        OutData[i]= num;                                                    ////////

        num-=70;                                                            ////////

    }                                                                    ////////

    num=0xff;                                                            ////////

    OutPut_Data();//调用主函数                                                ////////

    delay_ms(10);//定义发送频率                                            ////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


///*****************************************************************************

//下面是USART.H里面的函数

///*****************************************************************************

//串口示波器的变量

extern float OutData[4];//这是全局变量

unsigned short CRC_CHECK(unsigned short *Buf, unsigned short CRC_CNT);

void voTxIsr(void);

void OutPut_Data();



///*****************************************************************************//下面的是USART.C里面的文件

//这里用到了串口接收数据中断函数,所以需要把原先的数据串口中断函数屏蔽了

///*****************************************************************************

//the following is MCU code for CRC16 ,please refer.

//-------------------------------------------------------------------------------------------

#define ULONG unsigned long

#define RxCountMax 18

//float OutData[4];    这个是全局变量,在main函数和USART.H中都有定义

unsigned short TxBuf[10];

unsigned short RxBuf[RxCountMax];

unsigned short RxCnt;

unsigned short TxCnt;

unsigned short Rx50msCnt;

unsigned long pAddr1,pAddr2,pAddr3,pAddr4;


//CRC16校验算法

unsigned short CRC_CHECK(unsigned short *Buf, unsigned short CRC_CNT)

{

    unsigned short CRC_Temp;

    unsigned char i,j;

    CRC_Temp = 0xffff;


    for (i=0;i

        CRC_Temp ^= Buf[i];        

        for (j=0;j<8;j++) {

            if (CRC_Temp & 0x01)

                CRC_Temp = (CRC_Temp >>1 ) ^ 0xa001;

            else

                CRC_Temp = CRC_Temp >> 1;

        }

    }

    return(CRC_Temp);

}


//Receive interrupt routine 串口接收中断函数

void USART1_IRQHandler(void)

{

    unsigned short i,CRC_RX,CRC_Tmp;

    RxBuf[RxCnt] = USART1->DR;        //acquire data    接收数据

    RxCnt++;

        

    if(RxCnt == RxCountMax) {

        CRC_Tmp =  CRC_CHECK(RxBuf,16);      //CRC Calculation    计算接收到的数据的CRC校验值

        CRC_RX = ((unsigned short)RxBuf[RxCountMax-1]<<8) + RxBuf[RxCountMax-2];    //接收的数据中的最后两位就是CRC校验值

        if(CRC_Tmp == CRC_RX){        //比较两个校验值是否相同

            LED0=~LED0;    //这里是我做的一个现象,通信成功就亮/灭一下灯

            pAddr1 = ((ULONG)(RxBuf[0x3])<<24)|((ULONG)(RxBuf[0x2])<<16)|((ULONG)(RxBuf[0x1])<<8)|RxBuf[0x0];    //然后把数据保存起来

            pAddr2 = ((ULONG)(RxBuf[0x7])<<24)|((ULONG)(RxBuf[0x6])<<16)|((ULONG)(RxBuf[0x5])<<8)|RxBuf[0x4];

            pAddr3 = ((ULONG)(RxBuf[0xB])<<24)|((ULONG)(RxBuf[0xA])<<16)|((ULONG)(RxBuf[0x9])<<8)|RxBuf[0x8];

            pAddr4 = ((ULONG)(RxBuf[0xF])<<24)|((ULONG)(RxBuf[0xE])<<16)|((ULONG)(RxBuf[0xD])<<8)|RxBuf[0xC];        

        }

        RxCnt = 0;  

    }

    Rx50msCnt = 0;

//to add--Clear Receive Data Register Fll flag;

//    USART1->DR=res;

//    while((USART1->SR&0X40)==0);//



//Transfer interrupt routine    串口发送数据函数

void voTxIsr(void)

{

    if(TxCnt <= 9)

    {

        USART1->DR = TxBuf[TxCnt];

        //Clear Tx interrupt flag

        TxCnt++;

        if(TxCnt >= 10)

        {

            //send interrupt disable        

            TxCnt=0;

        }

    }

}



//-------------------------------------------------------------------------------------------

//Monitor routine Execute every T Period time    应用函数,在主函数中直接调用这个就可以了

void OutPut_Data()

{

    int temp[4] = {0};

    unsigned int temp1[4] = {0};

    unsigned short databuf[10] = {0};

    unsigned char i;

    unsigned short CRC16 = 0;

    for(i=0;i<4;i++)

    {

    temp[i]  = (u16)OutData[i]; //把要发送的数据传过来

    temp1[i] = (u16)temp[i];    //并复制一份数据,进行下面的处理

    }


    for(i=0;i<4;i++) 

    {

    databuf[i*2]   = (u8)(temp1[i]%256);    //高低位处理

    databuf[i*2+1] = (u8)(temp1[i]/256); 

    }


    CRC16 = CRC_CHECK(databuf,8);   //计算要发送数据的CRC16校验值

    databuf[8] = CRC16%256;         //并保存在databuf的8 9里面

    databuf[9] = CRC16/256;


    for(i=0;i<10;i++)//把数据和校验位一起发送出去

    {

//        voTxIsr();

        if(TxCnt <= 9)

        {

            USART1->DR = databuf[TxCnt];//发送数据给寄存器

            while((USART1->SR&0X40)==0);//直到发送完成才结束发送  

            TxCnt++;

            if(TxCnt >= 10)

            {

                TxCnt=0;    //准备下次发送数据    

            }

        }

    }

}


关键字:STM32  CRC校验 


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析