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

采用「抽象基类+派生类」C++体系,完美替代C语言的统一接口,实现代码复用

核心设计思路

  • 抽象基类 Peripheral:定义所有外设的统一接口(Init、Read、Write、Ctrl、DeInit),纯虚函数强制派生类实现

  • 派生类:UART、I2C、SPI、ADC、PWM、AHT10、OLED、Flash,继承基类,实现自身专属逻辑

  • 兼容HAL库:直接调用HAL接口,无需修改底层,和原有C语言框架功能完全一致

  • 可扩展性:新增外设只需新增派生类,重写纯虚函数,不修改原有基类和其他派生类

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

1.1 driver_common.h(核心标准)

cpp 复制代码
#ifndef __DRIVER_COMMON_H
#define __DRIVER_COMMON_H

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

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

// 统一驱动接口(仿Linux file_operations,C++纯虚基类,强制派生类实现)
class DRV_DriverBase {
public:
    virtual ~DRV_DriverBase() = default; // 虚析构,避免派生类析构泄漏
    virtual DRV_StatusTypeDef Init(void* cfg) = 0;
    virtual DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) = 0;
    virtual DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) = 0;
    virtual DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) = 0;
    virtual DRV_StatusTypeDef DeInit() = 0;
};

#endif

1.2 driver_common.cpp(预留扩展)

cpp 复制代码
#include "driver_common.h"
// 预留全局工具函数、公共逻辑扩展(C++语法,支持类、模板等)

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

2.1 drv_dev.h

cpp 复制代码
#ifndef __DRV_DEV_H
#define __DRV_DEV_H

#include "driver_common.h"
#include <cstring> // C++字符串处理

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

// 设备结构体(统一管理)
struct Device {
    const char* name;          // 设备名称(唯一)
    DevTypeEnum type;          // 设备类型
    DRV_DriverBase* drv;       // 设备对应的驱动(C++基类指针,多态调用)
    void* config;              // 设备配置参数
};

// 设备注册表类(C++封装,隐藏内部实现)
class DeviceManager {
private:
    static const uint8_t MAX_DEV = 32;  // 最大支持设备数量
    Device* dev_list[MAX_DEV] = {nullptr}; // 设备列表(基类指针数组,支持多态)
    uint8_t dev_cnt = 0;                  // 已注册设备计数
public:
    // 单例模式,确保全局唯一设备管理器
    static DeviceManager& GetInstance() {
        static DeviceManager instance;
        return instance;
    }
    // 禁止拷贝和赋值
    DeviceManager(const DeviceManager&) = delete;
    DeviceManager& operator=(const DeviceManager&) = delete;
    
    // 注册设备
    void RegisterDevice(Device* dev);
    // 根据设备名称获取设备(返回指针,支持多态调用)
    Device* GetDevice(const char* name);
    
private:
    DeviceManager() = default; // 私有构造,仅通过GetInstance获取实例
};

#endif

2.2 drv_dev.cpp

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

// 注册设备(将设备添加到设备列表)
void DeviceManager::RegisterDevice(Device* dev) {
    if (dev_cnt >= MAX_DEV || dev == nullptr || dev->name == nullptr || dev->drv == nullptr) {
        return;
    }
    dev_list[dev_cnt++] = dev;
}

// 根据名称获取设备(遍历设备列表匹配名称)
Device* DeviceManager::GetDevice(const char* name) {
    if (name == nullptr) {
        return nullptr;
    }
    for (uint8_t i = 0; i < dev_cnt; i++) {
        if (std::strcmp(dev_list[i]->name, name) == 0) {
            return dev_list[i];
        }
    }
    return nullptr;
}

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

3.1 drv_bus.h

cpp 复制代码
#ifndef __DRV_BUS_H
#define __DRV_BUS_H

#include "driver_common.h"

// 总线操作接口(C++纯虚基类,统一I2C/SPI操作)
class BusBase {
public:
    virtual ~BusBase() = default;
    virtual DRV_StatusTypeDef Send(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout) = 0;
    virtual DRV_StatusTypeDef Recv(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout) = 0;
};

