单片机仿Linux驱动开发(二)

框架核心特性汇总

  • 统一状态码:所有驱动共用一套状态定义,规范错误处理

  • 统一驱动接口(仿 Linux file_operations):所有外设均使用 Init/Read/Write/Ctrl/DeInit 统一接口,调用方式完全一致

  • 统一设备注册表(仿 device tree):支持设备注册、按名称获取,实现设备统一管理

  • 统一总线抽象(I2C/SPI):抽象总线操作,外设驱动无需关心底层总线实现,提升可移植性

  • 基础外设完整驱动:UART / I2C / SPI / ADC / PWM 全套实现,支持STM32 HAL库,可直接编译

  • 常用模块驱动:AHT10(温湿度)/ OLED(I2C)/ W25QXX(SPI Flash),基于统一框架开发

  • 支持 DMA / 中断:UART 预留DMA/中断接口,可直接替换使用

  • 可移植、可维护、可直接商用:严格分层解耦,内部细节隐藏,支持STM32全系列,适配各类项目

一、全局公共文件(所有驱动共用)

1.1 driver_common.h(核心标准)

c 复制代码
#ifndef __DRIVER_COMMON_H
#define __DRIVER_COMMON_H

#include "stm32f1xx_hal.h"
#include <stdint.h>
#include <string.h>

// 统一返回状态(所有驱动通用)
typedef enum {
    DRV_OK        = 0U,
    DRV_ERROR     = 1U,
    DRV_PARAM_ERR = 2U,
    DRV_BUSY      = 3U,
    DRV_TIMEOUT   = 4U,
    DRV_HW_ERR    = 5U
} DRV_StatusTypeDef;

// 统一驱动接口(仿Linux file_operations)
typedef struct {
    DRV_StatusTypeDef (*Init)(void *cfg);
    DRV_StatusTypeDef (*Read)(uint8_t *data, uint16_t len, uint32_t timeout);
    DRV_StatusTypeDef (*Write)(const uint8_t *data, uint16_t len, uint32_t timeout);
    DRV_StatusTypeDef (*Ctrl)(uint8_t cmd, void *param);
    DRV_StatusTypeDef (*DeInit)(void);
} DRV_DriverTypeDef;

#endif

1.2 driver_common.c(预留扩展)

c 复制代码
#include "driver_common.h"
// 预留全局工具函数、公共逻辑扩展

二、设备注册表(仿Linux device tree)

2.1 drv_dev.h

c 复制代码
#ifndef __DRV_DEV_H
#define __DRV_DEV_H

#include "driver_common.h"

// 设备类型枚举
typedef enum {
    DEV_TYPE_UART,
    DEV_TYPE_I2C,
    DEV_TYPE_SPI,
    DEV_TYPE_ADC,
    DEV_TYPE_PWM,
    DEV_TYPE_AHT10,
    DEV_TYPE_OLED,
    DEV_TYPE_FLASH
} DevTypeEnum;

// 设备结构体(统一管理)
typedef struct {
    const char* name;          // 设备名称(唯一)
    DevTypeEnum type;          // 设备类型
    const DRV_DriverTypeDef* drv; // 设备对应的驱动
    void* config;              // 设备配置参数
} Device_t;

// 设备注册接口
void dev_register(const Device_t* dev);
// 根据设备名称获取设备
const Device_t* dev_get(const char* name);

#endif

2.2 drv_dev.c

c 复制代码
#include "drv_dev.h"

#define MAX_DEV 32  // 最大支持设备数量
static const Device_t* g_dev_list[MAX_DEV] = {0}; // 设备列表
static uint8_t g_dev_cnt = 0;                     // 已注册设备计数

// 注册设备(将设备添加到设备列表)
void dev_register(const Device_t* dev) {
    if (g_dev_cnt >= MAX_DEV || dev == NULL) return;
    g_dev_list[g_dev_cnt++] = dev;
}

// 根据名称获取设备(遍历设备列表匹配名称)
const Device_t* dev_get(const char* name) {
    if (name == NULL) return NULL;
    for (int i = 0; i < g_dev_cnt; i++) {
        if (strcmp(g_dev_list[i]->name, name) == 0)
            return g_dev_list[i];
    }
    return NULL;
}

三、统一总线抽象层(I2C/SPI 通用)

3.1 drv_bus.h

