我正在使用ESP32。我想用Modbus RTU与外部世界通信。ESP32将成为奴隶。如何用c语言创建一些modbus寄存器。知道吗?它只是一个简单的C表?非常感谢
我做了你想做的同样的事情,不是用ESP32,但它是一样的。
基本上,您将所有想要作为modbus寄存器访问的变量放在一个精确的位置,可能是一个结构。
例如
struct modbusmap_t {
uint16_t speed; // this has modbus address 0
unit16_t cooler; // ...and this address 1
...
} modbusregs;
您的设备是从设备,因此您将实现一个接收modbus命令的服务器。当请求写入寄存器"0"时;N〃;收到时,您可以简单地使用访问该寄存器
*((uint16_t *) &modbusregs + N) = requestvalue;
对于阅读,同样适用:
uint16result = *((uint16_t *) &modbusregs + N);
还有其他方法可以做到这一点,例如通过工会。
总之,关键是将所有可作为modbus寄存器访问的变量放在一个已知的有序位置,并使用指针或数组来读取/写入它们。对于bit(modbus线圈(来说,需要更多的技巧,但想法是一样的。
在这个例子中;modbus寄存器0〃;映射到变量";速度";在您的来源中。Modbus没有符号的概念,但您可以使用2-完成或添加偏移(32000表示0速度,32010表示速度10,31990表示速度-10,依此类推(来管理它。
您可以使用这个简单的代码并根据需要进行扩展我从esp32 idf源代码推迟
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <stdint.h>
typedef struct
{
float holding_data0;
float holding_data1;
float holding_data2;
float holding_data3;
uint16_t test_regs[150];
float holding_data4;
float holding_data5;
float holding_data6;
float holding_data7;
} holding_reg_params_t;
extern holding_reg_params_t holding_reg_params;
#define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) >> 1))
#define MB_REG_HOLDING_START_AREA0 (HOLD_OFFSET(holding_data0))
#define MB_REG_HOLDING_START_AREA1 (HOLD_OFFSET(holding_data4))
/**
* @brief Type of Modbus parameter
*/
typedef enum
{
MB_PARAM_HOLDING = 0x00, /*!< Modbus Holding register. */
MB_PARAM_INPUT, /*!< Modbus Input register. */
MB_PARAM_COIL, /*!< Modbus Coils. */
MB_PARAM_DISCRETE, /*!< Modbus Discrete bits. */
MB_PARAM_COUNT,
MB_PARAM_UNKNOWN = 0xFF
} mb_param_type_t;
/**
* @brief Parameter storage area descriptor
*/
typedef struct
{
uint16_t start_offset; /*!< Modbus start address for area descriptor */
mb_param_type_t type; /*!< Type of storage area descriptor */
void *address; /*!< Instance address for storage area descriptor */
size_t size; /*!< Instance size for area descriptor (bytes) */
} mb_register_area_descriptor_t;
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
int main()
{
holding_reg_params_t holding_reg_params = {0};
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
holding_reg_params.holding_data0 = 1.34;
holding_reg_params.holding_data1 = 2.56;
holding_reg_params.holding_data2 = 3.78;
holding_reg_params.holding_data3 = 4.90;
holding_reg_params.holding_data4 = 5.67;
holding_reg_params.holding_data5 = 6.78;
holding_reg_params.holding_data6 = 7.79;
holding_reg_params.holding_data7 = 8.80;
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
reg_area.address = (void *)&holding_reg_params.holding_data0; // Set pointer to storage instance
// Set the size of register storage instance = 150 holding registers
reg_area.size = (size_t)(HOLD_OFFSET(holding_data4) - HOLD_OFFSET(test_regs));
*((float *)reg_area.address + reg_area.start_offset + 0) = 100;
*((float *)reg_area.address + reg_area.start_offset + 1) = 200;
*((float *)reg_area.address + reg_area.start_offset + 2) = 300;
*((float *)reg_area.address + reg_area.start_offset + 3) = 400;
*((uint16_t *)reg_area.address + reg_area.start_offset + 4) = 500;// be careful its wrong!
// ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
reg_area.start_offset = MB_REG_HOLDING_START_AREA1; // Offset of register area in Modbus protocol
reg_area.address = (void *)&holding_reg_params.holding_data4; // Set pointer to storage instance
reg_area.size = sizeof(float) << 2; // Set the size of register storage instance
// ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
// getchar();
}