news 2026/4/16 18:07:49

BH67F2472软件架构设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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函数,然后每个任务在后台运行。

程序流程图如下:

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 14:26:04

基于Web的学生成长激励系统设计与实现【高分通过】

如果你需要计算机开发、大数据、人工智能或信息安全方面的专业支持,我可以为你提供高质量、性价比突出的解决方案。 下拉到文章底部添加微信即可联系我。 高效负责、结果导向,合理收费,拒绝白嫖。 摘要 开发学生成长激励系统,既有…

作者头像 李华
网站建设 2026/4/16 11:06:14

基于实时迭代的数值鲁棒NMPC双模稳定预测模型附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 🍊个人信条:格物致知,完整Matlab代码及仿真…

作者头像 李华
网站建设 2026/4/16 12:21:56

AI辅助学习如何避免依赖陷阱?

个人首页: VON 鸿蒙系列专栏: 鸿蒙开发小型案例总结 综合案例 :鸿蒙综合案例开发 鸿蒙6.0:从0开始的开源鸿蒙6.0.0 鸿蒙5.0:鸿蒙5.0零基础入门到项目实战 本文章所属专栏:《AI从0到1:普通人…

作者头像 李华
网站建设 2026/4/16 12:28:58

基于SpringBoot的高校HIV预防宣传系统毕业设计项目源码

项目简介基于 SpringBoot 的高校 HIV 预防宣传系统,直击 “高校 HIV 科普覆盖不足、学生认知片面、咨询求助渠道不畅” 的核心痛点,依托 SpringBoot 轻量级框架优势与高校场景化运营能力,构建 “科普宣传 风险自测 在线咨询 数据管理” 的…

作者头像 李华
网站建设 2026/4/16 12:56:29

刷题日记day4(搜索)

第一篇题解 蒟蒻的第四篇题解希望大家支持 题目描述 P3915树的分解 P3915 树的分解 题目描述 给出 NNN 个点的树和 KKK,问能否把树划分成 NK\frac{N}{K}KN​ 个连通块,且每个连通块的点数都是 KKK。 输入格式 第一行,一个整数 TTT&am…

作者头像 李华