c 复制代码
#ifndef __DRV_BUS_H
#define __DRV_BUS_H

#include "driver_common.h"

// 总线操作接口(统一I2C/SPI操作)
typedef struct {
    DRV_StatusTypeDef (*send)(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout);
    DRV_StatusTypeDef (*recv)(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout);
} BusOps_t;

// I2C总线结构体(绑定总线操作+设备地址)
typedef struct {
    const BusOps_t* ops;  // 总线操作接口
    uint8_t addr;         // I2C设备地址
} I2C_Bus_t;

// SPI总线结构体(绑定总线操作)
typedef struct {
    const BusOps_t* ops;  // 总线操作接口
} SPI_Bus_t;

#endif

3.2 drv_bus.c

c 复制代码
#include "drv_bus.h"
// 底层总线操作绑定预留,可根据实际硬件适配I2C/SPI底层实现
// 示例:可将drv_i2c、drv_spi的读写函数绑定到BusOps_t接口

四、基础外设完整驱动(统一接口)

4.1 UART 驱动(支持DMA/中断)

4.1.1 drv_uart.h

c 复制代码
#ifndef __DRV_UART_H
#define __DRV_UART_H

#include "driver_common.h"

// UART配置结构体
typedef struct {
    UART_HandleTypeDef *huart; // UART句柄(HAL库)
} DRV_UART_ConfigTypeDef;

// UART控制命令
typedef enum {
    UART_CMD_RESET = 0U,  // 复位UART
    UART_CMD_SET_BAUD     // 设置波特率
} DRV_UART_CmdTypeDef;

// 获取UART驱动实例
const DRV_DriverTypeDef *DRV_UART_GetDriver(void);

#endif

4.1.2 drv_uart.c(含DMA/中断支持)

c 复制代码
#include "drv_uart.h"

static DRV_UART_ConfigTypeDef s_uart_cfg; // 内部配置(static隐藏)

// 初始化UART
static DRV_StatusTypeDef UART_Init(void *cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    s_uart_cfg = *(DRV_UART_ConfigTypeDef *)cfg;
    return DRV_OK;
}

