最近调试一个激光测距模块使用modbus rtu协议,发现返回的数据不正常,尝试了用串口传输,发现返回的数据是正常的,但用libmodbus就无法返回正常数据,请问这是怎么回事?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "modbus.h"
#define GPIO_EXPORT_PATH "/sys/class/gpio/export"
#define GPIO_PIN_PATH "/sys/class/gpio/gpio41" // X为GPIO引脚号
// 定义MODBUS设备参数
const char *serial_port = "/dev/ttyS3"; // 串口设备路径
const int baud_rate = 115200;
const char parity = 'N';
const int data_bits = 8;
const int stop_bits = 1;
const int slave_id = 1;
// 定义测量数据结构
typedef struct {
float distance;
} MeasurementData;
int wp_gpio(){
int gpio_pin = 41; // 替换为您要操作的GPIO引脚号
// 导出GPIO引脚
FILE *export_file = fopen(GPIO_EXPORT_PATH, "w");
if (export_file == NULL) {
perror("Failed to open export file");
return 1;
}
fprintf(export_file, "%d", gpio_pin);
fclose(export_file);
// 设置GPIO引脚为输出模式
char direction_path[50];
sprintf(direction_path, "%s/direction", GPIO_PIN_PATH);
FILE *direction_file = fopen(direction_path, "w");
if (direction_file == NULL) {
perror("Failed to open direction file");
return 1;
}
fprintf(direction_file, "out");
fclose(direction_file);
// 将GPIO引脚设置为低电平
char value_path[50];
sprintf(value_path, "%s/value", GPIO_PIN_PATH);
FILE *value_file = fopen(value_path, "w");
if (value_file == NULL) {
perror("Failed to open value file");
return 1;
}
fprintf(value_file, "0"); // 设置为低电平
fclose(value_file);
// 在这里可以执行其他操作
// 将GPIO引脚设置为高电平(唤醒)
value_file = fopen(value_path, "w");
if (value_file == NULL) {
perror("Failed to open value file");
return 1;
}
fprintf(value_file, "1"); // 设置为高电平(唤醒)
fclose(value_file);
return 0;
}
int close_gpio() {
int gpio_pin = 41; // 替换为您要操作的GPIO引脚号
// 将GPIO引脚设置为低电平
char value_path[50];
sprintf(value_path, "%s/value", GPIO_PIN_PATH);
FILE *value_file = fopen(value_path, "w");
if (value_file == NULL) {
perror("Failed to open value file");
return 1;
}
fprintf(value_file, "0"); // 设置为低电平
fclose(value_file);
// 取消导出GPIO引脚
FILE *unexport_file = fopen("/sys/class/gpio/unexport", "w");
if (unexport_file == NULL) {
perror("Failed to open unexport file");
return 1;
}
fprintf(unexport_file, "%d", gpio_pin);
fclose(unexport_file);
return 0;
}
// 初始化MODBUS通信并连接到设备
modbus_t *initialize_modbus() {
modbus_t *ctx = modbus_new_rtu(serial_port, baud_rate, parity, data_bits, stop_bits);
if (ctx == NULL) {
fprintf(stderr, "Failed to create MODBUS context\n");
return NULL;
}
modbus_set_slave(ctx, slave_id);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "MODBUS connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return NULL;
}
return ctx;
}
// 读取测量数据
int read_measurement_data(modbus_t *ctx, MeasurementData *measurement) {
// 发送打开激光命令
uint16_t open_laser_cmd[] = {0x00, 0x01, 0x02, 0x00, 0x00};
uint16_t open_buffer[16]={0};
int write_result = modbus_write_registers(ctx, 0x1c05, sizeof(open_laser_cmd), open_laser_cmd);
if (write_result == -1) {
fprintf(stderr, "Failed to write open laser command: %s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return 1;
}
usleep(500000);
int ret = modbus_read_registers(ctx, 0x1c, 2, open_buffer);
printf(" ret = %d\n",ret);
printf("buffer: %x %x\n",open_buffer[0],open_buffer[1]);
// 开启测量
uint16_t start_measurement_cmd[] = {0x00, 0x01, 0x02, 0x00, 0x00};
uint16_t start_buffer[16]={0};
int start_write = modbus_write_registers(ctx, 0x1c06, sizeof(start_measurement_cmd), start_measurement_cmd);
if (start_write == -1) {
fprintf(stderr, "Failed to write start laser command: %s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return 1;
}
usleep(500000); // 500ms
modbus_read_registers(ctx, 0x1c, 2, start_buffer);
printf("start_buffer:%x %x\n",start_buffer[0],start_buffer[1]);
float measured_distance = -9999.0;
uint16_t read_measurement_cmd[] = {0x00, 0x02};
uint16_t measurement_data[4];
// 读取测量值
while (measured_distance <= 0) {
for(int i = 0;i<=4;i++){
// 发送读取测量值的命令
modbus_write_registers(ctx, 0x0100, sizeof(read_measurement_cmd), read_measurement_cmd);
// 等待读取完成
usleep(500000); // 500ms
// 读取测量值
modbus_read_registers(ctx, 0x04, 4, measurement_data);
printf("start_buffer:%x %x %x %x\n",measurement_data[0],measurement_data[1],measurement_data[2],measurement_data[3]);
// 解析测量值
uint16_t high_byte = measurement_data[2];
uint16_t low_byte = measurement_data[3];
/*
uint32_t combined_value = (high_byte << 16) | low_byte;
memcpy(&measured_distance, &combined_value, sizeof(float));*/
//memcpy(&measured_distance, measurement_data, sizeof(float));
uint32_t combined_value = (high_byte << 16) | low_byte;
float measured_distance;
memcpy(&measured_distance, &combined_value, sizeof(float));
// 根据您的需求,可以添加其他测量结果的处理
if (measured_distance > 0) {
break; // 退出循环
}
// 将测量值保存到measurement结构
measurement->distance = measured_distance;
usleep(100000); // 100ms
}
break;
}
return 0;
}
int main() {
wp_gpio();
// 初始化MODBUS通信
modbus_t *ctx = initialize_modbus();
if (ctx == NULL) {
return 1;
}
// 读取测量数据
MeasurementData measurement;
if (read_measurement_data(ctx, &measurement) == -1) {
fprintf(stderr, "Failed to read measurement data\n");
modbus_close(ctx);
modbus_free(ctx);
return 1;
}
// 打印测量结果
if (measurement.distance == -9999.0) {
fprintf(stdout, "Measurement failed or signal weak\n");
} else {
fprintf(stdout, "Measured Distance: %.2f meters\n", measurement.distance);
}
// 关闭MODBUS连接和释放上下文
modbus_close(ctx);
modbus_free(ctx);
close_gpio();
return 0;
}