[AI写代码]modbus rtu master单片机程序modbus主机代码

实现一个基于 STM32 HAL库 ucosiii的Modbus-RTU Master 主机C语言程序代码,提供完整的C和H文件,能够与从机设备进行通信,
功能码实现:
- **0x03**:读取保持寄存器。
- **0x06**:写入单个寄存器。
- **0x10**:写入多个寄存器。
- 其他功能码(如 0x01、0x02、0x04 等)。
Modbus 协议实现包含帧构建、发送、接收、解析等功能。
超时处理:设置通信超时机制,防止死锁。
错误处理:处理从机返回的错误码。在源码里加上详细注释

/* modbus_master.h */
#ifndef __MODBUS_MASTER_H
#define __MODBUS_MASTER_H

#include "stm32f1xx_hal.h"
#include "os.h"

// Modbus功能码定义
#define READ_COILS           0x01
#define READ_DISCRETE_INPUTS 0x02
#define READ_HOLDING_REG     0x03
#define READ_INPUT_REG       0x04
#define WRITE_SINGLE_COIL    0x05
#define WRITE_SINGLE_REG     0x06
#define WRITE_MULTI_REG      0x10

// 错误码定义
#define MB_SUCCESS           0
#define MB_TIMEOUT_ERR       -1
#define MB_CRC_ERR           -2
#define MB_FUNC_ERR          -3

// Modbus主站结构体
typedef struct {
    UART_HandleTypeDef *huart;    // 使用的串口句柄
    uint32_t timeout;             // 超时时间(ms)
    uint8_t retry_count;          // 重试次数
    OS_SEM rx_sem;                // 接收信号量
    OS_MUTEX uart_mutex;          // 串口互斥锁
} ModbusMaster;

// 函数声明
void ModbusMaster_Init(ModbusMaster *mb, UART_HandleTypeDef *huart);
int8_t ReadHoldingRegisters(ModbusMaster *mb, uint8_t slave_addr, 
                          uint16_t start_addr, uint16_t reg_num, 
                          uint16_t *data);
int8_t WriteSingleRegister(ModbusMaster *mb, uint8_t slave_addr,
                         uint16_t reg_addr, uint16_t value);
int8_t WriteMultipleRegisters(ModbusMaster *mb, uint8_t slave_addr,
                            uint16_t start_addr, uint16_t reg_num,
                            uint16_t *values);

#endif /* __MODBUS_MASTER_H */

/* modbus_master.c */
#include "modbus_master.h"
#include <string.h>

// 私有函数声明
static uint16_t CRC16(uint8_t *buf, uint16_t len);
static void BuildRequestFrame(uint8_t *frame, uint8_t slave_addr, 
                            uint8_t func_code, uint16_t addr, 
                            uint16_t data);
static int8_t SendRequest(ModbusMaster *mb, uint8_t *frame, uint8_t len);
static int8_t ReceiveResponse(ModbusMaster *mb, uint8_t *resp, 
                            uint8_t expected_len);

// 初始化Modbus主站
void ModbusMaster_Init(ModbusMaster *mb, UART_HandleTypeDef *huart) {
    mb->huart = huart;
    mb->timeout = 1000; // 默认超时1秒
    mb->retry_count = 3;
    OSSemCreate(&mb->rx_sem, "MB Rx Sem", 0);
    OSMutexCreate(&mb->uart_mutex, "MB UART Mutex", OS_ERR_NONE);
}

// 读取保持寄存器(功能码0x03)
int8_t ReadHoldingRegisters(ModbusMaster *mb, uint8_t slave_addr, 
                          uint16_t start_addr, uint16_t reg_num, 
                          uint16_t *data) {
    uint8_t frame[8];
    uint8_t resp[256];
    int8_t result = MB_TIMEOUT_ERR;
    
    // 构建请求帧
    BuildRequestFrame(frame, slave_addr, READ_HOLDING_REG, start_addr, reg_num);
    
    OSMutexPend(&mb->uart_mutex, 0, OS_OPT_PEND_BLOCKING, NULL);
    
    for(uint8_t retry = 0; retry < mb->retry_count; retry++) {
        // 发送请求
        if(SendRequest(mb, frame, 8) != HAL_OK) continue;
        
        // 接收响应(2*reg_num + 5字节)
        uint8_t expected_len = 5 + 2 * reg_num;
        if(ReceiveResponse(mb, resp, expected_len) == MB_SUCCESS) {
            // 校验响应
            if(resp[1] == READ_HOLDING_REG) {
                memcpy(data, &resp[3], 2 * reg_num);
                result = MB_SUCCESS;
                break;
            } else if(resp[1] & 0x80) { // 错误响应
                result = MB_FUNC_ERR;
                break;
            }
        }
    }
    
    OSMutexPost(&mb->uart_mutex, OS_OPT_POST_NONE);
    return result;
}

// 发送请求帧(带CRC校验)
static int8_t SendRequest(ModbusMaster *mb, uint8_t *frame, uint8_t len) {
    uint16_t crc = CRC16(frame, len - 2);
    frame[len - 2] = crc & 0xFF;
    frame[len - 1] = crc >> 8;
    
    HAL_UART_AbortReceive(mb->huart);
    return HAL_UART_Transmit(mb->huart, frame, len, mb->timeout);
}