// 读取数据(支持中断/DMA,替换注释即可)
static DRV_StatusTypeDef UART_Read(uint8_t *data, uint16_t len, uint32_t timeout) {
    //  polling模式(默认)
    if (HAL_UART_Receive(s_uart_cfg.huart, data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    // DMA模式(替换上面一行即可)
    // if (HAL_UART_Receive_DMA(s_uart_cfg.huart, data, len) != HAL_OK)
    //     return DRV_ERROR;
    // 中断模式(替换上面一行即可)
    // if (HAL_UART_Receive_IT(s_uart_cfg.huart, data, len) != HAL_OK)
    //     return DRV_ERROR;
    return DRV_OK;
}

// 写入数据(支持中断/DMA,替换注释即可)
static DRV_StatusTypeDef UART_Write(const uint8_t *data, uint16_t len, uint32_t timeout) {
    // polling模式(默认)
    if (HAL_UART_Transmit(s_uart_cfg.huart, (uint8_t *)data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    // DMA模式(替换上面一行即可)
    // if (HAL_UART_Transmit_DMA(s_uart_cfg.huart, data, len) != HAL_OK)
    //     return DRV_ERROR;
    // 中断模式(替换上面一行即可)
    // if (HAL_UART_Transmit_IT(s_uart_cfg.huart, data, len) != HAL_OK)
    //     return DRV_ERROR;
    return DRV_OK;
}

// UART控制(预留扩展)
static DRV_StatusTypeDef UART_Ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param; // 避免未使用警告,可根据需求扩展
    return DRV_OK;
}

// 反初始化UART
static DRV_StatusTypeDef UART_DeInit(void) {
    return DRV_OK;
}

// UART驱动实例(绑定统一接口)
static const DRV_DriverTypeDef s_uart_drv = {
    .Init   = UART_Init,
    .Read   = UART_Read,
    .Write  = UART_Write,
    .Ctrl   = UART_Ctrl,
    .DeInit = UART_DeInit
};

// 对外提供驱动实例
const DRV_DriverTypeDef *DRV_UART_GetDriver(void) {
    return &s_uart_drv;
}

4.2 I2C 驱动

4.2.1 drv_i2c.h

c 复制代码
#ifndef __DRV_I2C_H
#define __DRV_I2C_H

#include "driver_common.h"

// I2C配置结构体
typedef struct {
    I2C_HandleTypeDef *hi2c; // I2C句柄(HAL库)
} DRV_I2C_ConfigTypeDef;

// I2C控制命令
typedef enum {
    I2C_CMD_RESET = 0U,  // 复位I2C
    I2C_CMD_SET_SPEED    // 设置I2C速度
} DRV_I2C_CmdTypeDef;

// 获取I2C驱动实例
const DRV_DriverTypeDef *DRV_I2C_GetDriver(void);

#endif

4.2.2 drv_i2c.c

c 复制代码
#include "drv_i2c.h"

static DRV_I2C_ConfigTypeDef s_i2c_cfg; // 内部配置(static隐藏)

// 初始化I2C
static DRV_StatusTypeDef I2C_Init(void *cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    s_i2c_cfg = *(DRV_I2C_ConfigTypeDef *)cfg;
    return DRV_OK;
}

// 读取I2C数据(主模式,默认地址0x70<<1,可根据设备修改)
static DRV_StatusTypeDef I2C_Read(uint8_t *data, uint16_t len, uint32_t timeout) {
    if (HAL_I2C_Master_Receive(s_i2c_cfg.hi2c, 0x70 << 1, data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    return DRV_OK;
}

// 写入I2C数据(主模式,默认地址0x70<<1,可根据设备修改)
static DRV_StatusTypeDef I2C_Write(const uint8_t *data, uint16_t len, uint32_t timeout) {
    if (HAL_I2C_Master_Transmit(s_i2c_cfg.hi2c, 0x70 << 1, (uint8_t *)data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    return DRV_OK;
}

// I2C控制(预留扩展)
static DRV_StatusTypeDef I2C_Ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化I2C
static DRV_StatusTypeDef I2C_DeInit(void) {
    return DRV_OK;
}

// I2C驱动实例(绑定统一接口)
static const DRV_DriverTypeDef s_i2c_drv = {
    .Init   = I2C_Init,
    .Read   = I2C_Read,
    .Write  = I2C_Write,
    .Ctrl   = I2C_Ctrl,
    .DeInit = I2C_DeInit
};

// 对外提供驱动实例
const DRV_DriverTypeDef *DRV_I2C_GetDriver(void) {
    return &s_i2c_drv;
}

4.3 SPI 驱动

4.3.1 drv_spi.h

c 复制代码
#ifndef __DRV_SPI_H
#define __DRV_SPI_H

#include "driver_common.h"

// SPI配置结构体
typedef struct {
    SPI_HandleTypeDef *hspi; // SPI句柄(HAL库)
} DRV_SPI_ConfigTypeDef;

// 获取SPI驱动实例
const DRV_DriverTypeDef *DRV_SPI_GetDriver(void);

#endif

4.3.2 drv_spi.c

c 复制代码
#include "drv_spi.h"

static DRV_SPI_ConfigTypeDef s_spi_cfg; // 内部配置(static隐藏)

// 初始化SPI
static DRV_StatusTypeDef SPI_Init(void *cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    s_spi_cfg = *(DRV_SPI_ConfigTypeDef *)cfg;
    return DRV_OK;
}

// 读取SPI数据
static DRV_StatusTypeDef SPI_Read(uint8_t *data, uint16_t len, uint32_t timeout) {
    if (HAL_SPI_Receive(s_spi_cfg.hspi, data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    return DRV_OK;
}

// 写入SPI数据
static DRV_StatusTypeDef SPI_Write(const uint8_t *data, uint16_t len, uint32_t timeout) {
    if (HAL_SPI_Transmit(s_spi_cfg.hspi, (uint8_t *)data, len, timeout) != HAL_OK)
        return DRV_ERROR;
    return DRV_OK;
}

// SPI控制(预留扩展)
static DRV_StatusTypeDef SPI_Ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化SPI
static DRV_StatusTypeDef SPI_DeInit(void) {
    return DRV_OK;
}

// SPI驱动实例(绑定统一接口)
static const DRV_DriverTypeDef s_spi_drv = {
    .Init   = SPI_Init,
    .Read   = SPI_Read,
    .Write  = SPI_Write,
    .Ctrl   = SPI_Ctrl,
    .DeInit = SPI_DeInit
};

// 对外提供驱动实例
const DRV_DriverTypeDef *DRV_SPI_GetDriver(void) {
    return &s_spi_drv;
}

4.4 ADC 驱动

4.4.1 drv_adc.h

c 复制代码
#ifndef __DRV_ADC_H
#define __DRV_ADC_H

#include "driver_common.h"

// ADC配置结构体
typedef struct {
    ADC_HandleTypeDef *hadc; // ADC句柄(HAL库)
} DRV_ADC_ConfigTypeDef;

// 获取ADC驱动实例
const DRV_DriverTypeDef *DRV_ADC_GetDriver(void);

#endif

4.4.2 drv_adc.c

c 复制代码
#include "drv_adc.h"

static DRV_ADC_ConfigTypeDef s_adc_cfg; // 内部配置(static隐藏)

// 初始化ADC
static DRV_StatusTypeDef ADC_Init(void *cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    s_adc_cfg = *(DRV_ADC_ConfigTypeDef *)cfg;
    return DRV_OK;
}

// 读取ADC数据(Polling模式,可扩展中断/DMA)
static DRV_StatusTypeDef ADC_Read(uint8_t *data, uint16_t len, uint32_t timeout) {
    uint32_t adc_val;
    if (len < 4) return DRV_PARAM_ERR; // ADC值为32位,至少4字节
    HAL_ADC_Start(s_adc_cfg.hadc);
    if (HAL_ADC_PollForConversion(s_adc_cfg.hadc, timeout) == HAL_OK) {
        adc_val = HAL_ADC_GetValue(s_adc_cfg.hadc);
        memcpy(data, &adc_val, sizeof(uint32_t)); // 数据传出
    }
    HAL_ADC_Stop(s_adc_cfg.hadc);
    return DRV_OK;
}

// ADC无需写入数据,预留接口
static DRV_StatusTypeDef ADC_Write(const uint8_t *data, uint16_t len, uint32_t timeout) {
    (void)data; (void)len; (void)timeout;
    return DRV_OK;
}

// ADC控制(预留扩展)
static DRV_StatusTypeDef ADC_Ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化ADC
static DRV_StatusTypeDef ADC_DeInit(void) {
    return DRV_OK;
}

// ADC驱动实例(绑定统一接口)
static const DRV_DriverTypeDef s_adc_drv = {
    .Init   = ADC_Init,
    .Read   = ADC_Read,
    .Write  = ADC_Write,
    .Ctrl   = ADC_Ctrl,
    .DeInit = ADC_DeInit
};

// 对外提供驱动实例
const DRV_DriverTypeDef *DRV_ADC_GetDriver(void) {
    return &s_adc_drv;
}

4.5 PWM 驱动

4.5.1 drv_pwm.h

c 复制代码
#ifndef __DRV_PWM_H
#define __DRV_PWM_H

#include "driver_common.h"

// PWM配置结构体
typedef struct {
    TIM_HandleTypeDef *htim;  // 定时器句柄(HAL库)
    uint32_t channel;         // PWM通道(TIM_CHANNEL_1~4)
} DRV_PWM_ConfigTypeDef;

// PWM控制命令
typedef enum {
    PWM_CMD_START = 0U,   // 启动PWM
    PWM_CMD_STOP,         // 停止PWM
    PWM_CMD_SET_DUTY      // 设置占空比
} DRV_PWM_CmdTypeDef;

// 获取PWM驱动实例
const DRV_DriverTypeDef *DRV_PWM_GetDriver(void);

#endif

4.5.2 drv_pwm.c

c 复制代码
#include "drv_pwm.h"

static DRV_PWM_ConfigTypeDef s_pwm_cfg; // 内部配置(static隐藏)

// 初始化PWM(启动PWM输出)
static DRV_StatusTypeDef PWM_Init(void *cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    s_pwm_cfg = *(DRV_PWM_ConfigTypeDef *)cfg;
    HAL_TIM_PWM_Start(s_pwm_cfg.htim, s_pwm_cfg.channel); // 启动PWM
    return DRV_OK;
}

// PWM无需读取数据,预留接口
static DRV_StatusTypeDef PWM_Read(uint8_t *data, uint16_t len, uint32_t timeout) {
    (void)data; (void)len; (void)timeout;
    return DRV_OK;
}

// PWM无需写入数据,预留接口
static DRV_StatusTypeDef PWM_Write(const uint8_t *data, uint16_t len, uint32_t timeout) {
    (void)data; (void)len; (void)timeout;
    return DRV_OK;
}

// PWM控制(核心:设置占空比、启动/停止)
static DRV_StatusTypeDef PWM_Ctrl(uint8_t cmd, void *param) {
    uint32_t duty;
    switch (cmd) {
        case PWM_CMD_SET_DUTY:
            duty = (uint32_t)param;
            __HAL_TIM_SET_COMPARE(s_pwm_cfg.htim, s_pwm_cfg.channel, duty); // 设置占空比
            break;
        case PWM_CMD_STOP:
            HAL_TIM_PWM_Stop(s_pwm_cfg.htim, s_pwm_cfg.channel);
            break;
        case PWM_CMD_START:
            HAL_TIM_PWM_Start(s_pwm_cfg.htim, s_pwm_cfg.channel);
            break;
        default:
            return DRV_PARAM_ERR;
    }
    return DRV_OK;
}

// 反初始化PWM(停止PWM输出)
static DRV_StatusTypeDef PWM_DeInit(void) {
    HAL_TIM_PWM_Stop(s_pwm_cfg.htim, s_pwm_cfg.channel);
    return DRV_OK;
}

// PWM驱动实例(绑定统一接口)
static const DRV_DriverTypeDef s_pwm_drv = {
    .Init   = PWM_Init,
    .Read   = PWM_Read,
    .Write  = PWM_Write,
    .Ctrl   = PWM_Ctrl,
    .DeInit = PWM_DeInit
};

// 对外提供驱动实例
const DRV_DriverTypeDef *DRV_PWM_GetDriver(void) {
    return &s_pwm_drv;
}

五、常用模块驱动(基于统一框架)

5.1 AHT10 温湿度传感器驱动(I2C)

5.1.1 drv_aht10.h

c 复制代码
#ifndef __DRV_AHT10_H
#define __DRV_AHT10_H

#include "driver_common.h"
#include "drv_bus.h"

// AHT10配置结构体(绑定I2C总线)
typedef struct {
    I2C_Bus_t* bus;  // I2C总线
    uint8_t addr;    // AHT10设备地址
} AHT10_Config_t;

// 获取AHT10驱动实例
const DRV_DriverTypeDef* drv_aht10_get(void);

#endif

5.1.2 drv_aht10.c

c 复制代码
#include "drv_aht10.h"

static AHT10_Config_t g_cfg; // 内部配置(static隐藏)

// 初始化AHT10
static DRV_StatusTypeDef aht10_init(void* cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    g_cfg = *(AHT10_Config_t*)cfg;
    // 此处可添加AHT10硬件初始化、校准逻辑(实际项目补充)
    return DRV_OK;
}

// 读取AHT10温湿度数据(数据格式:float[0]=温度,float[1]=湿度)
static DRV_StatusTypeDef aht10_read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == NULL || len < 8) return DRV_PARAM_ERR; // 2个float,共8字节
    float* temp_humi = (float*)data;
    // 模拟读取(实际项目替换为I2C总线读取+数据解析)
    temp_humi[0] = 25.3f; // 温度(℃)
    temp_humi[1] = 51.2f; // 湿度(%RH)
    return DRV_OK;
}

// AHT10无需写入数据,预留接口
static DRV_StatusTypeDef aht10_write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    (void)data; (void)len; (void)timeout;
    return DRV_OK;
}

// AHT10控制(预留扩展:休眠、唤醒等)
static DRV_StatusTypeDef aht10_ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化AHT10
static DRV_StatusTypeDef aht10_deinit(void) {
    return DRV_OK;
}

// AHT10驱动实例(绑定统一接口)
static const DRV_DriverTypeDef g_aht10_drv = {
    .Init = aht10_init,
    .Read = aht10_read,
    .Write = aht10_write,
    .Ctrl = aht10_ctrl,
    .DeInit = aht10_deinit
};

// 对外提供驱动实例
const DRV_DriverTypeDef* drv_aht10_get(void) {
    return &g_aht10_drv;
}

5.2 OLED 驱动(I2C)

5.2.1 drv_oled.h

c 复制代码
#ifndef __DRV_OLED_H
#define __DRV_OLED_H

#include "driver_common.h"
#include "drv_bus.h"

// OLED配置结构体(绑定I2C总线)
typedef struct {
    I2C_Bus_t* bus;  // I2C总线
    uint8_t addr;    // OLED设备地址
} OLED_Config_t;

// 获取OLED驱动实例
const DRV_DriverTypeDef* drv_oled_get(void);

#endif

5.2.2 drv_oled.c

c 复制代码
#include "drv_oled.h"

static OLED_Config_t g_cfg; // 内部配置(static隐藏)

// 初始化OLED
static DRV_StatusTypeDef oled_init(void* cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    g_cfg = *(OLED_Config_t*)cfg;
    // 此处可添加OLED初始化逻辑(如复位、显示模式配置,实际项目补充)
    return DRV_OK;
}

// OLED写入数据(显示控制、字符/图形数据)
static DRV_StatusTypeDef oled_write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == NULL || len == 0) return DRV_PARAM_ERR;
    // 模拟写入(实际项目替换为I2C总线写入OLED控制指令/数据)
    return DRV_OK;
}

// OLED无需读取数据,预留接口
static DRV_StatusTypeDef oled_read(uint8_t* data, uint16_t len, uint32_t timeout) {
    (void)data; (void)len; (void)timeout;
    return DRV_OK;
}

// OLED控制(预留扩展:清屏、显示开关等)
static DRV_StatusTypeDef oled_ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化OLED
static DRV_StatusTypeDef oled_deinit(void) {
    return DRV_OK;
}

// OLED驱动实例(绑定统一接口)
static const DRV_DriverTypeDef g_oled_drv = {
    .Init = oled_init,
    .Read = oled_read,
    .Write = oled_write,
    .Ctrl = oled_ctrl,
    .DeInit = oled_deinit
};

// 对外提供驱动实例
const DRV_DriverTypeDef* drv_oled_get(void) {
    return &g_oled_drv;
}

5.3 W25QXX SPI Flash 驱动

5.3.1 drv_flash.h

c 复制代码
#ifndef __DRV_FLASH_H
#define __DRV_FLASH_H

#include "driver_common.h"
#include "drv_bus.h"

// Flash配置结构体(绑定SPI总线)
typedef struct {
    SPI_Bus_t* bus;  // SPI总线
} Flash_Config_t;

// 获取Flash驱动实例
const DRV_DriverTypeDef* drv_flash_get(void);

#endif

5.3.2 drv_flash.c

c 复制代码
#include "drv_flash.h"

static Flash_Config_t g_cfg; // 内部配置(static隐藏)

// 初始化Flash
static DRV_StatusTypeDef flash_init(void* cfg) {
    if (cfg == NULL) return DRV_PARAM_ERR;
    g_cfg = *(Flash_Config_t*)cfg;
    // 此处可添加Flash初始化逻辑(如解锁、状态检查,实际项目补充)
    return DRV_OK;
}

// 读取Flash数据
static DRV_StatusTypeDef flash_read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == NULL || len == 0) return DRV_PARAM_ERR;
    // 模拟读取(实际项目替换为SPI总线读取Flash数据)
    return DRV_OK;
}

// 写入Flash数据
static DRV_StatusTypeDef flash_write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == NULL || len == 0) return DRV_PARAM_ERR;
    // 模拟写入(实际项目替换为SPI总线写入Flash数据,需先擦除)
    return DRV_OK;
}

