[其他ST产品] RS485 Modbus协议 采集传感器数据

[复制链接]
 楼主| 回复就哭哭 发表于 2022-11-30 19:06 | 显示全部楼层
如果要读取传感器状态、数据,都需要发送请求帧
 楼主| 回复就哭哭 发表于 2022-11-30 19:07 | 显示全部楼层
数据需要CRC校验

 楼主| 回复就哭哭 发表于 2022-11-30 19:07 | 显示全部楼层
具体指令规则需查看传感器指令文档
 楼主| 回复就哭哭 发表于 2022-11-30 19:08 | 显示全部楼层
根据传感器指令文档编程

6730263873994ccd27.png
 楼主| 回复就哭哭 发表于 2022-11-30 19:09 | 显示全部楼层
打开传感器开关

void open_sensor(){
        //控制电源开关的引脚拉高
}
 楼主| 回复就哭哭 发表于 2022-11-30 19:09 | 显示全部楼层
发送读取命令

void start_read(){
    uint8_t TxData[10]= "010300000001840A";
        HAL_UART_Transmit(&huart3,TxData,10,0xffff);
    HAL_Delay(100);
}
 楼主| 回复就哭哭 发表于 2022-11-30 19:12 | 显示全部楼层
读取数据

在串口接收中断中接收数据,如果下一个串口数据在4ms之内到来,那么重新计时,定时器中断不会生效;如果没来,则认为接收完一帧数据,程序会进入定时器中断,这个很关键
 楼主| 回复就哭哭 发表于 2022-11-30 19:14 | 显示全部楼层
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  2. {
  3.                 if(huart->Instance == USART3){
  4.                           HAL_TIM_Base_Stop_IT(&htim5);
  5.                           HAL_UART_Receive_IT(&huart3, &uart3Data, 1);
  6.               uart3WriteByte(uart3Data);
  7.               HAL_TIM_Base_Start_IT(&htim5);//开始计时4ms,即modbus设备在9600波特率下传输一帧数据的时间间隔
  8.                           uart3Data** = 1;
  9.                 }
  10. }
 楼主| 回复就哭哭 发表于 2022-11-30 19:14 | 显示全部楼层
在定时器中断中进行处理数据
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  2. {
  3.   if(htim==(&htim5))
  4.   {
  5.                 //TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //标准库需要清除TIMx更新中断标志,HAL库不需要,直接写业务逻辑就行
  6.                  HAL_TIM_Base_Stop_IT(&htim5);
  7.                  Modbus_Work();//数据处理函数
  8.                  Uart3BufClear();
  9.                  RS485_RX_CNT++;
  10.   }
  11. }
 楼主| 回复就哭哭 发表于 2022-11-30 19:15 | 显示全部楼层
数据CRC校验

CRC原理就不啰嗦了
不同种类的CRC校验的多项式并不统一,这里是0xA001,文档中会说明


  1. int16_t CRC_16( int8_t *vptr, int8_t len)
  2. {
  3.     uint16_t MODBUSCRC = 0xffff;
  4.     uint16_t POLYNOMIAL = 0xa001;
  5.     uint8_t i, j;

  6.     for (i = 0; i < len; i++)
  7.     {
  8.         MODBUSCRC ^= vptr[i] ;
  9.         for (j = 0; j < 8; j++)
  10.         {
  11.             if ((MODBUSCRC & 0x0001) != 0)
  12.             {
  13.                 MODBUSCRC >>= 1;
  14.                 MODBUSCRC ^= POLYNOMIAL;
  15.             }
  16.             else
  17.             {
  18.                 MODBUSCRC >>= 1;
  19.             }
  20.         }
  21.     }
  22.     return MODBUSCRC;
  23. }
 楼主| 回复就哭哭 发表于 2022-11-30 19:16 | 显示全部楼层
数据解析
  1. int Modbus_Work(void)
  2. {
  3.         double depth;
  4.         uint16_t  depth_high;
  5.         uint16_t  depth_low;
  6.         int len = strlen((char*)(sensor485DataBuffer+1));
  7.         if(sensor485DataBuffer[1] == 0x01)//从机地址正确则进行换算
  8.         {
  9.                 if((CRC_16((int8_t *)(sensor485DataBuffer+1),len))==0x0000){//CRC校验
  10.                         depth_high = sensor485DataBuffer[3];
  11.                         depth_low = sensor485DataBuffer[4];
  12.                         depth = (double)((depth_high << 8) + depth_low)/1000;
  13.                 }
  14.         }memset(sensor485DataBuffer,0,len+1);
  15.         return depth;//这就是水深值了
  16. }
童雨竹 发表于 2024-11-8 07:02 | 显示全部楼层

根据色彩的变化记录每一行的颜色跳变点,由此识别出车牌区域。
Wordsworth 发表于 2024-11-8 08:05 | 显示全部楼层

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。
Clyde011 发表于 2024-11-8 09:08 | 显示全部楼层

需要设定一个阈值来对像素点进行设置
公羊子丹 发表于 2024-11-8 10:01 | 显示全部楼层

计算量小,计算快。缺点也严重:在不同的图像中,颜色分布差别大,处理效果也不会很好。
万图 发表于 2024-11-8 11:04 | 显示全部楼层

在内存中开辟七个长为车牌长的七分之一和宽为车牌宽的区域
Uriah 发表于 2024-11-8 12:07 | 显示全部楼层

二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑色)或者255(白色
帛灿灿 发表于 2024-11-8 14:03 | 显示全部楼层

分别记录车牌区域的上下高度。然后通过RGB-HSV颜色转换
Bblythe 发表于 2024-11-8 15:06 | 显示全部楼层

通过OV7670摄像头进行图像采集
周半梅 发表于 2024-11-8 17:02 | 显示全部楼层

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部