// 接收响应(带超时处理)
static int8_t ReceiveResponse(ModbusMaster *mb, uint8_t *resp, uint8_t expected_len) {
    uint8_t rx_len = 0;
    uint32_t start_time = HAL_GetTick();
    
    HAL_UART_Receive_IT(mb->huart, resp, expected_len);
    
    while((HAL_GetTick() - start_time) < mb->timeout) {
        if(__HAL_UART_GET_FLAG(mb->huart, UART_FLAG_RXNE)) {
            rx_len = mb->huart->RxXferSize - mb->huart->RxXferCount;
            if(rx_len >= expected_len) break;
        }
        OSTimeDlyHMSM(0, 0, 0, 10); // UCOSIII延时10ms
    }
    
    if(rx_len < expected_len) return MB_TIMEOUT_ERR;
    
    // CRC校验
    uint16_t crc = CRC16(resp, expected_len - 2);
    if((resp[expected_len-2] != (crc & 0xFF)) || 
       (resp[expected_len-1] != (crc >> 8))) {
        return MB_CRC_ERR;
    }
    
    return MB_SUCCESS;
}

// CRC16计算(MODBUS-RTU标准)
static uint16_t CRC16(uint8_t *buf, uint16_t len) {
    uint16_t crc = 0xFFFF;
    for(uint16_t pos = 0; pos < len; pos++) {
        crc ^= (uint16_t)buf[pos];
        for(uint8_t i = 8; i != 0; i--) {
            if((crc & 0x0001) != 0) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}
// UCOSIII任务示例
void ModbusTask(void *p_arg) {
    ModbusMaster mb;
    uint16_t holding_regs[10];
    
    ModbusMaster_Init(&mb, &huart1);
    
    while(1) {
        // 读取从站1的保持寄存器40001-40010
        int8_t result = ReadHoldingRegisters(&mb, 0x01, 0x0000, 10, holding_regs);
        
        if(result == MB_SUCCESS) {
            // 处理数据...
        } else {
            // 错误处理...
        }
        
        OSTimeDlyHMSM(0, 0, 1, 0); // 每秒执行一次
    }
}

第二版本代码 克劳德3.7编写

基于HAL UCOSIII

/**
  ******************************************************************************
  * @file    modbus_master.h
  * @author  Claude AI
  * @brief   Modbus RTU Master mode header file
  * @details 基于STM32 HAL库和uCOS-III的Modbus-RTU主机实现
  ******************************************************************************
  */

#ifndef __MODBUS_MASTER_H
#define __MODBUS_MASTER_H

#ifdef __cplusplus
extern "C" {
#endif

/* 包含所需头文件 */
#include "stm32f4xx_hal.h"
#include "os.h"
#include <stdint.h>
#include <string.h>
#include <stdbool.h>

/* Modbus 功能码定义 */
#define MODBUS_READ_COILS                0x01  // 读取线圈状态
#define MODBUS_READ_DISCRETE_INPUTS      0x02  // 读取离散输入状态
#define MODBUS_READ_HOLDING_REGISTERS    0x03  // 读取保持寄存器
#define MODBUS_READ_INPUT_REGISTERS      0x04  // 读取输入寄存器
#define MODBUS_WRITE_SINGLE_COIL         0x05  // 写单个线圈
#define MODBUS_WRITE_SINGLE_REGISTER     0x06  // 写单个寄存器
#define MODBUS_WRITE_MULTIPLE_COILS      0x0F  // 写多个线圈
#define MODBUS_WRITE_MULTIPLE_REGISTERS  0x10  // 写多个寄存器

/* Modbus 异常码定义 */
#define MODBUS_EXCEPTION_ILLEGAL_FUNCTION        0x01
#define MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS    0x02
#define MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE      0x03
#define MODBUS_EXCEPTION_SLAVE_DEVICE_FAILURE    0x04
#define MODBUS_EXCEPTION_ACKNOWLEDGE             0x05
#define MODBUS_EXCEPTION_SLAVE_DEVICE_BUSY       0x06
#define MODBUS_EXCEPTION_MEMORY_PARITY_ERROR     0x08
#define MODBUS_EXCEPTION_GATEWAY_PATH_UNAVAILABLE 0x0A
#define MODBUS_EXCEPTION_GATEWAY_TARGET_FAILED   0x0B

/* Modbus 参数配置 */
#define MODBUS_MAX_SLAVE_NUM            10    // 最大从机数量
#define MODBUS_MAX_PDU_LENGTH           253   // 最大PDU长度
#define MODBUS_MAX_ADU_LENGTH           256   // 最大ADU长度 (PDU + 地址 + CRC)
#define MODBUS_DEFAULT_TIMEOUT          1000  // 默认超时时间(ms)

/* Modbus 主机状态定义 */
typedef enum {
    MODBUS_MASTER_STATE_IDLE,       // 空闲状态
    MODBUS_MASTER_STATE_WAIT_REPLY, // 等待从机回复
    MODBUS_MASTER_STATE_PROCESS     // 处理接收的数据
} ModbusMasterState;

/* Modbus 错误码定义 */
typedef enum {
    MODBUS_MASTER_OK = 0,                   // 操作成功
    MODBUS_MASTER_ERROR_TIMEOUT,            // 通信超时
    MODBUS_MASTER_ERROR_CRC,                // CRC校验错误
    MODBUS_MASTER_ERROR_EXCEPTION,          // 从机返回异常
    MODBUS_MASTER_ERROR_INVALID_SLAVE_ID,   // 无效的从机ID
    MODBUS_MASTER_ERROR_INVALID_RESPONSE,   // 无效的从机响应
    MODBUS_MASTER_ERROR_BUSY                // 主机忙,无法处理新请求
} ModbusMasterError;

/* Modbus 主机配置 */
typedef struct {
    UART_HandleTypeDef *huart;        // 串口句柄
    uint32_t timeout;                 // 通信超时时间(ms)
    OS_SEM rxSem;                     // 接收信号量
    OS_MUTEX mutex;                   // 互斥信号量
    ModbusMasterState state;          // 当前状态
    uint8_t rxBuffer[MODBUS_MAX_ADU_LENGTH]; // 接收缓冲区
    uint16_t rxCount;                 // 接收计数
    uint8_t txBuffer[MODBUS_MAX_ADU_LENGTH]; // 发送缓冲区
    uint8_t lastSlaveID;              // 上一次通信的从机ID
    uint8_t lastFunctionCode;         // 上一次发送的功能码
    ModbusMasterError lastError;      // 最后一次错误
    uint8_t expectLength;             // 预期接收长度
    OS_TMR timeoutTimer;              // 超时定时器
} ModbusMaster;

/* 函数原型 */

/**
 * @brief  初始化Modbus主机
 * @param  mbus: Modbus主机结构体指针
 * @param  huart: 使用的串口句柄
 * @param  timeout: 通信超时时间(ms)
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_Init(ModbusMaster *mbus, UART_HandleTypeDef *huart, uint32_t timeout);

/**
 * @brief  读取线圈状态 (功能码0x01)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 线圈数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadCoils(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint8_t *data);

/**
 * @brief  读取离散输入状态 (功能码0x02)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 输入数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadDiscreteInputs(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint8_t *data);

/**
 * @brief  读取保持寄存器 (功能码0x03)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadHoldingRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint16_t *data);

/**
 * @brief  读取输入寄存器 (功能码0x04)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadInputRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint16_t *data);

/**
 * @brief  写单个线圈 (功能码0x05)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  coilAddr: 线圈地址
 * @param  value: 线圈值 (0=OFF, 非0=ON)
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteSingleCoil(ModbusMaster *mbus, uint8_t slaveID, uint16_t coilAddr, bool value);

/**
 * @brief  写单个寄存器 (功能码0x06)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  regAddr: 寄存器地址
 * @param  value: 寄存器值
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteSingleRegister(ModbusMaster *mbus, uint8_t slaveID, uint16_t regAddr, uint16_t value);

/**
 * @brief  写多个线圈 (功能码0x0F)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 线圈数量
 * @param  data: 线圈值数组
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteMultipleCoils(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, const uint8_t *data);

/**
 * @brief  写多个寄存器 (功能码0x10)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 寄存器值数组
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteMultipleRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, const uint16_t *data);

/**
 * @brief  获取错误描述
 * @param  error: 错误码
 * @retval 错误描述字符串
 */
const char* ModbusMaster_GetErrorString(ModbusMasterError error);

/**
 * @brief  设置通信超时时间
 * @param  mbus: Modbus主机结构体指针
 * @param  timeout: 超时时间(ms)
 * @retval None
 */
void ModbusMaster_SetTimeout(ModbusMaster *mbus, uint32_t timeout);

/**
 * @brief  UART接收回调函数,应在HAL_UART_RxCpltCallback中调用
 * @param  mbus: Modbus主机结构体指针
 * @param  huart: 串口句柄
 * @retval None
 */
void ModbusMaster_UartRxCpltCallback(ModbusMaster *mbus, UART_HandleTypeDef *huart);

/**
 * @brief  超时回调函数,内部使用
 * @param  p_tmr: 定时器指针
 * @param  p_arg: 参数指针 (ModbusMaster结构体)
 * @retval None
 */
void ModbusMaster_TimeoutCallback(OS_TMR *p_tmr, void *p_arg);

#ifdef __cplusplus
}
#endif

#endif /* __MODBUS_MASTER_H */
/**
  ******************************************************************************
  * @file    modbus_master.c
  * @author  Claude AI
  * @brief   Modbus RTU Master mode implementation
  * @details 基于STM32 HAL库和uCOS-III的Modbus-RTU主机实现
  ******************************************************************************
  */

#include "modbus_master.h"

/* 私有函数声明 */
static uint16_t ModbusMaster_CRC16(const uint8_t *buffer, uint16_t length);
static ModbusMasterError ModbusMaster_SendRequest(ModbusMaster *mbus, uint8_t slaveID, uint8_t functionCode, 
                                        uint8_t *data, uint16_t dataLen, uint16_t expectedLen);
static ModbusMasterError ModbusMaster_ProcessResponse(ModbusMaster *mbus);

/**
 * @brief  计算Modbus CRC16校验
 * @param  buffer: 数据缓冲区
 * @param  length: 数据长度
 * @retval CRC校验值
 */
static uint16_t ModbusMaster_CRC16(const uint8_t *buffer, uint16_t length)
{
    uint16_t crc = 0xFFFF;
    uint16_t i, j;
    
    for (i = 0; i < length; i++) {
        crc ^= buffer[i];
        for (j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

/**
 * @brief  初始化Modbus主机
 * @param  mbus: Modbus主机结构体指针
 * @param  huart: 使用的串口句柄
 * @param  timeout: 通信超时时间(ms)
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_Init(ModbusMaster *mbus, UART_HandleTypeDef *huart, uint32_t timeout)
{
    OS_ERR err;
    
    /* 参数检查 */
    if (mbus == NULL || huart == NULL) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 初始化结构体 */
    memset(mbus, 0, sizeof(ModbusMaster));
    mbus->huart = huart;
    mbus->timeout = (timeout > 0) ? timeout : MODBUS_DEFAULT_TIMEOUT;
    mbus->state = MODBUS_MASTER_STATE_IDLE;
    mbus->lastError = MODBUS_MASTER_OK;
    
    /* 创建信号量 */
    OSSemCreate(&mbus->rxSem, "Modbus RX Sem", 0, &err);
    if (err != OS_ERR_NONE) {
        return MODBUS_MASTER_ERROR_BUSY;
    }
    
    /* 创建互斥信号量 */
    OSMutexCreate(&mbus->mutex, "Modbus Mutex", &err);
    if (err != OS_ERR_NONE) {
        return MODBUS_MASTER_ERROR_BUSY;
    }
    
    /* 创建超时定时器 */
    OSTmrCreate(&mbus->timeoutTimer, "Modbus Timeout Timer", 0, 0, OS_OPT_TMR_ONE_SHOT,
                ModbusMaster_TimeoutCallback, mbus, &err);
    if (err != OS_ERR_NONE) {
        return MODBUS_MASTER_ERROR_BUSY;
    }
    
    /* 启用UART接收中断 */
    HAL_UART_Receive_IT(mbus->huart, mbus->rxBuffer, 1);
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  设置通信超时时间
 * @param  mbus: Modbus主机结构体指针
 * @param  timeout: 超时时间(ms)
 * @retval None
 */
void ModbusMaster_SetTimeout(ModbusMaster *mbus, uint32_t timeout)
{
    OS_ERR err;
    
    if (mbus == NULL || timeout == 0) {
        return;
    }
    
    OSMutexPend(&mbus->mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    mbus->timeout = timeout;
    OSMutexPost(&mbus->mutex, OS_OPT_POST_NONE, &err);
}

/**
 * @brief  发送Modbus请求并等待响应
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  functionCode: 功能码
 * @param  data: 数据缓冲区
 * @param  dataLen: 数据长度
 * @param  expectedLen: 预期响应长度 (0表示未知长度)
 * @retval 错误码
 */
static ModbusMasterError ModbusMaster_SendRequest(ModbusMaster *mbus, uint8_t slaveID, uint8_t functionCode,
                                       uint8_t *data, uint16_t dataLen, uint16_t expectedLen)
{
    OS_ERR err;
    uint16_t crc;
    uint32_t tickStart;
    OS_ERR tmrErr;
    CPU_TS ts;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || dataLen > MODBUS_MAX_PDU_LENGTH - 1) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 获取互斥锁 */
    OSMutexPend(&mbus->mutex, 0, OS_OPT_PEND_BLOCKING, &ts, &err);
    if (err != OS_ERR_NONE) {
        return MODBUS_MASTER_ERROR_BUSY;
    }
    
    /* 检查是否空闲 */
    if (mbus->state != MODBUS_MASTER_STATE_IDLE) {
        OSMutexPost(&mbus->mutex, OS_OPT_POST_NONE, &err);
        return MODBUS_MASTER_ERROR_BUSY;
    }
    
    /* 构建请求帧 */
    mbus->txBuffer[0] = slaveID;
    mbus->txBuffer[1] = functionCode;
    if (dataLen > 0) {
        memcpy(&mbus->txBuffer[2], data, dataLen);
    }
    
    /* 计算CRC */
    crc = ModbusMaster_CRC16(mbus->txBuffer, dataLen + 2);
    mbus->txBuffer[dataLen + 2] = crc & 0xFF;          // CRC低字节
    mbus->txBuffer[dataLen + 3] = (crc >> 8) & 0xFF;   // CRC高字节
    
    /* 准备接收响应 */
    mbus->state = MODBUS_MASTER_STATE_WAIT_REPLY;
    mbus->rxCount = 0;
    mbus->lastSlaveID = slaveID;
    mbus->lastFunctionCode = functionCode;
    mbus->expectLength = expectedLen;
    
    /* 清除信号量 */
    OSSemSet(&mbus->rxSem, 0, &err);
    
    /* 启动超时定时器 */
    OSTmrStop(&mbus->timeoutTimer, OS_OPT_TMR_NONE, NULL, &tmrErr);
    OSTmrSet(&mbus->timeoutTimer, mbus->timeout / (1000 / OSCfg_TmrTaskRate_Hz), 0, &ModbusMaster_TimeoutCallback, mbus, &tmrErr);
    OSTmrStart(&mbus->timeoutTimer, &tmrErr);
    
    /* 发送请求 */
    HAL_UART_Transmit(mbus->huart, mbus->txBuffer, dataLen + 4, 1000);
    
    /* 等待响应 */
    if (OSSemPend(&mbus->rxSem, mbus->timeout, OS_OPT_PEND_BLOCKING, &ts, &err) != OS_ERR_NONE) {
        mbus->state = MODBUS_MASTER_STATE_IDLE;
        mbus->lastError = MODBUS_MASTER_ERROR_TIMEOUT;
        OSMutexPost(&mbus->mutex, OS_OPT_POST_NONE, &err);
        return MODBUS_MASTER_ERROR_TIMEOUT;
    }
    
    /* 停止超时定时器 */
    OSTmrStop(&mbus->timeoutTimer, OS_OPT_TMR_NONE, NULL, &tmrErr);
    
    /* 处理响应 */
    mbus->lastError = ModbusMaster_ProcessResponse(mbus);
    mbus->state = MODBUS_MASTER_STATE_IDLE;
    
    /* 释放互斥锁 */
    OSMutexPost(&mbus->mutex, OS_OPT_POST_NONE, &err);
    
    return mbus->lastError;
}

/**
 * @brief  处理Modbus响应
 * @param  mbus: Modbus主机结构体指针
 * @retval 错误码
 */
static ModbusMasterError ModbusMaster_ProcessResponse(ModbusMaster *mbus)
{
    uint16_t crc, receivedCrc;
    
    /* 检查接收数据长度 */
    if (mbus->rxCount < 4) { // 至少包含从机地址、功能码、数据和CRC
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 检查从机地址 */
    if (mbus->rxBuffer[0] != mbus->lastSlaveID) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 检查CRC */
    crc = ModbusMaster_CRC16(mbus->rxBuffer, mbus->rxCount - 2);
    receivedCrc = (mbus->rxBuffer[mbus->rxCount - 1] << 8) | mbus->rxBuffer[mbus->rxCount - 2];
    if (crc != receivedCrc) {
        return MODBUS_MASTER_ERROR_CRC;
    }
    
    /* 检查是否有异常 */
    if ((mbus->rxBuffer[1] & 0x80) && mbus->rxCount >= 5) {
        // 异常响应
        return MODBUS_MASTER_ERROR_EXCEPTION;
    }
    
    /* 检查功能码 */
    if (mbus->rxBuffer[1] != mbus->lastFunctionCode) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  UART接收回调函数,应在HAL_UART_RxCpltCallback中调用
 * @param  mbus: Modbus主机结构体指针
 * @param  huart: 串口句柄
 * @retval None
 */
void ModbusMaster_UartRxCpltCallback(ModbusMaster *mbus, UART_HandleTypeDef *huart)
{
    OS_ERR err;
    
    if (mbus == NULL || huart != mbus->huart || mbus->state != MODBUS_MASTER_STATE_WAIT_REPLY) {
        return;
    }
    
    /* 增加接收计数 */
    mbus->rxCount++;
    
    /* 如果已接收到足够的数据 */
    if ((mbus->expectLength > 0 && mbus->rxCount >= mbus->expectLength) || 
        mbus->rxCount >= MODBUS_MAX_ADU_LENGTH) {
        mbus->state = MODBUS_MASTER_STATE_PROCESS;
        OSSemPost(&mbus->rxSem, OS_OPT_POST_1, &err); // 发送信号量
        return;
    }
    
    /* 如果收到异常帧(功能码最高位置1) */
    if (mbus->rxCount >= 3 && (mbus->rxBuffer[1] & 0x80)) {
        if (mbus->rxCount >= 5) { // 异常响应长度:从机ID(1) + 功能码(1) + 错误码(1) + CRC(2) = 5
            mbus->state = MODBUS_MASTER_STATE_PROCESS;
            OSSemPost(&mbus->rxSem, OS_OPT_POST_1, &err);
            return;
        }
    }
    
    /* 特定功能码的响应处理 */
    if (mbus->rxCount >= 3) {
        uint8_t byteCount;
        switch (mbus->lastFunctionCode) {
            case MODBUS_READ_COILS:
            case MODBUS_READ_DISCRETE_INPUTS:
            case MODBUS_READ_HOLDING_REGISTERS:
            case MODBUS_READ_INPUT_REGISTERS:
                if (mbus->rxCount == 3) {
                    byteCount = mbus->rxBuffer[2];
                    /* 计算总响应长度: 从机ID(1) + 功能码(1) + 字节数(1) + 数据(n) + CRC(2) */
                    mbus->expectLength = 3 + byteCount + 2;
                }
                break;
                
            case MODBUS_WRITE_SINGLE_COIL:
            case MODBUS_WRITE_SINGLE_REGISTER:
                /* 响应长度: 从机ID(1) + 功能码(1) + 地址(2) + 值(2) + CRC(2) = 8 */
                mbus->expectLength = 8;
                break;
                
            case MODBUS_WRITE_MULTIPLE_COILS:
            case MODBUS_WRITE_MULTIPLE_REGISTERS:
                /* 响应长度: 从机ID(1) + 功能码(1) + 地址(2) + 数量(2) + CRC(2) = 8 */
                mbus->expectLength = 8;
                break;
                
            default:
                break;
        }
    }
    
    /* 继续接收数据 */
    HAL_UART_Receive_IT(mbus->huart, &mbus->rxBuffer[mbus->rxCount], 1);
}

/**
 * @brief  超时回调函数,内部使用
 * @param  p_tmr: 定时器指针
 * @param  p_arg: 参数指针 (ModbusMaster结构体)
 * @retval None
 */
void ModbusMaster_TimeoutCallback(OS_TMR *p_tmr, void *p_arg)
{
    ModbusMaster *mbus = (ModbusMaster *)p_arg;
    OS_ERR err;
    
    if (mbus == NULL || mbus->state != MODBUS_MASTER_STATE_WAIT_REPLY) {
        return;
    }
    
    mbus->lastError = MODBUS_MASTER_ERROR_TIMEOUT;
    OSSemPost(&mbus->rxSem, OS_OPT_POST_1, &err);
}

/**
 * @brief  读取线圈状态 (功能码0x01)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 线圈数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadCoils(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint8_t *data)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    uint8_t byteCount;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 2000) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_READ_COILS, requestData, 4, 0);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 处理响应数据 */
    byteCount = mbus->rxBuffer[2];
    if (byteCount != (quantity + 7) / 8) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 复制数据 */
    memcpy(data, &mbus->rxBuffer[3], byteCount);
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  读取离散输入状态 (功能码0x02)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 输入数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadDiscreteInputs(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint8_t *data)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    uint8_t byteCount;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 2000) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_READ_DISCRETE_INPUTS, requestData, 4, 0);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 处理响应数据 */
    byteCount = mbus->rxBuffer[2];
    if (byteCount != (quantity + 7) / 8) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 复制数据 */
    memcpy(data, &mbus->rxBuffer[3], byteCount);
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  读取保持寄存器 (功能码0x03)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadHoldingRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint16_t *data)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    uint8_t byteCount;
    uint16_t i;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 125) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_READ_HOLDING_REGISTERS, requestData, 4, 0);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 处理响应数据 */
    byteCount = mbus->rxBuffer[2];
    if (byteCount != quantity * 2) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 复制并转换数据 (高字节在前) */
    for (i = 0; i < quantity; i++) {
        data[i] = (mbus->rxBuffer[3 + i * 2] << 8) | mbus->rxBuffer[4 + i * 2];
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  读取输入寄存器 (功能码0x04)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 接收数据缓冲区
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_ReadInputRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, uint16_t *data)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    uint8_t byteCount;
    uint16_t i;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 125) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_READ_INPUT_REGISTERS, requestData, 4, 0);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 处理响应数据 */
    byteCount = mbus->rxBuffer[2];
    if (byteCount != quantity * 2) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    /* 复制并转换数据 (高字节在前) */
    for (i = 0; i < quantity; i++) {
        data[i] = (mbus->rxBuffer[3 + i * 2] << 8) | mbus->rxBuffer[4 + i * 2];
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  写单个线圈 (功能码0x05)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  coilAddr: 线圈地址
 * @param  value: 线圈值 (0=OFF, 非0=ON)
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteSingleCoil(ModbusMaster *mbus, uint8_t slaveID, uint16_t coilAddr, bool value)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (coilAddr >> 8) & 0xFF;      // 地址高字节
    requestData[1] = coilAddr & 0xFF;             // 地址低字节
    requestData[2] = value ? 0xFF : 0x00;         // 值高字节 (FF00=ON, 0000=OFF)
    requestData[3] = 0x00;                        // 值低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_WRITE_SINGLE_COIL, requestData, 4, 8);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 验证响应中的地址和值 */
    if (((mbus->rxBuffer[2] << 8) | mbus->rxBuffer[3]) != coilAddr ||
        ((mbus->rxBuffer[4] << 8) | mbus->rxBuffer[5]) != (value ? 0xFF00 : 0x0000)) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  写单个寄存器 (功能码0x06)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  regAddr: 寄存器地址
 * @param  value: 寄存器值
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteSingleRegister(ModbusMaster *mbus, uint8_t slaveID, uint16_t regAddr, uint16_t value)
{
    uint8_t requestData[4];
    ModbusMasterError error;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 构建请求数据 */
    requestData[0] = (regAddr >> 8) & 0xFF;    // 地址高字节
    requestData[1] = regAddr & 0xFF;           // 地址低字节
    requestData[2] = (value >> 8) & 0xFF;      // 值高字节
    requestData[3] = value & 0xFF;             // 值低字节
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_WRITE_SINGLE_REGISTER, requestData, 4, 8);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 验证响应中的地址和值 */
    if (((mbus->rxBuffer[2] << 8) | mbus->rxBuffer[3]) != regAddr ||
        ((mbus->rxBuffer[4] << 8) | mbus->rxBuffer[5]) != value) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  写多个线圈 (功能码0x0F)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 线圈数量
 * @param  data: 线圈值数组
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteMultipleCoils(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, const uint8_t *data)
{
    uint8_t requestData[MODBUS_MAX_PDU_LENGTH - 1];
    ModbusMasterError error;
    uint8_t byteCount;
    uint16_t i;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 1968) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 计算字节数 */
    byteCount = (quantity + 7) / 8;
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    requestData[4] = byteCount;                // 字节数
    
    /* 复制线圈值 */
    for (i = 0; i < byteCount; i++) {
        requestData[5 + i] = data[i];
    }
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_WRITE_MULTIPLE_COILS, requestData, 5 + byteCount, 8);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 验证响应中的地址和数量 */
    if (((mbus->rxBuffer[2] << 8) | mbus->rxBuffer[3]) != startAddr ||
        ((mbus->rxBuffer[4] << 8) | mbus->rxBuffer[5]) != quantity) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  写多个寄存器 (功能码0x10)
 * @param  mbus: Modbus主机结构体指针
 * @param  slaveID: 从机地址
 * @param  startAddr: 起始地址
 * @param  quantity: 寄存器数量
 * @param  data: 寄存器值数组
 * @retval 错误码
 */