// I2C总线类(继承总线基类)
class I2CBus : public BusBase {
private:
    I2C_HandleTypeDef* hi2c; // 私有成员,隐藏底层实现
public:
    DRV_StatusTypeDef Send(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Recv(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout) override;
    // 设置I2C句柄(对外提供接口,隐藏内部成员)
    void SetHandle(I2C_HandleTypeDef* h) { hi2c = h; }
};

// SPI总线类(继承总线基类)
class SPIBus : public BusBase {
private:
    SPI_HandleTypeDef* hspi; // 私有成员,隐藏底层实现
public:
    DRV_StatusTypeDef Send(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Recv(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout) override;
    // 设置SPI句柄(对外提供接口,隐藏内部成员)
    void SetHandle(SPI_HandleTypeDef* h) { hspi = h; }
};

#endif

3.2 drv_bus.cpp

cpp 复制代码
#include "drv_bus.h"

// I2C总线发送实现
DRV_StatusTypeDef I2CBus::Send(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (hi2c == nullptr || data == nullptr || len == 0) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_I2C_Master_Transmit(hi2c, addr, (uint8_t*)data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// I2C总线接收实现
DRV_StatusTypeDef I2CBus::Recv(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout) {
    if (hi2c == nullptr || data == nullptr || len == 0) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_I2C_Master_Receive(hi2c, addr, data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// SPI总线发送实现(SPI无地址,addr占位)
DRV_StatusTypeDef SPIBus::Send(uint8_t addr, const uint8_t* data, uint16_t len, uint32_t timeout) {
    (void)addr; // 占位,避免未使用警告
    if (hspi == nullptr || data == nullptr || len == 0) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_SPI_Transmit(hspi, (uint8_t*)data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// SPI总线接收实现(SPI无地址,addr占位)
DRV_StatusTypeDef SPIBus::Recv(uint8_t addr, uint8_t* data, uint16_t len, uint32_t timeout) {
    (void)addr; // 占位,避免未使用警告
    if (hspi == nullptr || data == nullptr || len == 0) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_SPI_Receive(hspi, data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

4.1.1 drv_uart.h

cpp 复制代码
#ifndef __DRV_UART_H
#define __DRV_UART_H

#include "driver_common.h"

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

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

// UART驱动类(继承统一驱动基类)
class DRV_UART : public DRV_DriverBase {
private:
    DRV_UART_ConfigTypeDef uart_cfg; // 私有配置,隐藏内部细节
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_UART& GetInstance() {
        static DRV_UART instance;
        return instance;
    }
private:
    DRV_UART() = default; // 私有构造,禁止外部实例化
    DRV_UART(const DRV_UART&) = delete; // 禁止拷贝
    DRV_UART& operator=(const DRV_UART&) = delete; // 禁止赋值
};

#endif

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

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

// 初始化UART
DRV_StatusTypeDef DRV_UART::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    uart_cfg = *(DRV_UART_ConfigTypeDef*)cfg;
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

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

// 反初始化UART
DRV_StatusTypeDef DRV_UART::DeInit() {
    // 可添加UART反初始化逻辑(如关闭中断、DMA等)
    return DRV_StatusTypeDef::DRV_OK;
}

4.2 I2C 驱动

4.2.1 drv_i2c.h

cpp 复制代码
#ifndef __DRV_I2C_H
#define __DRV_I2C_H

#include "driver_common.h"

// I2C配置结构体
struct DRV_I2C_ConfigTypeDef {
    I2C_HandleTypeDef* hi2c; // I2C句柄(HAL库)
    uint8_t addr;            // I2C设备地址(7位,已左移1位)
};

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

// I2C驱动类(继承统一驱动基类)
class DRV_I2C : public DRV_DriverBase {
private:
    DRV_I2C_ConfigTypeDef i2c_cfg; // 私有配置,隐藏内部细节
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_I2C& GetInstance() {
        static DRV_I2C instance;
        return instance;
    }
private:
    DRV_I2C() = default; // 私有构造,禁止外部实例化
    DRV_I2C(const DRV_I2C&) = delete;
    DRV_I2C& operator=(const DRV_I2C&) = delete;
};

#endif

4.2.2 drv_i2c.cpp

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

// 初始化I2C
DRV_StatusTypeDef DRV_I2C::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    i2c_cfg = *(DRV_I2C_ConfigTypeDef*)cfg;
    return DRV_StatusTypeDef::DRV_OK;
}

// 读取I2C数据(主模式)
DRV_StatusTypeDef DRV_I2C::Read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || i2c_cfg.hi2c == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_I2C_Master_Receive(i2c_cfg.hi2c, i2c_cfg.addr, data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// 写入I2C数据(主模式)
DRV_StatusTypeDef DRV_I2C::Write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || i2c_cfg.hi2c == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_I2C_Master_Transmit(i2c_cfg.hi2c, i2c_cfg.addr, (uint8_t*)data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

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

// 反初始化I2C
DRV_StatusTypeDef DRV_I2C::DeInit() {
    // 可添加I2C反初始化逻辑
    return DRV_StatusTypeDef::DRV_OK;
}

4.3 SPI 驱动

4.3.1 drv_spi.h

cpp 复制代码
#ifndef __DRV_SPI_H
#define __DRV_SPI_H

#include "driver_common.h"

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

// SPI驱动类(继承统一驱动基类)
class DRV_SPI : public DRV_DriverBase {
private:
    DRV_SPI_ConfigTypeDef spi_cfg; // 私有配置,隐藏内部细节
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_SPI& GetInstance() {
        static DRV_SPI instance;
        return instance;
    }
private:
    DRV_SPI() = default; // 私有构造,禁止外部实例化
    DRV_SPI(const DRV_SPI&) = delete;
    DRV_SPI& operator=(const DRV_SPI&) = delete;
};

#endif

4.3.2 drv_spi.cpp

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

// 初始化SPI
DRV_StatusTypeDef DRV_SPI::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    spi_cfg = *(DRV_SPI_ConfigTypeDef*)cfg;
    return DRV_StatusTypeDef::DRV_OK;
}

// 读取SPI数据
DRV_StatusTypeDef DRV_SPI::Read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || spi_cfg.hspi == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_SPI_Receive(spi_cfg.hspi, data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// 写入SPI数据
DRV_StatusTypeDef DRV_SPI::Write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || spi_cfg.hspi == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    if (HAL_SPI_Transmit(spi_cfg.hspi, (uint8_t*)data, len, timeout) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

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

// 反初始化SPI
DRV_StatusTypeDef DRV_SPI::DeInit() {
    // 可添加SPI反初始化逻辑
    return DRV_StatusTypeDef::DRV_OK;
}

4.4 ADC 驱动

4.4.1 drv_adc.h

cpp 复制代码
#ifndef __DRV_ADC_H
#define __DRV_ADC_H

#include "driver_common.h"

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

// ADC驱动类(继承统一驱动基类)
class DRV_ADC : public DRV_DriverBase {
private:
    DRV_ADC_ConfigTypeDef adc_cfg; // 私有配置,隐藏内部细节
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_ADC& GetInstance() {
        static DRV_ADC instance;
        return instance;
    }
private:
    DRV_ADC() = default; // 私有构造,禁止外部实例化
    DRV_ADC(const DRV_ADC&) = delete;
    DRV_ADC& operator=(const DRV_ADC&) = delete;
};

#endif

4.4.2 drv_adc.cpp

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

// 初始化ADC
DRV_StatusTypeDef DRV_ADC::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    adc_cfg = *(DRV_ADC_ConfigTypeDef*)cfg;
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

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

// 反初始化ADC
DRV_StatusTypeDef DRV_ADC::DeInit() {
    // 可添加ADC反初始化逻辑
    return DRV_StatusTypeDef::DRV_OK;
}

4.5 PWM 驱动

4.5.1 drv_pwm.h

cpp 复制代码
#ifndef __DRV_PWM_H
#define __DRV_PWM_H

#include "driver_common.h"

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

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

// PWM驱动类(继承统一驱动基类)
class DRV_PWM : public DRV_DriverBase {
private:
    DRV_PWM_ConfigTypeDef pwm_cfg; // 私有配置,隐藏内部细节
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_PWM& GetInstance() {
        static DRV_PWM instance;
        return instance;
    }
private:
    DRV_PWM() = default; // 私有构造,禁止外部实例化
    DRV_PWM(const DRV_PWM&) = delete;
    DRV_PWM& operator=(const DRV_PWM&) = delete;
};

#endif

4.5.2 drv_pwm.cpp

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

// 初始化PWM(启动PWM输出)
DRV_StatusTypeDef DRV_PWM::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    pwm_cfg = *(DRV_PWM_ConfigTypeDef*)cfg;
    if (HAL_TIM_PWM_Start(pwm_cfg.htim, pwm_cfg.channel) != HAL_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

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

// 反初始化PWM(停止PWM输出)
DRV_StatusTypeDef DRV_PWM::DeInit() {
    HAL_TIM_PWM_Stop(pwm_cfg.htim, pwm_cfg.channel);
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

5.1.1 drv_aht10.h

cpp 复制代码
#ifndef __DRV_AHT10_H
#define __DRV_AHT10_H

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

// AHT10配置结构体(绑定I2C总线)
struct AHT10_Config_t {
    I2CBus* bus;  // I2C总线指针(C++基类指针,支持多态)
    uint8_t addr; // AHT10设备地址(7位,已左移1位)
};

// AHT10驱动类(继承统一驱动基类)
class DRV_AHT10 : public DRV_DriverBase {
private:
    AHT10_Config_t cfg; // 私有配置,隐藏内部细节
    // 私有成员函数,内部使用,不对外暴露
    DRV_StatusTypeDef Calibrate(); // AHT10校准函数
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_AHT10& GetInstance() {
        static DRV_AHT10 instance;
        return instance;
    }
private:
    DRV_AHT10() = default; // 私有构造,禁止外部实例化
    DRV_AHT10(const DRV_AHT10&) = delete;
    DRV_AHT10& operator=(const DRV_AHT10&) = delete;
};

#endif

5.1.2 drv_aht10.cpp

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

// AHT10命令定义
#define AHT10_CALIBRATE_CMD 0xE1
#define AHT10_MEASURE_CMD   0xAC

// 私有函数:AHT10校准
DRV_StatusTypeDef DRV_AHT10::Calibrate() {
    uint8_t cmd = AHT10_CALIBRATE_CMD;
    return cfg.bus->Send(cfg.addr, &cmd, 1, 100);
}

// 初始化AHT10
DRV_StatusTypeDef DRV_AHT10::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    this->cfg = *(AHT10_Config_t*)cfg;
    // 校准AHT10(必须执行)
    if (Calibrate() != DRV_StatusTypeDef::DRV_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    HAL_Delay(10); // 等待校准完成
    return DRV_StatusTypeDef::DRV_OK;
}

// 读取AHT10温湿度数据(数据格式:float[0]=温度,float[1]=湿度)
DRV_StatusTypeDef DRV_AHT10::Read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len < 8 || cfg.bus == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR; // 2个float,共8字节
    }
    float* temp_humi = (float*)data;
    uint8_t buf[6] = {0};
    uint8_t cmd = AHT10_MEASURE_CMD;
    
    // 发送测量命令
    if (cfg.bus->Send(cfg.addr, &cmd, 1, timeout) != DRV_StatusTypeDef::DRV_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    HAL_Delay(80); // 等待测量完成
    
    // 读取测量数据
    if (cfg.bus->Recv(cfg.addr, buf, 6, timeout) != DRV_StatusTypeDef::DRV_OK) {
        return DRV_StatusTypeDef::DRV_ERROR;
    }
    
    // 解析温湿度数据
    uint32_t humi_raw = ((buf[1] << 16) | (buf[2] << 8) | buf[3]) & 0x00FFFFFF;
    uint32_t temp_raw = ((buf[3] & 0x0F) << 16) | (buf[4] << 8) | buf[5];
    
    // 转换为实际温湿度(AHT10标准公式)
    temp_humi[1] = (humi_raw / (float)(1 << 20)) * 100.0f; // 湿度(%RH)
    temp_humi[0] = (temp_raw / (float)(1 << 20)) * 200.0f - 50.0f; // 温度(℃)
    
    return DRV_StatusTypeDef::DRV_OK;
}

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

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

// 反初始化AHT10
DRV_StatusTypeDef DRV_AHT10::DeInit() {
    return DRV_StatusTypeDef::DRV_OK;
}

5.2 OLED 驱动(I2C)

5.2.1 drv_oled.h

cpp 复制代码
#ifndef __DRV_OLED_H
#define __DRV_OLED_H

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

// OLED配置结构体(绑定I2C总线)
struct OLED_Config_t {
    I2CBus* bus;  // I2C总线指针(C++基类指针,支持多态)
    uint8_t addr; // OLED设备地址(7位,已左移1位)
};

// OLED驱动类(继承统一驱动基类)
class DRV_OLED : public DRV_DriverBase {
private:
    OLED_Config_t cfg; // 私有配置,隐藏内部细节
    // 私有成员函数,内部使用,不对外暴露
    DRV_StatusTypeDef WriteCmd(uint8_t cmd); // 写命令
    DRV_StatusTypeDef WriteData(uint8_t data); // 写数据
public:
    DRV_StatusTypeDef Init(void* cfg) override;
    DRV_StatusTypeDef Read(uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Write(const uint8_t* data, uint16_t len, uint32_t timeout) override;
    DRV_StatusTypeDef Ctrl(uint8_t cmd, void* param) override;
    DRV_StatusTypeDef DeInit() override;
    // 单例模式,获取驱动实例
    static DRV_OLED& GetInstance() {
        static DRV_OLED instance;
        return instance;
    }
private:
    DRV_OLED() = default; // 私有构造,禁止外部实例化
    DRV_OLED(const DRV_OLED&) = delete;
    DRV_OLED& operator=(const DRV_OLED&) = delete;
};

#endif

5.2.2 drv_oled.cpp

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

// 私有函数:写OLED命令
DRV_StatusTypeDef DRV_OLED::WriteCmd(uint8_t cmd) {
    uint8_t buf[2] = {0x00, cmd}; // 0x00表示命令,0x40表示数据
    return cfg.bus->Send(cfg.addr, buf, 2, 100);
}

// 私有函数:写OLED数据
DRV_StatusTypeDef DRV_OLED::WriteData(uint8_t data) {
    uint8_t buf[2] = {0x40, data};
    return cfg.bus->Send(cfg.addr, buf, 2, 100);
}

// 初始化OLED
DRV_StatusTypeDef DRV_OLED::Init(void* cfg) {
    if (cfg == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    this->cfg = *(OLED_Config_t*)cfg;
    
    // OLED初始化序列(0.96寸I2C OLED通用)
    HAL_Delay(100); // 等待OLED上电稳定
    WriteCmd(0xAE); // 关闭显示
    WriteCmd(0x00); // 设置列地址低4位
    WriteCmd(0x10); // 设置列地址高4位
    WriteCmd(0x40); // 设置显示起始行
    WriteCmd(0xB0); // 设置页地址
    WriteCmd(0x81); // 设置对比度
    WriteCmd(0xFF); // 对比度最大值
    WriteCmd(0xA1); // 左右反置
    WriteCmd(0xA6); // 正常显示(0xA7为反显)
    WriteCmd(0xA8); // 设置驱动路数
    WriteCmd(0x3F); // 64路驱动
    WriteCmd(0xC8); // 上下反置
    WriteCmd(0xD3); // 设置显示偏移
    WriteCmd(0x00); // 偏移0
    WriteCmd(0xD5); // 设置震荡频率
    WriteCmd(0x80); // 正常频率
    WriteCmd(0xD9); // 设置预充电周期
    WriteCmd(0xF1); // 预充电周期
    WriteCmd(0xDA); // 设置COM引脚配置
    WriteCmd(0x12); // COM引脚配置
    WriteCmd(0xDB); // 设置VCOMH电压
    WriteCmd(0x40); // VCOMH电压
    WriteCmd(0xAF); // 开启显示
    
    return DRV_StatusTypeDef::DRV_OK;
}

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

// OLED写入数据(显示控制、字符/图形数据)
DRV_StatusTypeDef DRV_OLED::Write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || cfg.bus == nullptr) {
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    // 设置显示位置(示例:第0页,第0列)
    WriteCmd(0xB0); // 第0页
    WriteCmd(0x00); // 列地址低4位
    WriteCmd(0x10); // 列地址高4位
    
    // 写入显示数据
    for (uint16_t i = 0; i < len; i++) {
        if (WriteData(data[i]) != DRV_StatusTypeDef::DRV_OK) {
            return DRV_StatusTypeDef::DRV_ERROR;
        }
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// OLED控制(扩展:清屏、显示开关等)
DRV_StatusTypeDef DRV_OLED::Ctrl(uint8_t cmd, void* param) {
    (void)param;
    switch (cmd) {
        case 0: // 清屏命令
            for (uint8_t page = 0; page < 8; page++) {
                WriteCmd(0xB0 + page);
                WriteCmd(0x00);
                WriteCmd(0x10);
                for (uint8_t col = 0; col < 128; col++) {
                    WriteData(0x00);
                }
            }
            break;
        case 1: // 开启显示
            WriteCmd(0xAF);
            break;
        case 2: // 关闭显示
            WriteCmd(0xAE);
            break;
        default:
            return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// 反初始化OLED
DRV_StatusTypeDef DRV_OLED::DeInit() {
    WriteCmd(0xAE); // 关闭显示
    return DRV_StatusTypeDef::DRV_OK;
}

5.3 W25QXX SPI Flash 驱动

5.3.1 Flash实现(flash.cpp)

cpp 复制代码
#include "flash.h"

// W25QXX Flash命令定义
#define W25QXX_WRITE_ENABLE  0x06
#define W25QXX_WRITE_DISABLE 0x04
#define W25QXX_READ_DATA     0x03
#define W25QXX_PAGE_PROGRAM  0x02
#define W25QXX_SECTOR_ERASE  0x20
#define W25QXX_CHIP_ERASE    0xC7
#define W25QXX_READ_ID       0x90

// Flash私有函数:写命令
DRV_StatusTypeDef Flash::WriteCmd(uint8_t cmd) {
    return cfg.bus->Send(0x00, &cmd, 1, 100); // SPI无地址,addr填0
}

// 初始化实现(解锁Flash)
DRV_StatusTypeDef Flash::Init(void* cfg) {
    if (cfg == nullptr)
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    this->cfg = *(Flash_ConfigTypeDef*)cfg;
    
    // Flash写使能(解锁)
    if (WriteCmd(W25QXX_WRITE_ENABLE) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    return DRV_StatusTypeDef::DRV_OK;
}

// 读取Flash数据实现
DRV_StatusTypeDef Flash::Read(uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || cfg.bus == nullptr)
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    
    uint8_t cmd_buf[4] = {0};
    // 读取命令 + 地址(示例:从0x000000地址开始读取)
    cmd_buf[0] = W25QXX_READ_DATA;
    cmd_buf[1] = 0x00; // 地址高8位
    cmd_buf[2] = 0x00; // 地址中8位
    cmd_buf[3] = 0x00; // 地址低8位
    
    // 发送读取命令和地址
    if (cfg.bus->Send(0x00, cmd_buf, 4, timeout) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    // 读取数据
    if (cfg.bus->Recv(0x00, data, len, timeout) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    return DRV_StatusTypeDef::DRV_OK;
}

// 写入Flash数据实现(需先擦除扇区)
DRV_StatusTypeDef Flash::Write(const uint8_t* data, uint16_t len, uint32_t timeout) {
    if (data == nullptr || len == 0 || cfg.bus == nullptr)
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    
    // 1. 写使能
    if (WriteCmd(W25QXX_WRITE_ENABLE) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    // 2. 页编程命令 + 地址(示例:写入0x000000地址)
    uint8_t cmd_buf[4] = {W25QXX_PAGE_PROGRAM, 0x00, 0x00, 0x00};
    if (cfg.bus->Send(0x00, cmd_buf, 4, timeout) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    // 3. 写入数据(W25QXX单页最大256字节,需控制len)
    if (len > 256)
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    if (cfg.bus->Send(0x00, data, len, timeout) != DRV_StatusTypeDef::DRV_OK)
        return DRV_StatusTypeDef::DRV_ERROR;
    
    // 4. 等待写入完成(实际项目需添加等待逻辑)
    HAL_Delay(10);
    
    return DRV_StatusTypeDef::DRV_OK;
}

// 控制函数实现(扇区擦除、芯片擦除、读ID)
DRV_StatusTypeDef Flash::Ctrl(uint8_t cmd, void* param) {
    if (param == nullptr || cfg.bus == nullptr)
        return DRV_StatusTypeDef::DRV_PARAM_ERR;
    
    switch ((Flash_CmdTypeDef)cmd) {
        case Flash_CmdTypeDef::FLASH_CMD_ERASE_SECTOR: {
            // 扇区擦除(param为扇区地址)
            uint32_t addr = *(uint32_t*)param;
            uint8_t cmd_buf[4] = {W25QXX_SECTOR_ERASE, (addr>>16)&0xFF, (addr>>8)&0xFF, addr&0xFF};
            WriteCmd(W25QXX_WRITE_ENABLE); // 擦除前需写使能
            if (cfg.bus->Send(0x00, cmd_buf, 4, 100) != DRV_StatusTypeDef::DRV_OK)
                return DRV_StatusTypeDef::DRV_ERROR;
            HAL_Delay(100); // 等待扇区擦除完成
            break;
        }
        case Flash_CmdTypeDef::FLASH_CMD_ERASE_CHIP:
            // 芯片擦除
            WriteCmd(W25QXX_WRITE_ENABLE);
            if (WriteCmd(W25QXX_CHIP_ERASE) != DRV_StatusTypeDef::DRV_OK)
                return DRV_StatusTypeDef::DRV_ERROR;
            HAL_Delay(1000); // 等待芯片擦除完成(耗时较长)
            break;
        case Flash_CmdTypeDef::FLASH_CMD_READ_ID: {
            // 读取Flash ID(param为存储ID的缓冲区)
            uint8_t cmd_buf[4] = {W25QXX_READ_ID, 0x00, 0x00, 0x00};
            if (cfg.bus->Send(0x00, cmd_buf, 4, 100) != DRV_StatusTypeDef::DRV_OK)
                return DRV_StatusTypeDef::DRV_ERROR;
            if (cfg.bus->Recv(0x00, (uint8_t*)param, 2, 100) != DRV_StatusTypeDef::DRV_OK)
                return DRV_StatusTypeDef::DRV_ERROR;
            break;
        }
        default:
            return DRV_StatusTypeDef::DRV_PARAM_ERR;
    }
    return DRV_StatusTypeDef::DRV_OK;
}

// 反初始化实现(写禁止)
DRV_StatusTypeDef Flash::DeInit() {
    WriteCmd(W25QXX_WRITE_DISABLE); // 写禁止,锁定Flash
    return DRV_StatusTypeDef::DRV_OK;
}

main.cpp(框架统一驱动调用示例)

cpp 复制代码
#include "main.h"
#include <stdio.h>
#include <string.h>

#include "driver_common.h"
#include "drv_dev.h"
#include "drv_bus.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"

// 全局总线实例
static I2CBus  g_i2c_bus;
static SPIBus  g_spi_bus;

// 外部HAL句柄
extern UART_HandleTypeDef  huart1;
extern I2C_HandleTypeDef   hi2c1;
extern SPI_HandleTypeDef   hspi1;
extern ADC_HandleTypeDef   hadc1;
extern TIM_HandleTypeDef   htim2;

// 设备注册
static Device uart_dev = {
    "uart1", DevTypeEnum::DEV_TYPE_UART, &DRV_UART::GetInstance(), nullptr
};
static Device i2c_dev = {
    "i2c1", DevTypeEnum::DEV_TYPE_I2C, &DRV_I2C::GetInstance(), nullptr
};
static Device spi_dev = {
    "spi1", DevTypeEnum::DEV_TYPE_SPI, &DRV_SPI::GetInstance(), nullptr
};
static Device adc_dev = {
    "adc1", DevTypeEnum::DEV_TYPE_ADC, &DRV_ADC::GetInstance(), nullptr
};
static Device pwm_dev = {
    "pwm2", DevTypeEnum::DEV_TYPE_PWM, &DRV_PWM::GetInstance(), nullptr
};
static Device aht10_dev = {
    "aht10", DevTypeEnum::DEV_TYPE_AHT10, &DRV_AHT10::GetInstance(), nullptr
};
static Device oled_dev = {
    "oled", DevTypeEnum::DEV_TYPE_OLED, &DRV_OLED::GetInstance(), nullptr
};
static Device flash_dev = {
    "w25qxx", DevTypeEnum::DEV_TYPE_FLASH, &DRV_Flash::GetInstance(), nullptr
};

void Driver_Init(void)
{
    // 注册全部设备
    DeviceManager::GetInstance().RegisterDevice(&uart_dev);
    DeviceManager::GetInstance().RegisterDevice(&i2c_dev);
    DeviceManager::GetInstance().RegisterDevice(&spi_dev);
    DeviceManager::GetInstance().RegisterDevice(&adc_dev);
    DeviceManager::GetInstance().RegisterDevice(&pwm_dev);
    DeviceManager::GetInstance().RegisterDevice(&aht10_dev);
    DeviceManager::GetInstance().RegisterDevice(&oled_dev);
    DeviceManager::GetInstance().RegisterDevice(&flash_dev);

    // UART初始化
    DRV_UART_ConfigTypeDef uart_cfg = {&huart1};
    DRV_UART::GetInstance().Init(&uart_cfg);

    // I2C总线 + I2C设备初始化
    g_i2c_bus.SetHandle(&hi2c1);
    AHT10_Config_t  aht_cfg  = {&g_i2c_bus, 0x70 << 1};
    OLED_Config_t   oled_cfg = {&g_i2c_bus, 0x78 << 1};
    DRV_AHT10::GetInstance().Init(&aht_cfg);
    DRV_OLED::GetInstance().Init(&oled_cfg);
    DRV_OLED::GetInstance().Ctrl(0, nullptr);

    // SPI总线 + Flash初始化
    g_spi_bus.SetHandle(&hspi1);
    Flash_Config_t flash_cfg = {&g_spi_bus};
    DRV_Flash::GetInstance().Init(&flash_cfg);

    // ADC初始化
    DRV_ADC_ConfigTypeDef adc_cfg = {&hadc1};
    DRV_ADC::GetInstance().Init(&adc_cfg);

    // PWM初始化
    DRV_PWM_ConfigTypeDef pwm_cfg = {&htim2, TIM_CHANNEL_1};
    DRV_PWM::GetInstance().Init(&pwm_cfg);
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    MX_ADC1_Init();
    MX_TIM2_Init();

    Driver_Init();

    float temp_humi[2] = {0};
    uint32_t adc_val = 0;
    uint32_t pwm_duty = 0;
    uint8_t log_buf[128] = {0};

    while (1)
    {
        // 1.读取温湿度
        DRV_AHT10::GetInstance().Read((uint8_t*)temp_humi, 8, 100);

        // 2.读取ADC
        DRV_ADC::GetInstance().Read((uint8_t*)&adc_val, 4, 100);

        // 3.渐变PWM占空比
        pwm_duty += 20;
        if(pwm_duty > 500) pwm_duty = 0;
        DRV_PWM::GetInstance().Ctrl((uint8_t)DRV_PWM_CmdTypeDef::PWM_CMD_SET_DUTY, &pwm_duty);

        // 4.串口打印所有数据
        sprintf((char*)log_buf,
        "TEMP:%.2fC HUMI:%.2f%% ADC:%lu PWM:%lu\r\n",
        temp_humi[0], temp_humi[1], adc_val, pwm_duty);
        DRV_UART::GetInstance().Write(log_buf, strlen((char*)log_buf), 100);

        HAL_Delay(300);
    }
}

// 工程自动生成底层函数声明
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_USART1_UART_Init(void);
void MX_I2C1_Init(void);
void MX_SPI1_Init(void);
void MX_ADC1_Init(void);
void MX_TIM2_Init(void);

C++核心优势

  1. 接口统一:所有外设都继承自Peripheral基类,调用方式完全一致(Init/Read/Write/Ctrl/DeInit),无需记忆不同外设的接口差异。

  2. 封装性好:各外设的内部配置(如句柄、参数)用private修饰,外部无法直接修改,只能通过类接口操作,避免误操作。

  3. 可扩展性强:新增外设(如DAC、CAN),只需新建派生类,重写基类纯虚函数,无需修改原有代码,符合"开闭原则"。

  4. 复用性高:总线逻辑(I2C/SPI)封装为独立类,AHT10、OLED可复用I2C总线,Flash复用SPI总线,减少代码冗余。

  5. 兼容HAL库:直接调用HAL接口,和原有C框架功能完全一致,无需修改底层驱动,上手成本低。

相关推荐
hhcs2 小时前
Linux TTM 子系统:ttm_mem_reg → ttm_resource
linux·drm mm·drm ttm
сокол2 小时前
【网安-Web渗透测试-Linux提权】CVE-2023-22809
linux·服务器·网络安全
踏着七彩祥云的小丑2 小时前
嵌入式——认识电子元器件——轻触按键开关系列
单片机·嵌入式硬件
一个人旅程~2 小时前
Q4OS-linuxDebian内核版本下载链接
linux·经验分享·电脑
2601_949695592 小时前
Nvidia控制面板打不开了?问题出在这里
驱动开发·计算机外设·电脑
YQ_012 小时前
大幅提速 colcon build —— ccache 缓存 + 并行数控制防爆内存
linux·缓存·机器人·ros2
被java抛弃的网工2 小时前
Linux基础--挣点元子(1)
linux·运维·服务器
Bryce_Zhou2 小时前
stm32U5A9配置USART+DMA
stm32·单片机·嵌入式硬件
小夏子_riotous2 小时前
Docker学习路径——7、Docker搭建MySQL 主从复制
linux·运维·mysql·docker·容器·centos·云计算