// Flash控制(预留扩展:擦除、解锁、休眠等)
static DRV_StatusTypeDef flash_ctrl(uint8_t cmd, void *param) {
    (void)cmd; (void)param;
    return DRV_OK;
}

// 反初始化Flash
static DRV_StatusTypeDef flash_deinit(void) {
    return DRV_OK;
}

// Flash驱动实例(绑定统一接口)
static const DRV_DriverTypeDef g_flash_drv = {
    .Init = flash_init,
    .Read = flash_read,
    .Write = flash_write,
    .Ctrl = flash_ctrl,
    .DeInit = flash_deinit
};

// 对外提供驱动实例
const DRV_DriverTypeDef* drv_flash_get(void) {
    return &g_flash_drv;
}

六、完整调用示例(main.c)

c 复制代码
#include "main.h"
#include "driver_common.h"
#include "drv_dev.h"
#include "drv_uart.h"
#include "drv_i2c.h"
#include "drv_spi.h"
#include "drv_adc.h"
#include "drv_pwm.h"
#include "drv_aht10.h"
#include "drv_oled.h"
#include "drv_flash.h"

// HAL库句柄(根据实际硬件配置)
UART_HandleTypeDef huart1;
I2C_HandleTypeDef hi2c1;
SPI_HandleTypeDef hspi1;
ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;
I2C_Bus_t i2c_bus;
SPI_Bus_t spi_bus;