ModbusMasterError ModbusMaster_WriteMultipleRegisters(ModbusMaster *mbus, uint8_t slaveID, uint16_t startAddr, uint16_t quantity, const uint16_t *data)
{
    uint8_t requestData[MODBUS_MAX_PDU_LENGTH - 1];
    ModbusMasterError error;
    uint8_t byteCount;
    uint16_t i;
    
    /* 参数检查 */
    if (mbus == NULL || slaveID == 0 || slaveID > 247 || data == NULL || quantity == 0 || quantity > 123) {
        return MODBUS_MASTER_ERROR_INVALID_SLAVE_ID;
    }
    
    /* 计算字节数 */
    byteCount = quantity * 2;
    
    /* 构建请求数据 */
    requestData[0] = (startAddr >> 8) & 0xFF;  // 起始地址高字节
    requestData[1] = startAddr & 0xFF;         // 起始地址低字节
    requestData[2] = (quantity >> 8) & 0xFF;   // 数量高字节
    requestData[3] = quantity & 0xFF;          // 数量低字节
    requestData[4] = byteCount;                // 字节数
    
    /* 复制寄存器值 */
    for (i = 0; i < quantity; i++) {
        requestData[5 + i * 2] = (data[i] >> 8) & 0xFF; // 值高字节
        requestData[6 + i * 2] = data[i] & 0xFF;        // 值低字节
    }
    
    /* 发送请求并等待响应 */
    error = ModbusMaster_SendRequest(mbus, slaveID, MODBUS_WRITE_MULTIPLE_REGISTERS, requestData, 5 + byteCount, 8);
    if (error != MODBUS_MASTER_OK) {
        return error;
    }
    
    /* 验证响应中的地址和数量 */
    if (((mbus->rxBuffer[2] << 8) | mbus->rxBuffer[3]) != startAddr ||
        ((mbus->rxBuffer[4] << 8) | mbus->rxBuffer[5]) != quantity) {
        return MODBUS_MASTER_ERROR_INVALID_RESPONSE;
    }
    
    return MODBUS_MASTER_OK;
}

