资讯详情

【RoboMaster】A板接收JY-ME01角度传感器数据--modebus协议&CRC软件校验

角度传感器应用于新车JY-ME01使用的是modbus协议传输数据时,需要使用A板接收数据并分析角度数据,以便以后使用时查找。

1、cubemax配置底层

1.1 时钟及项目配置

基本配置方法,全部通用。 在这里插入图片描述

1.2 串口dma配置

添加一个RX的dma,一共3步 配置与上图一致。(主要确认

2.串口接收数据的代码

文件:main.c

unsigned char  RX_BUFFER[20]; ///定义全局变量接收数组 
///放在串口初始化完成后   __HAL_UART_ENABLE_IT(&huart8,UART_IT_IDLE);//使能中断   HAL_UART_Receive_DMA(&huart8,RX_BUFFER,9);//开启dma接收数组,长度9Byte 

文件:stm32f4xx_it.c UART8_IRQHandler - 串口中断函数

uint16_t temp;  if(__HAL_UART_GET_FLAG(&huart8,UART_FLAG_IDLE)==SET){ 
             __HAL_UART_CLEAR_IDLEFLAG(&huart8);  ///清除标志位,准备下次接收数据     HAL_UART_DMAStop(&huart8);   //停止dma传输     temp=9-hdma_uart8_rx.Instance->NDTR;  /*读取ndtr寄存器中dma发送数据字节数,然后计算 距离9字节需要多少字节?*/     HAL_UART_Transmit_DMA(&huart8,RX_BUFFER,temp);  ///将剩余字节发送到接收数组   }   HAL_UART_Receive_DMA(&huart8,RX_BUFFER,9);  //重启dma 

3.CRC校验

原理

因为是在应用CRC验证算法,对原理研究不多。 粗略看计算原理: 1、 16进制的16位寄存器FFFF(全1)这个寄存器是CRC寄存器。 2、 第一个8位二进制数据(即通信信息帧的第一个字节)和16位CRC寄存器的低八位相差或,结果存储在CRC寄存器。 3、 把CRC将寄存器内容向右移动一位(朝低位),用0填补最高位,检测右移后的移出位。 4、 若移出位为零,则重复第三步(再次右移一位);若移出位为1,CRC寄存器和多项式A001进行异或。 5、 重复步骤3和4,直到右移8次,这样整个8位数据数据。 6、 重复步骤2和5,处理通信信息帧下一个字节。 7、 按上述步骤计算通信信息帧的所有字节后,得到16位CRC交换寄存器的高低字节。 8、 最后得到的CRC寄存器内容为:CC校验码。

重点:stm32上常用的CRC校验方法 1.硬件CRC 节省计算资源,但是F4开启CRC后无法配置参数,很玄学,暂时放弃 2.实时计算CRC校验 占用FLASH小,但是计算速度慢一点 3. 查表计算速度快,但是占用FLASH(A板内存大随便干),所以选用这个方法。

代码实现

由CRC校验原理可知,CRC校验有一个特点就是每个八位二进制字节对应的CRC校验码相同。所以对一个字节可以直接查表得到对应的校验结果值。 建议放在用户函数单独建立的文件内

    const unsigned char TabH[] = { 
          //CRC高位字节值表
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  
    };  
    const unsigned char TabL[] = { 
          //CRC低位字节值表
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  
        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  
        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  
        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  
        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  
        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  
        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  
        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  
        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  
        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  
        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,  
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  
        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  
        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  
        0x43, 0x83, 0x41, 0x81, 0x80, 0x40  
    } ;
float ANGLE;	//定义角度变量

uint16_t GetModbusCRC16_Tab(uint8_t *data, uint32_t len)//Modbus-CRC校验-----查表法
{ 
        
    unsigned int index;
    unsigned char crcH = 0xFF;  //高CRC字节
    unsigned char crcL = 0xFF;  //低CRC字节

    while (len--)  { 
         //计算指定长度的CRC
        index = crcL ^ *data++;
        crcL = crcH	^ TabH[ index];
        crcH = TabL[ index];
    }
		return crcL<<8|crcH;//高低位置换
}  

推荐一个可以用于检验CRC结果是否正确的网站:http://www.ip33.com/crc.html 串口中断函数加入CRC计算的过程,对比无误后计算角度并输出 原计算公式:

crc_val=GetModbusCRC16_Tab(RX_BUFFER,7);
    if(crc_val==((RX_BUFFER[7]<<8)|RX_BUFFER[8])){ 
        		
      ANGLE=(float)((RX_BUFFER[3]<<24)|(RX_BUFFER[4]<<16)|(RX_BUFFER[5]<<8)|RX_BUFFER[6]);
      ANGLE=ANGLE/0x40000*360;
    }

更改中断函数后的结果。

运行结果

标签: 传感器7a1707c5e0100200112传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台