关于单片机STM32裸机程序架构设计

发布者:幸福旅程最新更新时间:2024-05-07 来源: elecfans关键字:单片机  STM32 手机看文章 扫描二维码
随时随地手机看文章

本着授人以渔的原则,既提供我一直在用的程序架构,也讲程序架构的设计思路。

如果本文内容,你都能领悟并做到,不管项目多复杂,都将游刃有余。


我研发的那几年,接触大多数工程师,都没有程序架构的概念,基本一个while死循环干到底。

模块之间也没有封装好,导致代码写好以后,扩展性和维护性太差,类似的功能代码,也很难移植到新项目去复用。

早期我也是这样写的,反正实现功能就行了,代码好不好,功能上又看不出区别。

不过,等你接触到复杂的项目时,这招就行不通了,没设计好程序架构,根本做不稳定。

我意识到这个问题,是碰到两种需求的时候:

1.是做一个基于STM32的网关项目,项目做完以后,客户老是要改功能,客户不懂技术,在客户眼里,觉得改一个LED闪烁效果很简单,但对于程序架构没设计好的工程师来说,就是一个噩梦,比如每隔5秒快闪2次这种恶心的需求,搞不好很多代码都要重新组织。

我经常会被这种问题搞到头痛,特别是客户又催得急的时候,经常加班加到焦头烂耳,越急又越搞不出来。

2.我做过的很多项目,其实很多功能都有重复的,比如很多产品都有LED、都有按键、都有掉电参数存储、都有串口协议解析等等。

但是程序架构没写好,导致想移植代码,过来新项目复用时,不太好改,比如老项目才1个LED,新项目有6个LED,类似的还有按键等等。

后面为了有更多的时间摸鱼,我开始思考,怎么把程序写得,改起功能来很方便,代码复用性又很强那种,当时还不知道这个叫程序架构设计。

程序架构,我觉得是一个系统的学问,贯穿着整个项目,而不是具体某些细节。

就是各种功能模块,比如LED特效功能,按键检测功能,菜单功能,系统参数存储功能、语音功能、OTA升级功能等等。

这些功能模块的设计,我通常是采用硬件驱动代码和功能逻辑代码分离的方式,用大白话来说,就是一个功能模块,我可能会分2个.c文件来写,硬件驱动代码我以hal_xxx.c命名,功能逻辑代码我以mt_xxx.c命名。

硬件驱动代码主要是和单片机外设的配置代码,比如设置GPIO、Timer、串口、SPI这些,然后提供硬件接口给mt_xxx.c调用。

拿无际项目特训营的项目6来举例,这个项目可以实现远程控制,因为加了WiFi和4G模块。

如果你接触过类似项目,单片机和云平台之间,其实还有个串口通讯协议的,类似于下图这种。

a7c675aa-7f7a-11ee-939d-92fbcf53809c.png

按照我的思维,我会这样去设计程序:

单片机外设驱动的配置、串口发送数据、接收数据代码,我都放在hal_uart.c里。

a7e4cadc-7f7a-11ee-939d-92fbcf53809c.png

串口协议数据发送和解析的代码,我会放在mt_protocol.c文件里。

a808c824-7f7a-11ee-939d-92fbcf53809c.png

这样就能实现硬件驱动代码和功能逻辑代码彻底分离。

那这样的好处是什么?

1.万一要换单片机了,如果通讯协议不变的情况下,mt_protocol.c文件代码可以不用改,只要改hal_uart.c硬件驱动程序,就能对接起来。

2.如果通讯协议格式变了,单片机不变,那只需要改mt_protocol.c文件代码就可以了。

3.调试方便,比如mt_protocol.c的功能,可以在PC上搭建一个开发环境先调试好,再对接硬件驱动接口,对于复杂的功能,这招还是很有用的,毕竟keil仿真调试没那么方便灵活。

这种设计,就是一种架构思维,解决了代码扩展性和移植性的问题。

如果每个功能模块都采用这种思维去设计,最终从整体看,你的程序架构就非常好了,就像组装汽车一样灵活了。

