采用「抽象基类+派生类」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++核心优势
-
接口统一:所有外设都继承自
Peripheral基类,调用方式完全一致(Init/Read/Write/Ctrl/DeInit),无需记忆不同外设的接口差异。 -
封装性好:各外设的内部配置(如句柄、参数)用private修饰,外部无法直接修改,只能通过类接口操作,避免误操作。
-
可扩展性强:新增外设(如DAC、CAN),只需新建派生类,重写基类纯虚函数,无需修改原有代码,符合"开闭原则"。
-
复用性高:总线逻辑(I2C/SPI)封装为独立类,AHT10、OLED可复用I2C总线,Flash复用SPI总线,减少代码冗余。
-
兼容HAL库:直接调用HAL接口,和原有C框架功能完全一致,无需修改底层驱动,上手成本低。