/**
 * @brief  获取错误描述
 * @param  error: 错误码
 * @retval 错误描述字符串
 */
const char* ModbusMaster_GetErrorString(ModbusMasterError error)
{
    switch (error) {
        case MODBUS_MASTER_OK:
            return "成功";
        case MODBUS_MASTER_ERROR_TIMEOUT:
            return "通信超时";
        case MODBUS_MASTER_ERROR_CRC:
            return "CRC校验错误";
        case MODBUS_MASTER_ERROR_EXCEPTION:
            return "从机返回异常";
        case MODBUS_MASTER_ERROR_INVALID_SLAVE_ID:
            return "无效的从机ID";
        case MODBUS_MASTER_ERROR_INVALID_RESPONSE:
            return "无效的从机响应";
        case MODBUS_MASTER_ERROR_BUSY:
            return "主机忙,无法处理新请求";
        default:
            return "未知错误";
    }
}

 代码库使用示例

/**
  ******************************************************************************
  * @file    modbus_example.c
  * @author  Claude AI
  * @brief   Modbus RTU Master example
  * @details 基于STM32 HAL库和uCOS-III的Modbus-RTU主机使用示例
  ******************************************************************************
  */

#include "modbus_master.h"

/* 定义Modbus主机实例 */
ModbusMaster modbusInstance;

