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

单片机的工厂方法模式

记录下单片机使用工厂方法模式
在STM32上使用简单工厂模式(Simple Factory Pattern)的示例,以传感器为例。
简单工厂模式:定义一个工厂类(或函数),根据传入的参数决定创建哪一种具体的产品对象。在嵌入式系统中,对象通常通过结构体和函数指针来模拟。

我们将以传感器为例:假设有多个传感器类型(比如温度传感器、湿度传感器),每个传感器有初始化、读取数据等方法。工厂根据传感器类型返回对应的传感器对象(结构体指针)。

需要提供:
1.传感器抽象接口(结构体,包含函数指针)
2.具体传感器实现(温度传感器、湿度传感器)
3.工厂函数:根据类型创建对应的传感器实例,并返回接口指针。

sensor.h

#ifndef__DRV_SENSOR_H#define__DRV_SENSOR_H#include<stdint.h>/* 传感器类型枚举 */typedefenum{SENSOR_DS18B20,SENSOR_DHT22,SENSOR_TYPE_MAX}SensorType_t;/* 传感器对象结构体(类似于抽象类) */typedefstruct{void(*Init)(void*pPrivate);// 初始化函数float(*Read)(void*pPrivate);// 读取数据函数void*pPrivate;// 私有数据(具体传感器需要的硬件信息)constchar*name;// 传感器名称}Sensor_t;/* 工厂函数:创建传感器对象(返回常量指针,避免外部修改) */constSensor_t*Sensor_Create(SensorType_t type);#endif

sensor.c

#include"drv_sensor.h"#include"drv_DHT22.h"#include"drv_DS18B20.h"/* DHT22 私有数据 */staticDHT22_Private_t dht22_priv={.port=GPIOB,.pin=GPIO_PIN_1};staticconstSensor_t dht22_sensor={.Init=DHT22_Init,.Read=DHT22_Read,.pPrivate=&dht22_priv,.name="DHT22"};/* 静态私有数据实例(假设使用固定的引脚:例如 GPIOA, GPIO_PIN_0) */staticDS18B20_Private_t ds18b20_priv={.port=GPIOA,.pin=GPIO_PIN_0};/* DS18B20 传感器对象 */staticconstSensor_t ds18b20_sensor={.Init=DS18B20_Init,.Read=DS18B20_Read,.pPrivate=&ds18b20_priv,.name="DS18B20"};/* 工厂函数:根据类型返回对应的传感器对象 */constSensor_t*Sensor_Create(SensorType_t type){switch(type){caseSENSOR_DS18B20:return&ds18b20_sensor;// 需要外部声明caseSENSOR_DHT22:return&dht22_sensor;default:returnNULL;}}

DS18B20.h

#ifndef__DRV_DS18B20_H#define__DRV_DS18B20_H#include<stdint.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include"stm32f4xx_hal.h"#include"drv_sensor.h"typedefstruct{GPIO_TypeDef*port;uint16_tpin;}DS18B20_Private_t;staticvoidDS18B20_DelayUs(uint32_tus);staticuint8_tDS18B20_Reset(void*pPrivate);staticvoidDS18B20_WriteByte(void*pPrivate,uint8_tdata);staticuint8_tDS18B20_ReadByte(void*pPrivate);voidDS18B20_Init(void*pPrivate);floatDS18B20_Read(void*pPrivate);#endif

DS18B20.c

