菜单

自定义Modbus

下载

使用场景

本工程适用于———现有的modbus驱动不能满足于当前需求,需要对某些变量进行单独处理的情况

工程预览

使用指南

下载地址

https://help.simtutai.cn/docs/zi-ding-yi-Modbus-zhi-ling

对于modbus数据封装

c++ 复制代码
// MODBUS 06 - 写单个寄存器
bool HmiApp::modbus06_write(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) {
  vector<uint8_t> cmd;
  bool r = ModbusUtils::build_modbus06_command(slave_addr, reg_addr, value, cmd);
  if (!r)	return r;
  // 发送数据到串口
  int rb = STTUartWrite(cmd.data(), cmd.size());
  if (rb <= 0)	return false;
  return true;
}

bool HmiApp::modbus03_read(char * buff,uint8_t slave_addr, uint16_t reg_addr, uint16_t length) {
  vector<uint8_t> cmd;
  bool r = ModbusUtils::build_modbus03_command(slave_addr, reg_addr, length, cmd);
  if (!r)	return r;

  // 打印参数
  std::stringstream ss;
  ss << std::hex << std::uppercase << std::setfill('0');
  for(int i = 0; i < 8; i++) {
      ss << std::setw(2) << static_cast<int>(cmd[i]) << " ";
  }
  std::cout << "Data: " << ss.str() << std::endl;
  
  int ret = STTUartSendANDReadall(buff,length*2 + 3,200,cmd.data(),cmd.size());
  
  // 打印参数
  cout<<"ret = "<<ret<<endl;
  printf("Buff(HEX): ");
  for(int i = 0; i < ret; i++) {
      printf("%02X ", (unsigned char)buff[i]);
  }
  printf("\n");
  if (ret <= 0)	return false;
    return true;
}

// MODBUS 10 - 写多个寄存器
bool HmiApp::modbus10_write(uint8_t slave_addr, uint16_t start_addr, const std::vector<uint16_t>& values) {

  if (values.empty()) return false;
  vector<uint8_t> cmd;
  bool r = ModbusUtils::build_modbus10_command(slave_addr, start_addr, values, cmd);
  if (!r)	return r;
  // 发送数据到串口
  // 这里调用实际的串口发送函数,使用UrHandle->uartID
  int rb = STTUartWrite(cmd.data(), cmd.size());
  if (rb <= 0)	return false;
  return true;
}

对于发送和接收函数的封装

串口应选择模拟器/hmi中对应使用的modbus串口。案例工程模拟器和HMI均为COM1

c++ 复制代码
int HmiApp::STTUartWrite(unsigned char * bytes,int size){
  UARTDriverBase * UrHandle = (UARTDriverBase *)dm->getDvcdriver("COM1");
  if(UrHandle == nullptr)return 0;
  std::lock_guard<std::mutex> lock(UrHandle->mtx);
  return Util::uartWrite(UrHandle->uartID, bytes, 0, size);
}

int HmiApp::STTUartSendANDReadall(char * buff,uint8_t recvLen,uint16_t timeOut, unsigned char * bytes,int size){
  UARTDriverBase * UrHandle = (UARTDriverBase *)dm->getDvcdriver("COM1");
  if(UrHandle == nullptr)return 0;
  int ReadSize = 0;
  {
    char buffer[256] = {0};
    std::lock_guard<std::mutex> lock(UrHandle->mtx);
    Util::uartReadAll(UrHandle->uartID,buffer,256,10);
    if(size > 0){
      Util::uartWrite(UrHandle->uartID, bytes, 0, size);
    }
    Util::sleepfor(10);
    ReadSize = Util::uartReadAll(UrHandle->uartID,buff,recvLen,timeOut);
  }
  return ReadSize;
}

触发调用

下面案例以06功能码为例

c++ 复制代码
void Frm01::wMButton2_clk_cb(uint16_t code, LvEvent e) {
  /*wMButton2(功能键)的点击事件*/
  //	uint8_t slave_addr, uint16_t reg_addr, uint16_t value
  uint8_t slave_addr = 0x01;
  uint16_t reg_addr = static_cast<uint16_t>(StringUtil::safeStoi(wMTextNumber4->getText()));
  uint16_t value = static_cast<uint16_t>(StringUtil::safeStoi(wMTextNumber5->getText()));
  this->hmiApp->modbus06_write(slave_addr, reg_addr, value);
  cout << "END" << endl;
}

运行情况

03 连读两个地址

06 写单个地址

10 写连续多个地址

注意事项

头文件引入

c++ 复制代码
/*CUSTOM_HEAD_BEGIN*/
#include "dvc/UARTDriverBase.h"
#include <sstream>
#include <iomanip>
#include "ModbusUtil.h"
/*CUSTOM_HEAD_END*/



/*CUSTOM_CODE_BEGIN*/
  uint16_t modbus_crc16(const uint8_t* data, size_t length);
  int STTUartWrite(unsigned char * bytes,int size);
  int STTUartSendANDReadall(char * buff,uint8_t recvLen,uint16_t timeOut, unsigned char * bytes,int size);
  bool modbus06_write(uint8_t slave_addr, uint16_t reg_addr, uint16_t value);
  bool modbus10_write(uint8_t slave_addr, uint16_t start_addr, const std::vector<uint16_t>& values);
  bool modbus03_read(char * buff,uint8_t slave_addr, uint16_t reg_addr, uint16_t length);
/*CUSTOM_CODE_END*/

修改头文件 可以通过ctrl点击UrHandle进入修改

上一个
使用XPDF显示PDF文档
下一个
常见问题 FAQ
最近修改: 2025-10-28Powered by