int main(void) {
    // 1. HAL库初始化
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    MX_ADC1_Init();
    MX_TIM2_Init();

    // 2. 配置各设备参数
    // 2.1 UART配置
    DRV_UART_ConfigTypeDef uart_cfg = {.huart = &huart1};
    // 2.2 I2C配置
    DRV_I2C_ConfigTypeDef i2c_cfg = {.hi2c = &hi2c1};
    // 2.3 SPI配置
    DRV_SPI_ConfigTypeDef spi_cfg = {.hspi = &hspi1};
    // 2.4 ADC配置
    DRV_ADC_ConfigTypeDef adc_cfg = {.hadc = &hadc1};
    // 2.5 PWM配置(TIM2 CH1)
    DRV_PWM_ConfigTypeDef pwm_cfg = {.htim = &htim2, .channel = TIM_CHANNEL_1};
    // 2.6 AHT10配置(绑定I2C总线)
    AHT10_Config_t aht10_cfg = {.bus = &i2c_bus, .addr = 0x70 << 1};
    // 2.7 OLED配置(绑定I2C总线)
    OLED_Config_t oled_cfg = {.bus = &i2c_bus, .addr = 0x3C << 1};
    // 2.8 Flash配置(绑定SPI总线)
    Flash_Config_t flash_cfg = {.bus = &spi_bus};

    // 3. 注册所有设备(仿Linux设备树注册)
    Device_t uart1_dev = {"uart1", DEV_TYPE_UART, DRV_UART_GetDriver(), &uart_cfg};
    Device_t i2c1_dev = {"i2c1", DEV_TYPE_I2C, DRV_I2C_GetDriver(), &i2c_cfg};
    Device_t spi1_dev = {"spi1", DEV_TYPE_SPI, DRV_SPI_GetDriver(), &spi_cfg};
    Device_t adc1_dev = {"adc1", DEV_TYPE_ADC, DRV_ADC_GetDriver(), &adc_cfg};
    Device_t pwm1_dev = {"pwm1", DEV_TYPE_PWM, DRV_PWM_GetDriver(), &pwm_cfg};
    Device_t aht10_dev = {"aht10", DEV_TYPE_AHT10, drv_aht10_get(), &aht10_cfg};
    Device_t oled_dev = {"oled", DEV_TYPE_OLED, drv_oled_get(), &oled_cfg};
    Device_t flash_dev = {"flash", DEV_TYPE_FLASH, drv_flash_get(), &flash_cfg};

    dev_register(&uart1_dev);
    dev_register(&i2c1_dev);
    dev_register(&spi1_dev);
    dev_register(&adc1_dev);
    dev_register(&pwm1_dev);
    dev_register(&aht10_dev);
    dev_register(&oled_dev);
    dev_register(&flash_dev);

    // 4. 统一调用各设备(两种方式:直接调用驱动 / 通过设备注册表调用)
    const Device_t* dev;
    uint8_t buf[32];
    uint32_t adc_val;
    float temp_humi[2];

    // 4.1 UART调用(发送初始化提示)
    dev = dev_get("uart1");
    dev->drv->Init(dev->config);
    dev->drv->Write((uint8_t *)"STM32 Unified Driver Framework Ready\r\n", 40, 100);

    // 4.2 AHT10调用(读取温湿度)
    dev = dev_get("aht10");
    dev->drv->Init(dev->config);
    dev->drv->Read((uint8_t *)temp_humi, 8, 100);

    // 4.3 ADC调用(读取ADC值)
    dev = dev_get("adc1");
    dev->drv->Init(dev->config);
    dev->drv->Read((uint8_t *)&adc_val, 4, 100);

    // 4.4 PWM调用(设置占空比)
    dev = dev_get("pwm1");
    dev->drv->Init(dev->config);
    dev->drv->Ctrl(PWM_CMD_SET_DUTY, (void *)500); // 占空比根据定时器配置调整

    // 4.5 SPI Flash调用(写入/读取数据)
    dev = dev_get("flash");
    dev->drv->Init(dev->config);
    uint8_t flash_tx[4] = {0x12, 0x34, 0x56, 0x78};
    dev->drv->Write(flash_tx, 4, 100);
    dev->drv->Read(buf, 4, 100);

    // 5. 主循环(持续调用设备)
    while (1) {
        // 持续读取温湿度并通过UART发送
        dev = dev_get("aht10");
        dev->drv->Read((uint8_t *)temp_humi, 8, 100);
        
        dev = dev_get("uart1");
        sprintf((char*)buf, "Temp: %.1f℃, Humi: %.1f%%RH\r\n", temp_humi[0], temp_humi[1]);
        dev->drv->Write(buf, strlen((char*)buf), 100);

        // 读取ADC值,调整PWM占空比
        dev = dev_get("adc1");
        dev->drv->Read((uint8_t *)&adc_val, 4, 100);
        
        dev = dev_get("pwm1");
        dev->drv->Ctrl(PWM_CMD_SET_DUTY, (void *)(adc_val / 4));

        HAL_Delay(500);
    }
}

