嵌入式设计模式之策略模式(2)

场景描述

假设有一个嵌入式设备需要与多种外部传感器通信(如温湿度传感器、加速度计、显示屏),这些传感器分别使用UART、I2C、SPI协议。设备需要根据当前连接的传感器类型,动态选择通信协议。


策略模式实现

1. 定义策略接口(通信协议通用接口)

复制代码
// communication_strategy.h
typedef struct {
    int (*init)(void);           // 初始化协议
    int (*send)(uint8_t *data, uint32_t len);  // 发送数据
    int (*receive)(uint8_t *buffer, uint32_t len); // 接收数据
    void (*deinit)(void);        // 释放资源
} CommunicationStrategy;

2. 实现具体策略类(UART/I2C/SPI)

UART策略实现
复制代码
// uart_strategy.c
#include "hal_uart.h"

static int uart_init(void) {
    return uart_initialize(115200, UART_PARITY_NONE); // 初始化UART
}

static int uart_send(uint8_t *data, uint32_t len) {
    return uart_transmit(data, len); // UART发送数据
}

static int uart_receive(uint8_t *buffer, uint32_t len) {
    return uart_receive(buffer, len); // UART接收数据
}

static void uart_deinit(void) {
    uart_deinitialize(); // 关闭UART
}

// UART策略对象
const CommunicationStrategy uart_strategy = {
    uart_init,
    uart_send,
    uart_receive,
    uart_deinit
};
I2C策略实现
复制代码
// i2c_strategy.c
#include "hal_i2c.h"

static int i2c_init(void) {
    return i2c_configure(I2C_SPEED_100KHZ); // 初始化I2C
}

static int i2c_send(uint8_t *data, uint32_t len) {
    return i2c_write(SENSOR_ADDRESS, data, len); // I2C发送(需设备地址)
}

static int i2c_receive(uint8_t *buffer, uint32_t len) {
    return i2c_read(SENSOR_ADDRESS, buffer, len); // I2C接收
}

static void i2c_deinit(void) {
    i2c_disable();
}

// I2C策略对象
const CommunicationStrategy i2c_strategy = {
    i2c_init,
    i2c_send,
    i2c_receive,
    i2c_deinit
};
SPI策略实现
复制代码
// spi_strategy.c
#include "hal_spi.h"

static int spi_init(void) {
    return spi_configure(SPI_MODE_0, 1000000); // 初始化SPI
}

static int spi_send(uint8_t *data, uint32_t len) {
    spi_select_device(DEVICE_CS);   // 片选使能
    int ret = spi_transmit(data, len);
    spi_deselect_device(DEVICE_CS); // 片选禁用
    return ret;
}

static int spi_receive(uint8_t *buffer, uint32_t len) {
    spi_select_device(DEVICE_CS);
    int ret = spi_receive(buffer, len);
    spi_deselect_device(DEVICE_CS);
    return ret;
}

static void spi_deinit(void) {
    spi_disable();
}

// SPI策略对象
const CommunicationStrategy spi_strategy = {
    spi_init,
    spi_send,
    spi_receive,
    spi_deinit
};

3. 上下文类(通信管理器)

复制代码
// communication_manager.c
typedef struct {
    const CommunicationStrategy *strategy;  // 当前使用的协议策略
} CommunicationManager;

// 设置通信策略
void comm_set_strategy(CommunicationManager *mgr, 
                      const CommunicationStrategy *strategy) {
    if (mgr->strategy) {
        mgr->strategy->deinit();  // 先释放当前协议资源
    }
    mgr->strategy = strategy;
    mgr->strategy->init();        // 初始化新协议
}

// 发送数据(委托给当前策略)
int comm_send_data(CommunicationManager *mgr, 
                  uint8_t *data, uint32_t len) {
    if (mgr->strategy) {
        return mgr->strategy->send(data, len);
    }
    return -1; // 错误:未设置策略
}

// 接收数据
int comm_receive_data(CommunicationManager *mgr, 
                     uint8_t *buffer, uint32_t len) {
    if (mgr->strategy) {
        return mgr->strategy->receive(buffer, len);
    }
    return -1;
}

使用示例

复制代码
int main() {
    CommunicationManager comm_mgr = {0};
    uint8_t tx_data[] = {0x01, 0x02, 0x03};
    uint8_t rx_data[10];
    
    // 场景1:连接温湿度传感器(使用I2C)
    comm_set_strategy(&comm_mgr, &i2c_strategy);
    comm_send_data(&comm_mgr, tx_data, sizeof(tx_data));
    comm_receive_data(&comm_mgr, rx_data, sizeof(rx_data));
    
    // 场景2:切换至GPS模块(使用UART)
    comm_set_strategy(&comm_mgr, &uart_strategy);
    comm_send_data(&comm_mgr, tx_data, sizeof(tx_data));
    
    // 场景3:连接显示屏(使用SPI)
    comm_set_strategy(&comm_mgr, &spi_strategy);
    comm_send_data(&comm_mgr, tx_data, sizeof(tx_data));
    
    return 0;
}

策略模式在此场景的优势

  1. 协议透明性:上层应用无需关心底层是UART、I2C还是SPI。
  2. 运行时动态切换:根据外设热插拔或模式变化实时切换协议。
  3. 易于扩展:新增协议(如CAN、USB)只需实现策略接口,无需修改现有代码。
  4. 资源管理:策略切换时自动处理硬件初始化/释放,避免资源冲突。

典型应用场景

  • 多模通信设备:如同时支持蓝牙、Wi-Fi、LoRa的物联网网关。
  • 传感器融合系统:需要交替读取不同协议传感器的数据。
  • 协议适配器:兼容不同厂家设备的通信协议。

这种设计特别适合嵌入式中间件 或硬件抽象层(HAL) 的开发!

相关推荐
一隅论数智4 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
上海广测检测科技有限公司4 天前
智能平板出口巴西合规详解:Anatel射频、Inmetro电源/电池与LGPD数据合规叠加
经验分享
FLJwu4 天前
存储与固件量产实战01:运动相机TF卡量产翻车实录!V30≠4K可用,90%OEM踩中的隐形售后坑
经验分享·数码相机·相机
xiaomu001234 天前
床垫选型的技术评估模型:结构、材料、卫生与检测四层口径
经验分享
汉风设计装饰4 天前
智慧办公弱电系统设计:门禁、监控与 IoT 传感器的集成方案
经验分享
m0_719640874 天前
支持开源二次开发的VR遥操机器人2026年选型推荐
经验分享
陈卫军老师5 天前
陈卫军:把口味写在一张纸上,店才稳得住
经验分享·笔记·流量运营
从零开始的嵌入式之旅5 天前
day47
arm开发·经验分享·笔记·嵌入式硬件
恒锐丰科技林技术员5 天前
EG1164 高压大电流升压同步整流芯片解析
经验分享·嵌入式硬件·硬件工程
欣悦财务5 天前
怎么判断代理记账收费值不值,把费用折成服务密度再比
经验分享