发新帖我要提问
12
返回列表
打印
[其他ST产品]

RS485 Modbus协议 采集传感器数据

[复制链接]
楼主: 回复就哭哭
手机看帖
扫描二维码
随时随地手机跟帖
21
回复就哭哭|  楼主 | 2022-11-30 19:06 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
如果要读取传感器状态、数据,都需要发送请求帧

使用特权

评论回复
22
回复就哭哭|  楼主 | 2022-11-30 19:07 | 只看该作者
数据需要CRC校验

使用特权

评论回复
23
回复就哭哭|  楼主 | 2022-11-30 19:07 | 只看该作者
具体指令规则需查看传感器指令文档

使用特权

评论回复
24
回复就哭哭|  楼主 | 2022-11-30 19:08 | 只看该作者
根据传感器指令文档编程

使用特权

评论回复
25
回复就哭哭|  楼主 | 2022-11-30 19:09 | 只看该作者
打开传感器开关

void open_sensor(){
        //控制电源开关的引脚拉高
}

使用特权

评论回复
26
回复就哭哭|  楼主 | 2022-11-30 19:09 | 只看该作者
发送读取命令

void start_read(){
    uint8_t TxData[10]= "010300000001840A";
        HAL_UART_Transmit(&huart3,TxData,10,0xffff);
    HAL_Delay(100);
}

使用特权

评论回复
27
回复就哭哭|  楼主 | 2022-11-30 19:12 | 只看该作者
读取数据

在串口接收中断中接收数据,如果下一个串口数据在4ms之内到来,那么重新计时,定时器中断不会生效;如果没来,则认为接收完一帧数据,程序会进入定时器中断,这个很关键

使用特权

评论回复
28
回复就哭哭|  楼主 | 2022-11-30 19:14 | 只看该作者
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
                if(huart->Instance == USART3){
                          HAL_TIM_Base_Stop_IT(&htim5);
                          HAL_UART_Receive_IT(&huart3, &uart3Data, 1);
              uart3WriteByte(uart3Data);
              HAL_TIM_Base_Start_IT(&htim5);//开始计时4ms,即modbus设备在9600波特率下传输一帧数据的时间间隔
                          uart3Data** = 1;
                }
}

使用特权

评论回复
29
回复就哭哭|  楼主 | 2022-11-30 19:14 | 只看该作者
在定时器中断中进行处理数据
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim==(&htim5))
  {
                //TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //标准库需要清除TIMx更新中断标志,HAL库不需要,直接写业务逻辑就行
                 HAL_TIM_Base_Stop_IT(&htim5);
                 Modbus_Work();//数据处理函数
                 Uart3BufClear();
                 RS485_RX_CNT++;
  }
}

使用特权

评论回复
30
回复就哭哭|  楼主 | 2022-11-30 19:15 | 只看该作者
数据CRC校验

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


int16_t CRC_16( int8_t *vptr, int8_t len)
{
    uint16_t MODBUSCRC = 0xffff;
    uint16_t POLYNOMIAL = 0xa001;
    uint8_t i, j;

    for (i = 0; i < len; i++)
    {
        MODBUSCRC ^= vptr[i] ;
        for (j = 0; j < 8; j++)
        {
            if ((MODBUSCRC & 0x0001) != 0)
            {
                MODBUSCRC >>= 1;
                MODBUSCRC ^= POLYNOMIAL;
            }
            else
            {
                MODBUSCRC >>= 1;
            }
        }
    }
    return MODBUSCRC;
}

使用特权

评论回复
31
回复就哭哭|  楼主 | 2022-11-30 19:16 | 只看该作者
数据解析
int Modbus_Work(void)
{
        double depth;
        uint16_t  depth_high;
        uint16_t  depth_low;
        int len = strlen((char*)(sensor485DataBuffer+1));
        if(sensor485DataBuffer[1] == 0x01)//从机地址正确则进行换算
        {
                if((CRC_16((int8_t *)(sensor485DataBuffer+1),len))==0x0000){//CRC校验
                        depth_high = sensor485DataBuffer[3];
                        depth_low = sensor485DataBuffer[4];
                        depth = (double)((depth_high << 8) + depth_low)/1000;
                }
        }memset(sensor485DataBuffer,0,len+1);
        return depth;//这就是水深值了
}

使用特权

评论回复
32
童雨竹| | 2024-11-8 07:02 | 只看该作者

根据色彩的变化记录每一行的颜色跳变点,由此识别出车牌区域。

使用特权

评论回复
33
Wordsworth| | 2024-11-8 08:05 | 只看该作者

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。

使用特权

评论回复
34
Clyde011| | 2024-11-8 09:08 | 只看该作者

需要设定一个阈值来对像素点进行设置

使用特权

评论回复
35
公羊子丹| | 2024-11-8 10:01 | 只看该作者

计算量小,计算快。缺点也严重:在不同的图像中,颜色分布差别大,处理效果也不会很好。

使用特权

评论回复
36
万图| | 2024-11-8 11:04 | 只看该作者

在内存中开辟七个长为车牌长的七分之一和宽为车牌宽的区域

使用特权

评论回复
37
Uriah| | 2024-11-8 12:07 | 只看该作者

二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑色)或者255(白色

使用特权

评论回复
38
帛灿灿| | 2024-11-8 14:03 | 只看该作者

分别记录车牌区域的上下高度。然后通过RGB-HSV颜色转换

使用特权

评论回复
39
Bblythe| | 2024-11-8 15:06 | 只看该作者

通过OV7670摄像头进行图像采集

使用特权

评论回复
40
周半梅| | 2024-11-8 17:02 | 只看该作者

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则