目录
1. 类型与接口定义(sensor_framework.h)
1. DS18B20 驱动(sensor_ds18b20.c)
前言:
做嵌入式开发,如果没有好的框架以及架构,写出来的程序实时性以及扩展性不满足可维护性以及可移植性,那么程序写的就是失败的,所以强烈建议做嵌入式开发的朋友学习好的框架,学习架构知识!如果觉得认同,可以关注我,可以带你实现高级框架,优美的嵌入式系统框架!
另外,我的资源中上传了一本书:《从入职到架构师,嵌入式软件成长之路》,强烈建议下载阅读,学习如何更好的做架构设计!
正文:
在嵌入式 C 开发中,传感器驱动框架的封装需要兼顾可扩展性、移植性和易用性。核心思想是通过抽象接口屏蔽硬件细节,让上层应用无需关心传感器的具体通信方式(I2C/SPI/UART)和寄存器操作,只需调用统一 API 即可完成数据交互。
一、框架设计思路
- 接口抽象:将传感器的通用操作(初始化、读取数据、配置参数、销毁)抽象为函数指针,定义统一接口。
- 设备管理:通过注册 / 注销机制管理所有传感器,支持动态添加新传感器。
- 数据标准化:定义通用数据结构,统一不同传感器的输出格式(如温度、湿度、加速度等)。
- 硬件解耦:框架层不涉及具体硬件操作(如 I2C 时序),由传感器驱动实现细节。
二、框架核心实现
1. 类型与接口定义(sensor_framework.h)
首先定义传感器类型、状态码和核心接口,作为框架的 "协议"。
#ifndef SENSOR_FRAMEWORK_H
#define SENSOR_FRAMEWORK_H
#include <stdint.h>
#include <stdbool.h>
// 传感器类型枚举(可扩展)
typedef enum {
SENSOR_TYPE_TEMP, // 温度传感器
SENSOR_TYPE_HUMI, // 湿度传感器
SENSOR_TYPE_ACCEL, // 加速度传感器
SENSOR_TYPE_MAX
} SensorType;
// 传感器数据结构(通用格式,按需扩展)
typedef struct {
SensorType type; // 数据类型
union {
float temp; // 温度值 (℃)
float humi; // 湿度值 (%)
struct { // 加速度值 (g)
float x;
float y;
float z;
} accel;
} data;
uint32_t timestamp; // 数据时间戳
} SensorData;
// 传感器状态码
typedef enum {
SENSOR_OK = 0, // 操作成功
SENSOR_INIT_FAILED, // 初始化失败
SENSOR_READ_FAILED, // 读取失败
SENSOR_CFG_FAILED, // 配置失败
SENSOR_NOT_FOUND // 传感器未找到
} SensorStatus;
// 前向声明传感器设备结构体
typedef struct SensorDevice SensorDevice;
// 传感器操作接口(函数指针)
typedef SensorStatus (*SensorInitFunc)(SensorDevice *dev); // 初始化
typedef SensorStatus (*SensorReadFunc)(SensorDevice *dev, SensorData *data); // 读取数据
typedef SensorStatus (*SensorConfigFunc)(SensorDevice *dev, void *cfg); // 配置参数
typedef void (*SensorDestroyFunc)(SensorDevice *dev); // 销毁资源
// 传感器设备结构体(核心)
struct SensorDevice {
const char *name; // 传感器名称(如"DS18B20")
SensorType type; // 传感器类型
uint8_t id; // 唯一ID(用于区分同类型多个传感器)
void *private_data; // 私有数据(如I2C地址、引脚等硬件信息)
// 操作接口
SensorInitFunc init;
SensorReadFunc read;
SensorConfigFunc config;
SensorDestroyFunc destroy;
struct SensorDevice *next; // 链表节点(用于设备管理)
};
// 框架管理函数
SensorStatus sensor_register(SensorDevice *dev); // 注册传感器
SensorStatus sensor_unregister(uint8_t id); // 注销传感器
SensorDevice* sensor_find(uint8_t id); // 查找传感器
SensorStatus sensor_init_all(void); // 初始化所有传感器
SensorStatus sensor_read_data(uint8_t id, SensorData *data); // 读取指定传感器数据
#endif // SENSOR_FRAMEWORK_H
2. 框架实现(sensor_framework.c)
实现设备管理(注册 / 注销 / 查找)和通用 API,本质是维护一个传感器链表。
#include "sensor_framework.h"
#include <string.h>
// 传感器链表头(全局唯一)
static SensorDevice *sensor_list = NULL;
// 注册传感器(添加到链表)
SensorStatus sensor_register(SensorDevice *dev) {
if (dev == NULL || dev->name == NULL) {
return SENSOR_CFG_FAILED;
}
// 检查ID是否重复
SensorDevice *temp = sensor_list;
while (temp) {
if (temp->id == dev->id) {
return SENSOR_CFG_FAILED; // ID冲突
}
temp = temp->next;
}
// 添加到链表头部
dev->next = sensor_list;
sensor_list = dev;
return SENSOR_OK;
}
// 注销传感器(从链表移除)
SensorStatus sensor_unregister(uint8_t id) {
SensorDevice *prev = NULL;
SensorDevice *curr = sensor_list;
while (curr) {
if (curr->id == id) {
if (prev) {
prev->next = curr->next;
} else {
sensor_list = curr->next; // 移除头节点
}
if (curr->destroy) {
curr->destroy(curr); // 调用销毁函数释放资源
}
return SENSOR_OK;
}
prev = curr;
curr = curr->next;
}
return SENSOR_NOT_FOUND;
}
// 查找传感器(通过ID)
SensorDevice* sensor_find(uint8_t id) {
SensorDevice *temp = sensor_list;
while (temp) {
if (temp->id == id) {
return temp;
}
temp = temp->next;
}
return NULL;
}
// 初始化所有注册的传感器
SensorStatus sensor_init_all(void) {
SensorDevice *temp = sensor_list;
SensorStatus ret = SENSOR_OK;
while (temp) {
if (temp->init) {
if (temp->init(temp) != SENSOR_OK) {
ret = SENSOR_INIT_FAILED; // 只要有一个失败,整体返回失败
}
}
temp = temp->next;
}
return ret;
}
// 读取指定传感器数据
SensorStatus sensor_read_data(uint8_t id, SensorData *data) {
if (data == NULL) {
return SENSOR_CFG_FAILED;
}
SensorDevice *dev = sensor_find(id);
if (dev == NULL || dev->read == NULL) {
return SENSOR_NOT_FOUND;
}
return dev->read(dev, data);
}
三、传感器驱动实现(以 DS18B20 温度传感器为例)
传感器驱动需实现框架定义的接口,封装硬件细节(如 GPIO/I2C 操作)。
1. DS18B20 驱动(sensor_ds18b20.c)
#include "sensor_framework.h"
#include "ds18b20_hw.h" // 硬件层(如GPIO初始化、时序函数)
// DS18B20私有数据(硬件相关参数)
typedef struct {
uint8_t gpio_pin; // 连接的GPIO引脚
} DS18B20PrivateData;
// 初始化DS18B20
static SensorStatus ds18b20_init(SensorDevice *dev) {
if (dev == NULL || dev->private_data == NULL) {
return SENSOR_INIT_FAILED;
}
DS18B20PrivateData *priv = (DS18B20PrivateData*)dev->private_data;
// 调用硬件层初始化函数(如配置GPIO为输出)
if (ds18b20_hw_init(priv->gpio_pin) != 0) {
return SENSOR_INIT_FAILED;
}
return SENSOR_OK;
}
// 读取DS18B20温度数据
static SensorStatus ds18b20_read(SensorDevice *dev, SensorData *data) {
if (dev == NULL || data == NULL || dev->private_data == NULL) {
return SENSOR_READ_FAILED;
}
DS18B20PrivateData *priv = (DS18B20PrivateData*)dev->private_data;
float temp;
// 调用硬件层读取函数(如发送读取命令、解析温度)
if (ds18b20_hw_read(priv->gpio_pin, &temp) != 0) {
return SENSOR_READ_FAILED;
}
// 填充通用数据结构
data->type = SENSOR_TYPE_TEMP;
data->data.temp = temp;
data->timestamp = 0; // 实际应用中可使用系统定时器
return SENSOR_OK;
}
// 销毁DS18B20资源
static void ds18b20_destroy(SensorDevice *dev) {
if (dev && dev->private_data) {
// 释放私有数据(如果需要)
// free(dev->private_data); // 若使用动态内存
}
}
// 定义DS18B20设备实例
static DS18B20PrivateData ds18b20_priv = {
.gpio_pin = 5 // 假设连接到GPIO5
};
SensorDevice ds18b20_dev = {
.name = "DS18B20",
.type = SENSOR_TYPE_TEMP,
.id = 1, // 唯一ID
.private_data = &ds18b20_priv,
.init = ds18b20_init,
.read = ds18b20_read,
.config = NULL, // DS18B20无需复杂配置,可设为NULL
.destroy = ds18b20_destroy
};
四、使用示例(上层应用)
应用层通过框架 API 操作传感器,无需关心硬件细节。
#include "sensor_framework.h"
#include "sensor_ds18b20.h" // 包含具体传感器驱动
int main(void) {
SensorData data;
// 1. 注册传感器
sensor_register(&ds18b20_dev);
// 2. 初始化所有传感器
if (sensor_init_all() != SENSOR_OK) {
// 处理初始化失败
while (1);
}
// 3. 循环读取数据
while (1) {
// 读取ID=1的传感器(DS18B20)
if (sensor_read_data(1, &data) == SENSOR_OK) {
if (data.type == SENSOR_TYPE_TEMP) {
// 打印温度数据(实际应用中可发送到上位机等)
printf("Temp: %.2f℃\r\n", data.data.temp);
}
}
// 延时(根据需求调整)
delay_ms(1000);
}
return 0;
}
五、框架扩展与移植
- 添加新传感器:只需实现
SensorDevice结构体和接口函数,调用sensor_register注册即可。 - 移植到不同平台:修改传感器驱动中的硬件层(如
ds18b20_hw.c),适配新平台的 GPIO/I2C 驱动。 - 扩展功能:可添加传感器休眠 / 唤醒接口、数据滤波、校准等功能,只需在
SensorDevice中扩展函数指针。
该框架通过 "接口抽象 + 设备管理" 实现了传感器驱动的模块化,适合在资源有限的嵌入式系统中使用,同时兼顾了灵活性和可维护性。
1143

被折叠的 条评论
为什么被折叠?