void ModbusExample_Init(void)
{
    /* 假设UART3已经在其他地方初始化 */
    extern UART_HandleTypeDef huart3;
    
    /* 初始化Modbus主机,使用UART3,超时时间设为1000ms */
    ModbusMaster_Init(&modbusInstance, &huart3, 1000);
}

/* UART接收中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART3) {
        /* 处理Modbus接收中断 */
        ModbusMaster_UartRxCpltCallback(&modbusInstance, huart);
    }
}

/* 读取保持寄存器示例 */
void ModbusExample_ReadHoldingRegisters(void)
{
    uint16_t registerValues[10];
    ModbusMasterError error;
    
    /* 从从机地址1读取起始地址为0的10个保持寄存器 */
    error = ModbusMaster_ReadHoldingRegisters(&modbusInstance, 1, 0, 10, registerValues);
    
    if (error == MODBUS_MASTER_OK) {
        /* 数据读取成功,可以使用registerValues中的数据 */
        printf("读取成功,第一个寄存器值: %d\n", registerValues[0]);
    } else {
        /* 发生错误 */
        printf("读取失败: %s\n", ModbusMaster_GetErrorString(error));
    }
}

/* 写单个寄存器示例 */
void ModbusExample_WriteSingleRegister(void)
{
    ModbusMasterError error;
    
    /* 向从机地址1的寄存器地址100写入值1234 */
    error = ModbusMaster_WriteSingleRegister(&modbusInstance, 1, 100, 1234);
    
    if (error == MODBUS_MASTER_OK) {
        /* 数据写入成功 */
        printf("写入成功\n");
    } else {
        /* 发生错误 */
        printf("写入失败: %s\n", ModbusMaster_GetErrorString(error));
    }
}