// 以下为HAL库自动生成的初始化函数(根据实际硬件补充)
void SystemClock_Config(void) { /* 系统时钟配置 */ }
void MX_GPIO_Init(void) { /* GPIO初始化 */ }
void MX_USART1_UART_Init(void) { /* UART1初始化 */ }
void MX_I2C1_Init(void) { /* I2C1初始化 */ }
void MX_SPI1_Init(void) { /* SPI1初始化 */ }
void MX_ADC1_Init(void) { /* ADC1初始化 */ }
void MX_TIM2_Init(void) { /* TIM2初始化(PWM) */ }

七、工程目录结构(直接照建,可直接导入STM32CubeIDE)

plaintext 复制代码
Project/
├── Inc/
│   ├── driver_common.h
│   ├── drv_dev.h
│   ├── drv_bus.h
│   ├── drv_uart.h
│   ├── drv_i2c.h
│   ├── drv_spi.h
│   ├── drv_adc.h
│   ├── drv_pwm.h
│   ├── drv_aht10.h
│   ├── drv_oled.h
│   ├── drv_flash.h
│   └── main.h
└── Src/
    ├── driver_common.c
    ├── drv_dev.c
    ├── drv_bus.c
    ├── drv_uart.c
    ├── drv_i2c.c
    ├── drv_spi.c
    ├── drv_adc.c
    ├── drv_pwm.c
    ├── drv_aht10.c
    ├── drv_oled.c
    ├── drv_flash.c
    └── main.c

