传感器数据结构统一封装方法(结构体的使用)
程序员文章站
2022-03-22 19:56:16
...
在嵌入式开发中,经常遇到大量传感器数据需要获取,有可能这些传感器都是串口通信,IIC通信,或是485通信,区别仅仅是地址不同,数据量不一样,或是解析方式不同。为了增加程序可扩展性或是调试方便,往往会将有关传感器的数据统一进行管理,在C语言中,最常用的莫过于结构体了。
封装传感器结构体
我这里使用的传感器都是通过RS485进行通信的,是标准的ModBus RTU协议。每个传感器区别为地址不同,寄存器不同,寄存器长度不同。于是乎封装了以下结构体,可以将同一传感器数据进行统一管理。
typedef struct
{
uint8_t id; //设备地址
uint16_t reg_addr; //寄存器地址
uint16_t size; //寄存器长度
uint16_t data[4];//数据
uint8_t type[15];//传感器类型,描述性字符串
} SensorDataTypeDef ;
定义传感器
利用枚举类型定义我们的传感器地址。
typedef enum
{
RESERVE = 0x00,//保留
LIGHT = 0x01,
WINDSPEED = 0x02,
SOIL_TEMP_HUM = 0x03,
RAINFALL = 0x04,
SOIL_TEMP_HUM2 = 0x05,
AIR_TEMP_HUM = 0x06,
} SensorTypeDef;
然后使用刚刚的结构体定义我们的传感器。因为数组从0开始,传感器地址从1开始,所以使用一个保留字段。
SensorDataTypeDef sensorData[]=
{
{.id = RESERVE, .reg_addr = 0x02, .size = 2, .type = " " }, //保留
{.id = LIGHT, .reg_addr = 0x02, .size = 2, .type = "light" },
{.id = WINDSPEED, .reg_addr = 0x00, .size = 1, .type = "windspeed" },
{.id = SOIL_TEMP_HUM, .reg_addr = 0x00, .size = 2, .type = "soil_sensor_1" },
{.id = RAINFALL, .reg_addr = 0x0C, .size = 1, .type = "rainfall" },
{.id = SOIL_TEMP_HUM, .reg_addr = 0x00, .size = 2, .type = "soil_sensor_2" },
{.id = AIR_TEMP_HUM2, .reg_addr = 0x00, .size = 2, .type = "air_sensor" }
};
这样我们在获取传感器数据时将会非常方便,使用统一的函数接口即可获取到不同传感器的数据,非常方便。
uint8_t sensor_state = 0;
uint8_t readSensor(SensorTypeDef sensor)
{
uint16_t id = 0;
uint16_t addr=0;
uint16_t size=0;
id = sensorData[sensor].id;
addr = sensorData[sensor].reg_addr;
size = sensorData[sensor].size;
if ( ! ModbusMaster_readHoldingRegisters(id,addr, size) ) //读传感器寄存器
{
sensorData[sensor].data[0] = ModbusMaster_getResponseBuffer(0x00);
sensorData[sensor].data[1] = ModbusMaster_getResponseBuffer(0x01);
sensor_state &= (~( 1 << sensor )); //清零传感器出错标志位
return 0;
}
LOG("[systerm]:read error :%s\r\n", sensorData[sensor].type);
sensor_state |= ( 1 << sensor ); //置位传感器出错标志位
return sensor;
}
最后,这儿的sensor_state 变量占用一个字节,却可以表示8种不同类型的传感器状态,既节约空间又方便。
欢迎讨论~