zoukankan      html  css  js  c++  java
  • 基于STM32的CRC校验说明

    ///*****************************************************************************
    //下面是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_CNT; 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;    //准备下次发送数据    
                }
            }
        }
    }
  • 相关阅读:
    docker gitlab意外强制关机导致gitlab启动后报错unexpected end of JSON input
    Dockerfile实践记录
    html 打开新页面
    【rt-thread】2、尝试用ENV添加18b20传感器
    【rt-thread】1、快速建立rt-thread nano最小裁剪工程
    Git pull 强制覆盖本地文件
    *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    51单片机局部变量占用ram的问题
    【乐为物联】1、初识乐联
    Wing-AEP平台LWM2M设备接入
  • 原文地址:https://www.cnblogs.com/qidaiymm/p/6073188.html
Copyright © 2011-2022 走看看