当前位置: 首页 > news >正文

嵌入式设计模式之策略模式(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)的开发!

http://www.jsqmd.com/news/639920/

相关文章:

  • ESP32-S3-WROOM1引脚电平实测:为什么你的TFT屏幕不亮?可能是这几个GPIO在捣鬼
  • 跨越山海,数据直达:基于星空组网实现Windows与群晖的异地高效互联
  • 论文AIGC率太高?降痕技巧+平台避坑指南来了
  • Visual C++ Redistributable AIO:如何解决Windows运行库依赖问题的完整架构分析
  • 三步构建你的专属知识星球离线图书馆
  • 精准研判植被变绿趋势!长时序NDVI/LAI/GPP综合分析,干货拉满
  • 完整指南:使用DDrawCompat让经典DirectX游戏在现代Windows上完美运行
  • TrollInstallerX:iOS设备快速部署TrollStore的智能安装方案
  • 从MCUXpresso IDE迁移到VS Code:一个NXP MCU老鸟的CMake工程改造笔记
  • 网站国产化改造,如何做到软件成本几乎为零?
  • 健康160终极抢号神器:5分钟开启全自动挂号新时代
  • 3步掌握飞书文档转换:Cloud Document Converter零基础上手指南
  • 5、HPC集群基石:从零部署Munge认证服务
  • 【OpenClaw】通过 Nanobot 源码学习架构---()
  • 详细解释什么是 VM 虚拟机?
  • LM5109A半桥驱动芯片自举电路设计中的关键问题与解决方案
  • 安卓安全加固公司哪家强?技术实力、价格与售后保障全对比
  • 解决texstudio中提示错误 File `pstricks.sty not found. ^^M
  • 深入解析DRM驱动架构:从U-Boot阶段到Linux内核的显示驱动实现
  • 怎样为Windows 11 LTSC系统一键恢复微软商店:全面安装指南
  • 2026届毕业生推荐的十大降AI率方案推荐
  • AI净界-RMBG-1.4效果实测: vs Photoshop 抠图精度与效率对比
  • 2026年泉州生成式引擎优化领域综合实力3强机构深度分析报告 - 小白条111
  • 金融、游戏、IoT应用怎么选安卓安全加固?行业定制化方案解析
  • 嵌入式设备上的轻量级部署探索:Pixel Script Temple模型剪枝与量化
  • 如何免费解锁Cursor Pro功能:终极破解指南
  • 5个简单步骤:用Blender 3MF插件打造专业3D打印工作流
  • 【仅限首批200位架构师】AIAgent测试契约协议(Test Contract Protocol)v1.2内部文档首次公开
  • Keepalived + LVS(DR)+ Nginx + NFS
  • 如何永久备份微信聊天记录:免费开源工具WeChatMsg完全指南