#include"drv_DS18B20.h"/* 模拟单总线时序的函数(实际工程需精确延时) */staticvoidDS18B20_DelayUs(uint32_tus){// 简单循环延时,建议使用定时器或HAL_Delay微秒级实现for(uint32_ti=0;i<us*10;i++){__NOP();}}/* 复位脉冲和存在检测 */staticuint8_tDS18B20_Reset(void*pPrivate){DS18B20_Private_t*priv=(DS18B20_Private_t*)pPrivate;// 拉低总线 480usHAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_RESET);DS18B20_DelayUs(480);HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_SET);DS18B20_DelayUs(70);// 读取存在脉冲uint8_tpresence=HAL_GPIO_ReadPin(priv->port,priv->pin);DS18B20_DelayUs(410);returnpresence;}/* 写一个字节 */staticvoidDS18B20_WriteByte(void*pPrivate,uint8_tdata){DS18B20_Private_t*priv=(DS18B20_Private_t*)pPrivate;for(inti=0;i<8;i++){HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_RESET);DS18B20_DelayUs(2);if(data&0x01){HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_SET);}DS18B20_DelayUs(60);HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_SET);DS18B20_DelayUs(2);data>>=1;}}/* 读一个字节 */staticuint8_tDS18B20_ReadByte(void*pPrivate){DS18B20_Private_t*priv=(DS18B20_Private_t*)pPrivate;uint8_tdata=0;for(inti=0;i<8;i++){data>>=1;HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_RESET);DS18B20_DelayUs(2);HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_SET);DS18B20_DelayUs(2);if(HAL_GPIO_ReadPin(priv->port,priv->pin)){data|=0x80;}DS18B20_DelayUs(60);}returndata;}/* DS18B20 初始化函数(执行一次复位) */voidDS18B20_Init(void*pPrivate){// DS18B20_Reset(pPrivate);printf("DS18B20 Init is OK \n");}/* DS18B20 读取温度函数 */floatDS18B20_Read(void*pPrivate){// // 启动温度转换// DS18B20_Reset(pPrivate);// DS18B20_WriteByte(pPrivate, 0xCC); // 跳过ROM// DS18B20_WriteByte(pPrivate, 0x44); // 启动转换// // 等待转换完成(通常750ms,这里简化)// HAL_Delay(750);// // 读取暂存器// DS18B20_Reset(pPrivate);// DS18B20_WriteByte(pPrivate, 0xCC);// DS18B20_WriteByte(pPrivate, 0xBE);// uint8_t lsb = DS18B20_ReadByte(pPrivate);// uint8_t msb = DS18B20_ReadByte(pPrivate);// int16_t raw = (msb << 8) | lsb;// return raw * 0.0625f; // 12位精度,LSB=0.0625°Creturn10;}

DHT22.h

#ifndef__DRV_DHT22_H#define__DRV_DHT22_H#include<stdint.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include"stm32f4xx_hal.h"#include"drv_sensor.h"typedefstruct{GPIO_TypeDef*port;uint16_tpin;}DHT22_Private_t;staticvoidDHT22_DelayUs(uint32_tus);staticuint8_tDHT22_ReadData(void*pPrivate,int16_t*temp,int16_t*humi);voidDHT22_Init(void*pPrivate);floatDHT22_Read(void*pPrivate);#endif

DHT22.c

#include"drv_DHT22.h"/* 微秒延时(同DS18B20,可共用) */staticvoidDHT22_DelayUs(uint32_tus){for(uint32_ti=0;i<us*10;i++){__NOP();}}/* 读取DHT22数据,返回温度×10,湿度×10 */staticuint8_tDHT22_ReadData(void*pPrivate,int16_t*temp,int16_t*humi){DHT22_Private_t*priv=(DHT22_Private_t*)pPrivate;uint8_tdata[5]={0};// 主机拉低至少18msHAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_RESET);HAL_Delay(20);HAL_GPIO_WritePin(priv->port,priv->pin,GPIO_PIN_SET);DHT22_DelayUs(40);// 等待DHT22响应// 检测响应if(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_RESET){// 等待80us低电平结束while(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_RESET);// 等待80us高电平结束while(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_SET);// 读取40位数据for(inti=0;i<40;i++){while(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_RESET);DHT22_DelayUs(40);if(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_SET){data[i/8]|=(1<<(7-(i%8)));}while(HAL_GPIO_ReadPin(priv->port,priv->pin)==GPIO_PIN_SET);}// 校验和if(data[4]==((data[0]+data[1]+data[2]+data[3])&0xFF)){*humi=(data[0]<<8)|data[1];*temp=(data[2]<<8)|data[3];return1;}}return0;}voidDHT22_Init(void*pPrivate){// DHT22 上电后需要1s稳定,初始化时不需要额外操作HAL_Delay(1000);printf("DHT22 Init is OK \n");}floatDHT22_Read(void*pPrivate){// int16_t temp, humi;// if (DHT22_ReadData(pPrivate, &temp, &humi))// {// // 返回温度值(保留一位小数)// return temp / 10.0f;// }// return -999.0f; // 错误标志return15;//}

测试