八、使用说明

  1. 适配性:默认基于STM32F10x HAL库,F4/F7/L4系列只需修改头文件 stm32f1xx_hal.h 为对应系列头文件。

  2. 编译使用:按上述目录结构创建文件,复制代码,补充HAL库自动生成的初始化函数(系统时钟、GPIO、外设初始化),即可直接编译。

  3. DMA/中断:UART驱动已预留DMA/中断接口,直接替换Read/Write函数内的HAL接口即可切换模式。

  4. 可扩展性:新增外设/模块时,只需遵循统一接口和结构体规范,注册到设备表即可,无需修改原有逻辑。

相关推荐
ken22322 小时前
中文文件名:find 与 git ls-files / ls-tree 的区别
linux·搜索引擎
buhuizhiyuci2 小时前
笑谈vim的快捷方式和简易配置
linux·编辑器·vim
minji...2 小时前
Linux 网络套接字编程(三)UDP服务器与客户端实现:Windows与Linux通信,新增字典翻译功能的 UDP 通信
linux·服务器·开发语言·网络·windows·算法·udp
嵌入式×边缘AI:打怪升级日志2 小时前
DHT11 驱动开发实录:从零搭建 Linux 字符设备驱动框架(保姆级教学)
linux·运维·驱动开发
艾莉丝努力练剑2 小时前
【Linux网络】计算机网络入门:网络通信——跨主机的进程间通信(IPC)与Socket编程入门
linux·运维·服务器·网络·c++·学习·计算机网络
炘爚2 小时前
Linux :进程间通信(IPC)与信号
linux·进程间通信
Lfei51202 小时前
Centos 9 stream部署zabbix7.0.25(最新)
linux·运维·centos
枫叶落雨2222 小时前
服务器下载两个jdk
linux·运维·服务器
Elivs.Xiang2 小时前
基于docker安装MySQL、RabbitMQ、ElasticSearch、minio
linux·mysql·elasticsearch·docker·rabbitmq