中国移动 ML302 4G cat.1 模组移植 Modbus Master 实现简单边缘计算
此次移植工作以中国移动 ML302 模组为基础，亿琪软件 YiDTU 设备为原型，开发基于 Modbus Master 应用； 传统模式下，DTU 都是以透传为主要工作，所有的业务需求都是从服务器端发出，而 YiDTU 是作为边缘计算的角色，在工业现场就已经把数据处理做完； ![yigate-yidtu.png][1] 准备工作 硬件设备 YiDTU 设备一台 亿琪软件 YiDTU 设备内置 UART 转 RS485 模块，对外连接 RS485 双线设备，如：YiSensor 模拟量采集模块；对于开发而言，那就是主要针对 UART 串口操作； Micro USB 线一根 用于操作 YiDTU 设备：AT 串口操作，烧录操作； RS485 设备若干 可用 USB 转 RS485 转换器代替（需配合 modbus slave 软件使用）；有支持 Modbus Slave 设备最好；准备了两个：模拟量 4-20mA 和 开关量各一个； 9～30V 直流电源一个 支持最大 2A 电流的直流电源一个，用于给 YiDTU 设备供电； 将以上硬件设备连接好 软件 SDK 从中国移动物联网公司获取 ML302 相关 SDK，； 确保 SDK 编译正常； 烧录基本应用成功； 移植过程 Modbus Master 库 从 https://github.com/jiekechoo/ModBus-Master.git 获取源代码，使用 STM32 环境编译成功，确保你的环境没问题； 将 Modbus_Master 目录移植到 ML302 工程中 src/demo/modbus 下，根据需求删除不必要的组件功能； ML302 环境下编译通过，确保没有错误出现； Modbus 枚举值要重新定义 typedef enum { // Modbus function codes for bit access ku8MBReadCoils = 0x01, ///< Modbus function 0x01 Read Coils ku8MBReadDiscreteInputs = 0x02, ///< Modbus function 0x02 Read Discrete Inputs ku8MBWriteSingleCoil = 0x05, ///< Modbus function 0x05 Write Single Coil ku8MBWriteMultipleCoils = 0x0F, ///< Modbus function 0x0F Write Multiple Coils // Modbus function codes for 16 bit access ku8MBReadHoldingRegisters = 0x03, ///< Modbus function 0x03 Read Holding Registers ku8MBReadInputRegisters = 0x04, ///< Modbus function 0x04 Read Input Registers ku8MBWriteSingleRegister = 0x06, ///< Modbus function 0x06 Write Single Register ku8MBWriteMultipleRegisters = 0x10, ///< Modbus function 0x10 Write Multiple Registers ku8MBMaskWriteRegister = 0x16, ///< Modbus function 0x16 Mask Write Register ku8MBReadWriteMultipleRegisters = 0x17 ///< Modbus function 0x17 Read Write Multiple Registers } modbusFunc; 串口接收支持 串口接收任务中，将收到的内容复制到全局变量中，目的是把 Modbus Slave 回复的内容获取到，交给 Modbus 组件使用； extern uint8_t u8ModbusADU[1024]; extern uint8_t u8ModbusADUSize; // 接收处理函数中 { u8ModbusADUSize = uart_buf_len; memcpy(u8ModbusADU, uart_buf, u8ModbusADUSize); } - 接收完成后，创建一个 信号量，通知 Modbus 组件来处理； { uart_buf_len = 0; recv_count = 0; osSignalSet(OC_Main_TaskHandle, 0x0004); } ## Modbus 组件 - 将 Modbus 组件中接收处理替换成信号量等待，超时重置接收缓冲区； // 串口收到数据信号量，2000ms 超时 osEvent osevent = osSignalWait(0x0004, ku16MBResponseTimeout); if (osevent.status == osEventTimeout) { u8MBStatus = ku8MBResponseTimedOut; memset(u8ModbusADU, 0, sizeof(u8ModbusADU)); u8ModbusADUSize = 0; } - Modbus 发送函数重写 uint8_t Modbus_Master_Write(uint8_t buf, uint8_t length) { // if(HAL_UART_Transmit(&huart2 ,(uint8_t )buf,length,0xff)) if (cm_uart_send_no_cache(OPENCPU_MAIN_URAT, (uint8_t *)buf, length, 0xff) == 0) { return HAL_ERROR; } else { return HAL_OK; } } - 如果有 CS 控制口 IO，需要自定义相关函数 if 0 // transmit request RS485接口是需要每次发送前改变接口的模式 if (_preTransmission) { _preTransmission(); } endif //串口发送数据 Modbus_Master_Write(u8ModbusADU, u8ModbusADUSize); u8ModbusADUSize = 0; if 0 // transmit request RS485接口是需要每次发送后改变接口的模式 if (_postTransmission) { _postTransmission(); } endif > 移植过程比较简单，细节需要一定的嵌入式和 C 语言基础。 # 效果展示 在 YiDTU 业务逻辑中增加相应的功能模块，把数据传输到云平台，这样，就可以及时获取现场的模拟量数据。 ![PSX_20210119_151717.jpg][2] [1]: https://yiqisoft.cn/blogs/usr/uploads/2021/01/1616746346.png [2]: https://yiqisoft.cn/blogs/usr/uploads/2021/01/2439453110.jpg