我用STM32F103单片机的UART3连接一个sp3485芯片,利用485通信,485总线上挂载了四个485传感器,分别是采集PH,电导率,液位,和含氧量的四个传感器。
出现了以下问题
1.while循环中 其中有四行代码 ,分别是
(1)采集PH,
(2)采集液位高度
(3)采集液体电导率
(4)采集含氧量
这四行代码是分别封装的函数,里面的通信格式是用Modbus,用串口轮询方式HAL_UART_Transmist 发送指令给传感器,再用串口轮询接收HAL_UART_Receive方式接收传感器返回来的数据。
但是,只能维持一天的时间左右,大概过了30个小时,单片机又会采集到全部都是零的数据,但是不是死机的状态,他其他程序还是可以运行,就是采不到数据。
折腾了好多天,都不知道是什么问题。
然后我通过抓包 将485总线线上的信号通过485转USB串口返回电脑,通过串口助手发现:
代码的预期指令数据和发出去的指令数据不一致,比如,我代码要求的是串口通过轮询的方法发送
指令 :01 03 00 02 00 01 DA 8F (这一串指令放在一个uint8_t 的全局数组里面),但是发送到到485总线上的信号是 : 00 00 00 02 00 01 DA 8F ,这就不难奇怪,为什么我的传感器返回的数据是0了,因为485通信的机制是一问一答,modbus的通信就是主机发送指令 (指令包含地址码、功能码、数据、CRC校验码),当你的指令其中任何一个内容发生异常改变,传感器都不会产生应答返回数据,因为只要有一个内容出错,那么CRC校验码肯定会出错,所以这条指令肯定是无效的。
但是为什么会出现这个问题呢?
这个bug相当于是全局变量发生的异常改变;
1、定义的全局数组在其他线程被更改了 (但是通过查看,在程序的其他地方并没有发现这个全局数组被引用了)
2、被编译器优化 (尝试加volatile,结果无效)
3、数组或者指针越界,栈溢出(编译没报错)
解决办法,在全局数组的前面加 const 关键字,和将全局数组定义成局部数组,需要的时候就重新初始化,用完立即释放内存。
笔者觉得应当是内存问题。所以,当你希望一个数据它不被修改的时候记得加上 “const” 修饰。