/* 写多个寄存器示例 */
void ModbusExample_WriteMultipleRegisters(void)
{
    ModbusMasterError error;
    uint16_t values[5] = {1000, 2000, 3000, 4000, 5000};
    
    /* 向从机地址1的起始地址200写入5个寄存器 */
    error = ModbusMaster_WriteMultipleRegisters(&modbusInstance, 1, 200, 5, values);
    
    if (error == MODBUS_MASTER_OK) {
        /* 数据写入成功 */
        printf("写入多个寄存器成功\n");
    } else {
        /* 发生错误 */
        printf("写入失败: %s\n", ModbusMaster_GetErrorString(error));
    }
}

/* 自定义超时时间示例 */
void ModbusExample_SetTimeout(void)
{
    /* 设置通信超时时间为2000ms */
    ModbusMaster_SetTimeout(&modbusInstance, 2000);
    
    printf("超时时间已设置为2000ms\n");
}

/* 主函数示例 */
void ModbusExample_Run(void)
{
    /* 初始化Modbus */
    ModbusExample_Init();
    
    /* 使用示例 */
    ModbusExample_ReadHoldingRegisters();
    ModbusExample_WriteSingleRegister();
    ModbusExample_WriteMultipleRegisters();
    ModbusExample_SetTimeout();
}

