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

BH67F2472软件架构设计

1.难题

作为一名嵌入式开发者,想必各位小伙伴对以下场景早已司空见惯:当你正埋头于调试那几行关键代码,或者准备给项目打包成完工版本的时候。总有一个声音会适时响起:“咱再加个小功能呗?”通常这小功能,相当于要求你的自行车瞬间变身成摩托车。运气好点,是场局部“微创手术”;运气不好呢,直接项目重写

为啥咱总能精准踩坑?别怀疑,这大概率不是命运的捉弄,而是咱自己挖的。软件设计原则?好像听说过。设计模式?听起来像时尚界的潮流,咱搞硬件的实在人用不上吧?于是,咱的代码就成功进化成了“面向需求变更崩溃编程”,这种代码的结构之“精妙”,让任何试图修改它的人,都想给自己点一首《凉凉》。

为了避免下次需求变更时,咱的代码再次表演“原地爆炸”,我将以一个代码来介绍如何遵循软件设计原则,如何使用良好的设计模式和架构。

2.背景

前文提到,作为一名硬件工程师因为生活饮食不规律,缺少运动,导致最近做体检时发现我目前的血糖偏高。为实现血糖的动态监测,我还网购了一个家用的血糖仪,每天定时测量血糖数据。由于自己从事多年的仪器仪表行业,对这个每天用来测血糖的“小家伙”充满好奇,犹豫了很久将它拆开后发现一个惊人事实:整个电路板只有一颗芯片!一款专用于血糖仪的单片机BH67F2472。

详细查看电路板后,我发现仪器的制造商居然把芯片的程序下载口预留出来了,我网购了一个Holtek的下载器,安装了开发工具HT-IDE3000,并将这个自己写的程序下载到了血糖仪电路板的芯片中。接下来,我将以BH67F2472的一个代码来介绍如何遵循软件设计原则,如何使用良好的设计模式和架构。

3.电路介绍

程序使用了以下硬件资源:

  • 按键:GPIO口PA3连接按键,通过读取PA3的电平信号来检测按键是否按下;

  • 蜂鸣器:GPIO口PB6连接蜂鸣器,过控制PB6的电平驱动蜂鸣器,让蜂鸣器发出声音;

  • 液晶屏:LCD驱动引脚COM0COM3,SEG1SEG8连接到了段码液晶屏,微控制器内部的 LCD 驱动控制器按照特定的扫描时序在 COM 和SEG 线上产生驱动电压,点亮或熄灭液晶屏上特定的字段;

  • 温度测量:ADC通道1的PB3连接NTC热敏电阻,NTC的电阻值随环境温度变化而变化,当温度变化时NTC上的分压值随之改变。ADC通道读取PB3上的模拟电压值,实现温度测量;

  • 串口通信:UART0的TX/RX连接串口,实现输出调试打印信息。

4.程序介绍

4.1.模块化设计

程序采用了模块化设计,每个功能独立成一个模块。简单来说,就是把软件这个大工程,像搭乐高积木一样,拆成了一个个独立的功能模块 —— 每个模块负责一件事,谁也别抢谁的活儿。
这种设计方法的核心思想就是 :分而治之。通俗的讲就是:当你面对一个复杂的大问题,最明智的做法就是把它“化整为零”,拆解成一系列小到可以轻松搞定的小问题,然后挨个解决掉。程序的模块化设计如下图:

程序包含三个任务:

  • 任务一GPIO任务,GPIO口PA3连接按键,GPIO口PB6连接蜂鸣器,程序通过按键实现用户对显示内容的控制,短按按键实现循环切换显示模式:温度→血糖→电量→温度,每切换一次蜂鸣器会发出短鸣提示。
  • 任务二LCD任务,程序控制微控制器内部的 LCD
    驱动控制器点亮或熄灭液晶屏上特定的字段,实现3位7段数字的显示,同时段码液晶屏还可以显示不同数据的单位。
  • 任务三NTC任务,ADC通道1的PB3连接NTC热敏电阻,NTC的电阻值随环境温度变化而变化,当温度变化时NTC
    上的分压值随之改变。ADC通道读取 PB3上的模拟电压值,实现温度测量。

这种模块化设计严格遵循了单一职责原则——每个模块只专心做好自己那一摊事儿,绝不越界抢活干,模块之间奉行“君子之交淡如水”,彼此低耦合,互不依赖。这样一来,修改一个模块的代码,完全不用担心会“城门失火,殃及池鱼”,各干各的,互不打扰,世界和平!
模块化设计提高了软件系统的扩展性,软件工程源码中功能模块如下:

4.2.调度器

RTOS 通常需要额外的内存开销用于任务栈、内核数据结构以及提供任务调度。由于BH67F2472有限的计算资源(如 RAM、ROM 容量较小)和相对较低的运算性能,无法有效地承载一个完整的实时操作系统(RTOS)运行环境。为了在资源受限的条件下实现多任务逻辑的轮转执行,开作者设计并实现了一个精简的轮询式任务调度器。
HOLTEK开发环境所使用的 C 编译器不支持函数指针,函数指针是构建动态任务调用机制的常用且高效手段,缺失函数指针实现调度器将变得比较笨拙,只能使用枚举量和switch语句实现,在scheduler文件中实现了一个轮询执行的“伪调度器”,关键代码如下:

这种设计实现的调度器被称为“伪调度器”,因为这个调度器有以下特点:

  • 任务执行是顺序执行、非抢占执行。一个任务必须主动执行完毕并返回(break 出
    case)后,调度器才能切换到下一个任务,不存在由中断或系统调用触发的任务强制切换。
  • 静态绑定: 任务与枚举值、case 分支是静态编译时绑定的,缺乏运行时动态创建、删除或修改任务列表的能力。
  • 轻量级: 其实现极其简洁,仅需一个枚举变量、一个 switch 语句和若干函数调用,几乎不消耗额外的 RAM
    资源(栈空间除外),代码体积(ROM)也很小,完美契合资源受限环境。
4.3.分层设计

每一个任务都采用了分层设计,分层设计的核心思想也是“分而治之”,分层设计将软件功能水平分割成合理的多个子系统,软件中紧密关联的部分被集中放在一个层内。分层架构有以下优点:

  • 每一层都把一个具体功能抽象化。
  • 可以降低代码的相互依赖程度,更改代码时影响的层很少。
  • 层可以被复用。

程序中采用了2层的分层设计,第1层处理MCU寄存器相关操作,第2层处理驱动控制和逻辑控制,分层设计提高了软件系统的移植性,如果项目更换了MCU那么只用修改第1层,如果更改了业务逻辑那么只用修改第2层。分层架构框图如下:

以GPIO任务为例,GPIO的BSP层的接口函数是gpio_bsp_operation,上层文件可以通过gpio_bsp_operation函数完成GPIO的寄存器初始化、读操作、写操作。GPIO任务的BSP层代码如下:

4.4.隔离设计

程序中的任务相互隔离,所有任务只与调度器进行数据交互,然后调度器将消息推送给其他任务。各个任务之间的信息交互模式如下:

这种设计模式为中间者模式。在中间者模式,对象之间不能直接通信,而是间接地通过中间者进行通信。中间者收到信息后,再将信息转发给相关对象,这样减少了对象之间的相互依赖。中间者模式有以下优点:

  • 对象之间是松耦合。
  • 将多对多的关系通过中间者转换成一对一的关系。
  • 修改一个对象,不需要考虑其它对象通信适应问题。

这种设计减少了任务之间的耦合,提高了软件的扩展性,消息交互代码如下:

4.5.程序流程图

程序主要分为四个过程:

  • 初始化系统时钟,配置MCU系统时钟为8MHZ
  • 执行调度器初始化动作,调度器依次调用所有任务中的initialization函数,执行各个任务初始化。
  • 执行调度器依次调用所有任务read函数获取改任务输出信息,并将读取到的信息通过调用其他任务write函数写入执行操作。
  • 执行调度器依次调用所有任务run函数,然后每个任务在后台运行。

程序流程图如下:

感兴趣的小伙伴,希望获取资料的小伙伴,可以评论区留言或者私信作者。

http://www.cnnetsun.cn/news/27166.html

相关文章:

  • 昇腾 Ascend 自定义算子开发全攻略:从 TBE DSL 到 AICPU,打通 AI 加速最后一公里
  • 当电机开始“唱歌“:NVH工程师的降噪日常
  • AI界的“经济适用男“!80亿参数小模型完胜GPT-5,成本降低70%,CSDN程序员必藏的智能调度方案
  • FPGA教程系列-Vivado Aurora 8B/10B 例程解读
  • 227827827
  • MCU的启动流程你了解么?
  • 逻辑回归(Logistic Regression)进行多分类的实战
  • RNN(循环神经网络)原理
  • 人机协同重构创作生态——生成式AI赋能内容产业的变革与思考
  • Java 小白求职者在互联网大厂的面试实录:从 Spring Boot 到微服务架构
  • V助手舆情分析智能体:重塑舆情分析,从“人找信息”到“信息为人”
  • 连接2026:十款远程控制软件真实力横评与选择指南
  • 计算机毕业设计springboot基于Spark++Vue.js的学生管理系统 Spark+Vue 高校学生综合信息管理平台 基于 SpringBoot+Spark+Vue 的全链路学生事务中心
  • JavaScript 集合操作的哈希碰撞:攻击者如何利用特殊 Key 导致 Map/Set 性能降级到 O(N)
  • 为什么 C盘空间会莫名其妙减少(即使没装新软件)?
  • 17、深入理解 Linux 文件系统机制与结构
  • 29、Linux 软件使用与故障排除指南
  • 从入门到转行:网络安全自学与跳槽的终极建议
  • 网络安全小白自学之路,别拜师了,求人不如求己_网络安全小白怎么自学
  • 从系统运维到网络安全工程师,8个月转行真实经验分享!
  • 算法系列(Algorithm)- 快速排序
  • RobotStudio2025全功能授权
  • IsaacLab中UR机械臂与Robotiq夹爪的5大配置难点与解决方案
  • cmark Markdown解析器终极指南:从入门到精通
  • 4-bit量化FLUX模型:让专业AI绘图走进寻常百姓家
  • Excel VBA快速入门:7天从零到精通终极指南
  • AutoHotkey鼠标轨迹自动化终极指南:从零开始实现精准操作回放
  • UxPlay 终极指南:在 Linux 系统上实现 AirPlay 镜像的完整教程
  • 1-2 惜败!国安亚冠连败 中超 16 强魔咒难破
  • 一键解锁阅读3.0书源终极合集:1629个精品资源任你选