所以,要设计好程序架构,真的不是靠一个课程能搞定的,需要完整地做几个复杂的项目,并且有资深工程师的思路和代码,可以参考和借鉴,这样才能高效,系统地掌握。

每个功能模块都设计好以后,最后还需要有一个协调者。

类似于人的大脑,去协调手、脚、眼睛、耳朵、嘴巴。

这个大脑,一般就是程序的'地基',类似于RTOS,就是'协调者'身份,负责调度协调整个项目的各个功能模块。

RTOS本质也是一种程序架构,但是我很少用,因为它的处境,其实很尴尬。

没那么复杂的项目,上RTOS并没有优势,反而为后期调试带来不必要的麻烦,如果对系统不熟悉,就像埋了一个定时炸弹,可能会跑一段时间后死机的现象。

复杂的项目,有些直接上Linux了,现在很多***,成本也能做得很低。

所以,现在rtos的应用,我觉得主要集中在中等复杂的项目,要求实时性很高,同时工程师,又不具备设计程序架构的能力时。

不过,至今为止,我基本是用自己设计的架构去替代RTOS,目前大多数产品都够用。

a82623c4-7f7a-11ee-939d-92fbcf53809c.png

a83861e2-7f7a-11ee-939d-92fbcf53809c.png

这个架构,我也录了套系统的教程,粉丝可以找我拿去参考学习。

a843832e-7f7a-11ee-939d-92fbcf53809c.jpg


关键字:单片机  STM32 引用地址:关于单片机STM32裸机程序架构设计

上一篇:在RT-Thread studio中为STM32系列开启DSP支持
下一篇:STM32VCT6FSMC驱动3.5寸IPS全视角液晶屏

推荐阅读最新更新时间:2024-11-17 15:59