代码说明:

  1. 模块化设计:所有Modbus功能都被封装在模块化的API中,易于使用和维护。

  2. 完整的功能码实现

    • 0x01:读取线圈状态
    • 0x02:读取离散输入状态
    • 0x03:读取保持寄存器
    • 0x04:读取输入寄存器
    • 0x05:写单个线圈
    • 0x06:写单个寄存器
    • 0x0F:写多个线圈
    • 0x10:写多个寄存器
  3. CRC校验:实现了标准的Modbus CRC16校验算法。

  4. 超时处理:使用uCOS-III的定时器实现超时机制,可以自定义超时时间。

  5. 多从机支持:通过slaveID参数支持与多个从机设备通信,支持至少10个从机设备。

  6. 错误处理:完善的错误检测和处理机制,包括CRC错误、通信超时、从机异常码等。

  7. 线程安全:使用互斥信号量保证同时只有一个线程可以使用Modbus通信。

### Modbus RTU 中 DIcmd、AICmd 和 PIcmd 的含义 在 Modbus RTU 协议中,DIcmd、AICmd 和 PIcmd 并不是官方的标准术语,而是可能由某些特定厂商或应用场景引入的功能描述符。以下是这些术语的常见解释: #### 1. **DIcmd (Discrete Input Command)** DIcmd 通常用于表示离散输入(Discrete Inputs)的操作指令。离散输入是指布尔类型的二进制状态值(0 或 1),常用来监控开关、按钮或其他数字信号的状态。Modbus RTU 提供了一个专门的功能码来访问离散输入区域: - 功能码 `02` (`Read Discrete Inputs`) 被用来读取一组或多组离散输入寄存器的内容[^1]。 因此,DIcmd 可能是一个自定义名称,代表执行功能码 `02` 所需的相关操作逻辑。 --- #### 2. **AICmd (Analog Input Command)** AICmd 表示模拟量输入(Analog Inputs)的操作指令。模拟输入通常是连续变化的数值,例如温度、压力或电压等传感器采集的数据。这类数据存储于保持寄存器(Holding Registers)中,在 Modbus RTU 中可以通过以下功能码访问: - 功能码 `03` (`Read Holding Registers`) 用于读取多个保持寄存器中的模拟量数据[^1]。 - 功能码 `04` (`Read Input Registers`) 则可以读取只读型的输入寄存器内容。 AICmd 很可能是针对上述功能的一种封装或者简化调用方法。 --- #### 3. **PIcmd (Prescription Information Command)** PIcmd 是一个相对模糊的概念,具体意义取决于上下文环境。如果将其拆解来看,“Prescription”可理解为预设参数或配置信息。“Information”则指代与之关联的具体数据。综合起来,PIcmd 应该是用来设置或查询设备内部预定参数的一系列命令集合。 此类操作一般涉及入寄存器的动作,对应的功能码有: - 功能码 `06` (`Write Single Register`) 用于向单个保持寄存器入新值[^2]。 - 功能码 `16` (`Write Multiple Registers`) 支持批量更新一系列保持寄存器的内容。 需要注意的是,不同厂家可能会对 PIcmd 进行个性化扩展,建议查阅相关产品的技术文档获取更精确的信息。 --- ### 示例代码 下面展示如何利用 Java 实现基于 Modbus RTU 的基本交互过程,假设目标是从 Slave 设备读取离散输入和模拟输入数据并打印结果: ```java import com.deltamon.modbus.ModbusMaster; import com.deltamon.modbus.exception.ModbusTransportException; public class ModbusExample { public static void main(String[] args) throws Exception { try (ModbusMaster master = new ModbusMaster("/dev/ttyUSB0", 9600)) { // 初始化串口连接 int slaveId = 1; // 奴隶地址 short startAddress = 0; // 开始地址 int quantity = 8; // 数据数量 boolean[] diData = master.readDiscreteInputs(slaveId, startAddress, quantity); // 使用功能码 02 获取离散输入 System.out.println("Discrete Inputs Data:"); for (boolean value : diData) { System.out.print(value ? "ON " : "OFF "); } short[] aiData = master.readInputRegisters(slaveId, startAddress, quantity / 2); // 使用功能码 04 获取模拟输入 System.out.println("\n\nAnalog Inputs Data:"); for (short value : aiData) { System.out.printf("%d ", value); } } catch (ModbusTransportException e) { e.printStackTrace(); } } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值