/** * @brief The application entry point. * @retval int */intmain(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit */EventRecorderInitialize(EventRecordAll,1U);EventRecorderStart();/* USER CODE END SysInit */DWT_Init();/* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */// 创建温度传感器(DS18B20)constSensor_t*temp_sensor=Sensor_Create(SENSOR_DS18B20);if(temp_sensor){temp_sensor->Init(temp_sensor->pPrivate);printf("Sensor is %s\n",temp_sensor->name);}// 创建湿度传感器(DHT22)constSensor_t*humi_sensor=Sensor_Create(SENSOR_DHT22);if(humi_sensor){humi_sensor->Init(humi_sensor->pPrivate);printf("Sensor is %s\n",humi_sensor->name);}while(1){if(temp_sensor){floatt=temp_sensor->Read(temp_sensor->pPrivate);printf("Temperature: %.2f°C\n",t);}if(humi_sensor){floath=humi_sensor->Read(humi_sensor->pPrivate);printf("Humidity: %.2f%%\n",h);}HAL_Delay(2000);}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */// while (1)// {// /* USER CODE END WHILE */// /* USER CODE BEGIN 3 */// HAL_Delay(100);// }/* USER CODE END 3 */}

可以看到正确显示了相应传感器和数值,而调用的是同一个函数。若替换了相应的温度传感器和湿度传感器,则只需要在Sensor_Create(xx)即可。

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

相关文章:

  • AIVideo如何降本提效?中小企业AI视频创作平台落地实践
  • 小工厂也能搞智能排程?MES+轻量化APS的落地思路
  • 3D Face HRN惊艳案例:3D人脸重建+风格迁移联合生成艺术化头像
  • 关于如何将项目上传至Github(大于100MB的文件)
  • COZE - 1
  • 在openSUSE-Leap-15.6-DVD-x86_64中使用gnome-builder-45.0的基本功能(一)
  • Git-RSCLIP遥感图像分类代码实例:Python调用API实现批量推理
  • 蓝桥杯嵌入式-任务调度器
  • GME-Qwen2-VL-2B-Instruct效果展示:修复指令后,低匹配误判率下降68%(实测数据)
  • Qwen3-VL:30B快速部署教程:星图平台Qwen3-VL:30B+Clawdbot飞书集成全流程
  • all-MiniLM-L6-v2部署教程:Ollama + Grafana构建Embedding服务可观测体系
  • Pi0真实场景迁移路径:演示模式→仿真环境→真机ROS桥接全流程
  • GTE-Pro快速上手:curl命令直调REST API,验证‘缺钱’→‘资金链断裂’语义映射
  • 国家超算中心免费算力 海光深算三号BW1000(即异构加速卡BW)性能上对标NVIDIA H100,在AI训练 A100
  • DeepChat环境配置:Mac M2/M3芯片原生运行Llama3:8b的Metal加速配置指南
  • 2026年靠谱的等离子切割电焊两用机工厂推荐:固态电池焊接逆变两用机厂家选择指南 - 品牌宣传支持者
  • lingbot-depth-vitl14多场景实战:机器人SLAM前端深度图供给、AR虚拟锚点定位应用
  • DAMO-YOLO嵌入式部署:树莓派5+RPi.GPIO硬件触发识别流程
  • Nanbeige4.1-3B实战手册:用WebUI API对接企业微信/钉钉Bot服务
  • 2026年口碑好的推拉棚厂家推荐:活动推拉棚/大型推拉棚/大型固定推拉棚实力工厂怎么选 - 品牌宣传支持者
  • Qwen3-TTS声音克隆入门指南:如何录制高质量参考音频提升克隆效果
  • Nunchaku FLUX.1-dev开源可审计优势:模型权重/代码/工作流全透明
  • Qwen3-ASR-1.7B应用场景:法律庭审录音→发言角色分离+证据片段定位系统
  • 2026年知名的不插电电焊机厂家推荐:电机车蓄电池电焊机/矿用直流轨道电焊机实力工厂怎么选 - 品牌宣传支持者
  • CLIP-GmP-ViT-L-14部署教程:NVIDIA驱动+CUDA12.1+PyTorch2.1兼容方案
  • 伏羲天气预报实时校准:在线学习机制对预报偏差的动态补偿教程
  • Express/Koa 中间件的洋葱模型解析
  • GTE中文嵌入模型保姆级教程:GPU内存不足时的batch_size调优策略
  • 2026年比较好的防水涂料工厂推荐:道桥水性沥青基防水涂料/水泥基渗透结晶型防水涂料公司口碑哪家靠谱 - 品牌宣传支持者
  • 保护隐私的AI写真方案:Asian Beauty Z-Image Turbo纯本地推理实战解析