STM32系统结构、时钟树
AHB : AHB:Advanced High-performance Bus AHB和和和和APB这两种总线所连的外设是有区别的这两种总线所连的外设是有区别的这两种总线所连的外设是有区别的这两种总线所连的外设是有区别的。AHB总线连总线连总线连总线连接高速外设接高速外设接高速外设接高速外设,低速外设则通过低速外设则通过低速外设则通过低速外设则通过APB总线互连总线互连总线互连总线互连。 APB: APB(Advanced Peripheral Bus),外围总线的意思。该总线协议是ARM公司提出的AMBA总线结构之一,几乎已成为一种标准的片上总线结构。 FSMC: Flexible Static Memory Controlle
[单片机]
<font color='red'>STM32</font>系统结构、时钟树
12.STC15W408AS单片机比较器
一、比较器内部结构 STC15W408AS单片机内置比较器功能。的比较器内部规划如下图所示: 比较器正极输入端CMP+电平可以与比较器负极输入端CMP-的电平进行比较,也可以与内部BandGap参考电压(1.27V附近)进行比较。 二、STC15W系列与比较器相关的特殊功能寄存器 2.1 比较器控制寄存器1:CMPCR1 CMPCR1 : 比较器控制寄存器1 CMPEN:比较器模块使能位 CMPEN=1,使能比较器模块; CMPEN=0,禁用比较器模块, 比较器的电源关闭。 在 CMPEN为1的情况下: 当比较器的比较结果由LOW变成HIGH时, 若是PIE被设置成1, 那么内建的某
[单片机]
12.STC15W408AS<font color='red'>单片机</font>比较器
STM32生态系统—SBSFU原理介绍
安全启动,构建信任链 安全启动,作为信任根 安全启动,和用户应用一样,都是一段代码,放在片上的用户闪存中 复位后运行的代码只能是这段“安全启动” 这段“安全启动”代码,由用户开发,设备出厂后不能再修改 安全启动,如何认证下一阶段代码 “安全启动”代码,检查应用代码的签名,核实(广义的) “message integrity” 消息认证 安全启动,如何认证下一阶段代码 “安全启动”代码,检查应用代码的签名,核实(广义的) “message integrity” 签名以应用代码元数据//Meta data的形式提供 签名//元数据 是如何生成的 签名//元数据 是如何被校验的 安全固件更新
[单片机]
<font color='red'>STM32</font>生态系统—SBSFU原理介绍
51单片机实现scanf和printf函数
最开始学习C语言时,使用printf和scanf进行格式化输入输出十分方便。 学习单片机有很长时间了,之前要再屏幕上显示一个变量或者通过串口传出一些变量值观测的话,需要进行一系列的取余取整运算,很是麻烦。 最近又研究了一下keil中针对printf和scanf的实现机理,做了一些改动,实现了标准格式化输入输出,共大家参考。 1.printf函数在格式化输出时,向下调用了char putchar(char c);这个函数,在 stdio.h 里可以发现有这个函数,所以我们需要自己构造一个这样的函数,即通过串口putchar(),代码如下: char putchar(char c) { hal_uart_putchar(
[单片机]
STM32全局变量占用程序存储空间吗
全局变量是否占用最终程序的存储空间,这个问题其实早在我们学习C语言的时候就已经告诉我们答案了。我隐约记得初学C语言的时候,书本上告诉我们: 全局自动变量 保存在读写数据段 全局静态变量 保存在读写数据段 全局常量 保存在只读数据段 局部自动变量 保存在栈空间里的 而我们在做单片机程序的时候,由于都是用的C编程,所以数据的存储也是一样的。上面的读写数据段在单片机里就是RW-data段,上面的只读数据段在单片机里就是RO-data,还有一个零初始化数据段ZI-data段(由此可见,RW-data加上ZI-data就是总共要分配的RAM空间大小),最后一个Code段就不用介绍了,大家都明白。 那么究竟一个STM32程序编译链接完
[单片机]
<font color='red'>STM32</font>全局变量占用<font color='red'>程序</font>存储空间吗
基于PPP协议单片机拔号上网的设计与实现
    摘要: 通过对TCP/IP协议簇进行简化,讨论数据包的配置,设计并实现单片机拔号上网的系统。     关键词: 单片机 协议 TCP/IP 数据包 引言 20世纪90年代,以因特网为代表的计算机网络通信技术的发展和应用取得了前所未有的突破和成功,单片机上网技术在生活和现代建设的各方面的应用和研究随之成为当今一个热门话题。8位、16位单睡机的因为其较好的性价比,在测控领域仍然占据着重要地址。这些单片机的RAM、ROM一般都很小,而网络协议通常嵌入在操作系统中,无法把庞大的操作系统直接安装在这样的单片机中。所以, 要实现上述单片机通过拔号直接连上因特网,需要考虑的主要技术就是如何在单片机上嵌入能
[应用]
如何使用单片机制作一个手动计数器
1.实验任务 利用AT89S51单片机来制作一个手动计数器,在AT89S51单片机的P3.7管脚接一个轻触开关,作为手动计数的按钮,用单片机的P2.0-P2.7接一个共阴数码管,作为00-99计数的个位数显示,用单片机的P0.0-P0.7接一个共阴数码管,作为00-99计数的十位数显示;硬件电路图如图19所示。 2.电路原理图 图4.10.1 3.系统板上硬件连线 (1. 把“单片机系统”区域中的P0.0/AD0-P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:P0.0/AD0对应着a,P0.1/AD1对应着b,……,P0.7/AD7对应着h。 (2. 把“单片机系统”区域中的
[单片机]
如何使用<font color='red'>单片机</font>制作一个手动计数器
GD32单片机的工作原理和内部结构 GD32单片机怎么烧写程序
GD32单片机是一种基于ARM Cortex-M3核心的嵌入式处理器,由国内芯片厂商GigaDevice公司开发和生产。它是一种高性能、低功耗、成本合理的微控制器,广泛应用于智能家居、智能穿戴、消费电子、汽车电子、电力电子、医疗设备等领域。 GD32单片机在工作原理上与其他单片机基本相同,主要包括外设控制器、CPU核心、内存、时钟、复位电路等部分组成。不同的是,GD32单片机采用了ARM Cortex-M3的高性能处理器,拥有更高的运算速度和更强的计算能力,同时具备低功耗、低噪声、高可靠性等特点。 GD32单片机的内部结构主要包括CPU核心、中断控制器、系统控制器、时钟控制器、Flash存储器、SRAM存储器、DMA控制器
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved