电子产业一站式赋能平台

PCB联盟网

搜索
查看: 380|回复: 0
收起左侧

嵌入式软件为啥要进行模块化设计?

[复制链接]

570

主题

570

帖子

4308

积分

四级会员

Rank: 4

积分
4308
发表于 2024-7-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
$ d+ I+ T' Q/ o关注我,一起变得更加优秀!8 T- p! d  e2 B7 y5 y7 {' k
在如今的嵌入式软硬件技术开发领域,几乎每一位工程师都会大谈模块化设计,硬件工程师在设计原理图的时候,电源要模块化,核心板要模块化,功能电路要模块化。软件工程师在coding的时候,CPU初始化要模块化,IIC代码要模块化,RTC代码要模块化,等等。
7 R6 w$ E, Z6 V* T; o/ Q. M于是,当大家对模块化设计的概念和思想有了普遍共识后,我们在写单片机代码的时候,(大多数工程师极有可能)是以下面这种代码形式去组织产品的功能模块代码。
3 l) j3 [. @- F% R
  • void main(void){    gpio_init();    //初始化GPIO    iic_init();    //初始化IIC总线    rtc_init();    //初始化RTC        while(1)    {        function_code_1();    //功能代码1        function_code_2();    //功能代码2        function_code_3();    //功能代码3    }}+ h  Y; f# \/ N/ _# Q) z: @
    这看上去似乎是非常合情合理合逻辑的,先把需要用到的硬件接口都初始化完成,然后在 while(1) 循环里面不断地轮询,处理我们的业务逻辑。
    * W  k, L! c& Z9 _- _' w" A! Y0 ?. B( Q! w关于源代码文件的存放,可能是 iic.c 和 iic.h ,gpio.c 和 gpio.h 都放在MCU的外设驱动文件夹,功能模块源代码放在另一个文件夹。  " o. o" U: ?. n1 C/ d! w
    (几乎所有的单片机入门教程都是这么教我们的,外设驱动放一块,业务逻辑放一块,这看上去很模块化呀,没啥毛病~)" N) ?- j. [; E1 X1 i
    然而,当我们对这个世界的客观事物理解越来越深刻的时候,才发现这个世界的大多数事物,都是以“模块”的形式存在着。' ^, J$ p, B0 e
    我是一个模块(职场吗喽),给公司当牛马;公司是一个模块,给行业提供解决方案或产品;行业是一个模块,给产业链提供完善的行业支持;产业链是一个模块,给社会主义经济建设提供可靠的资源支撑;社会主义是。。。6 t, t$ l0 E1 ]
    扯远了:)
    2 {( r1 m1 N! J9 E9 ~4 o* y3 y

    c0nkuduu5wf6401463538.png

    c0nkuduu5wf6401463538.png

    + a- V; @' R  B' R5 x于是,我们上面的单片机伪代码,比如它是一个给广州塔按时点亮流水灯的控制器产品,用模块化的思想就可以优化为以下的形式;4 Q( c* ^7 `7 F: S# D# _
  • void main(void){    light_module_init();    //灯光模块,里面包含GPIO接口初始化    storage_module_init();  //存储模块,里面包含IIC初始化,存储设备初始化    clock_module_init();    //时钟模块,里面包含RTC额初始化。        while(1)    {        light_module.handler();  //处理灯光模块的逻辑,比如定时点灯        storage_module.handler();  //处理存储器逻辑,比如定时保存配置数据        clock_module.handler();    //处理时钟或闹钟,比如发出定时或计时信号    }}
    4 \8 [2 f0 m  ~) [从以上代码可以看出,我们把MCU外设驱动的初始化,放在模块的初始化函数里面进行处理了,主循环while(1)里面也是调用了模块提供的事务处理函数。各个模块分工明确,只扫自家门前雪,不管他人瓦上霜。2 \+ R! n$ P. d7 H
    模块之间可以通过约定的接口进行数据的交互和通信,并且严格禁止跨模块使用全局变量,模块的接口头文件禁止放入 “extern xxx变量” 的代码,一旦放入这种代码,大概率是会被下一位接坑者“友好问候”的 。
    & B- n5 A" z! a9 c2 R, z* k6 P- b% \模块化之后,事情一下子变得简单起来了,当我们发现塔上的灯不亮了,就去检查一下 light_module 和电源总闸呗,当我们发现定时时间不准了,就去检查一下时钟模块呗。怀疑硬件驱动有问题的,就去看看 xxx_module_init 的代码,怀疑业务逻辑的,就去看看 xxx_module_handler 代码。- Y4 d+ E2 S$ y" e- {1 P
    模块化设计是嵌入式系统设计中的一种重要方法论,但通常这种方法论描述得过于抽象,难以理解,以下是模块化设计的核心哲学思想,我们可以尝试通俗地理解这些思想背后的目标。
    4 J6 H# z% o  E4 Y1、高内聚、低耦合、接口明确5 [1 d7 m5 y2 C# ?8 c1 k
    模块内部的各个变量各个函数,都给咱统一管理起来,不对外的函数要static,不想让模块使用者知道的内容,就不要放在接口头文件,对外接口要规范,提供明确的接口使用指导。2 ?& G6 y& }, w2 j5 v& d; p
    2、可重用性、可扩展性、可维护性  P; }! f; _0 B# P! x7 W6 f0 i
    模块源码被使用时,可以轻松复制粘贴,模块使用者只需遵循接口规范,通过正确的输入即可获得正确的输出。模块作者给模块扩展功能时,不需要重写所有代码。模块设计者在维护模块某个功能时,只需专注某个局部,而不是模块全局。# b4 ]/ N  y( O4 g5 E. ?( x) c- W$ d
    3、单一职责原则8 S1 F1 O3 {. T1 l
    一个模块只负责一项任务(或者一项功能),其他不属于自己分内的事情,就别管了(也管不了),各家只扫门前雪就行了!1 ]( \3 [" C+ i1 Q4 W
    4、分层架构、配置管理8 C$ J6 f) v/ x/ K7 A( L- @
    模块化的内在设计可以采用分层架构,每一层负责处理不同的抽象级别。也就是说,模块内部之间也要有层次感,模块内部也不是一锅乱炖的东西,最起码的层次阶级还是要有的,并且还要提供适当的配置文件(或数据结构)来控制模块的功能与行为。
      w2 o, R; w- z+ a2 S5、测试与验证/ e! }# x" O" I
    哪里出问题了,直接找出问题的模块就行,电源出问题了,一开始该不会去怀疑网络通信不了而导致电源出问题吧?!模块化设计的软件,使得对单个模块进行测试验证或者找问题变得更加容易,有助于提高软件整体质量。* c6 T1 E6 t4 T
    通过遵循这些设计哲学,嵌入式软件的开发可以更加高效,最后,需要补充的一点就是,如果产品的功能逻辑肉眼可见的简单,就不用扯啥模块化了,用最直接简单粗暴的方式来操作硬件,完成功能开发,怎么方便怎么来,别整啥模块化给自己制造麻烦了。9 x, v7 R+ X4 x* m9 O$ r4 T
    模块化思想,是适用于对中大型的产品业务软件进行规划设计的,并不具备普适性用途,也不是放之四海而皆准的真理,工程师们还是需要具体问题具体分析,按需使用。+ h, c/ O& ]1 w2 T2 z
    -END-
    - _  P7 w5 l8 p5 ^: |. K; |往期推荐:点击图片即可跳转阅读: p8 F' E- m' u
    1 Y' y. _  z) P4 A& F* s
                                                            6 W+ L( @) z0 U- d* [8 L; F8 J
                                                                    * j: x9 V0 Z: y: v8 p* ~) b
                                                                           
    ( s2 M7 c' c7 B8 U4 ]                                                                                6 A" L* I- B0 w5 x

    rqp0zla54sk6401463638.jpg

    rqp0zla54sk6401463638.jpg
    4 p5 g  X4 A) R) S/ e2 c
                                                                                    : L2 [4 S! @) T) F9 Z6 ]
                                                                                            嵌入式 C 语言知识点,掩码结构体
    9 [6 `+ w# w* {3 j& U( Z7 g1 k9 m                                                       
    6 `+ u3 n6 _* u! U5 L                                                               
    ! M! }4 y; J2 x. l. H                                                                       
    : G- G2 ~4 b4 z5 I. Z' u9 m: [                                                                                2 P% |) m5 N: i9 I* e" b: {' U# ~

    lhktydbh4ci6401463738.jpg

    lhktydbh4ci6401463738.jpg

    ! I+ p! D3 G9 \7 }, R$ F9 t1 E                                                                                3 q, V4 ^0 Q% p# Q8 e* i$ I
                                                                                            面试官问我,怎样把 1000 TB 文件快速从南京传输到北京?(文末附最佳答案)! x4 D1 X- O& k. C2 U& B  q( q
                                                                   
      P0 R- b5 d3 y9 e5 A( T9 b7 r                                                                       
    ; j: b8 k! x( P9 V& c                                                                                % I, b2 J8 k+ \5 \

    bpkuuybadzw6401463838.jpg

    bpkuuybadzw6401463838.jpg

    " G+ x1 \$ y& O$ w# e# A                                                                               
    ! h: m6 c/ B- H6 _                                                                                        做项目时,嵌入式方案的选型套路有哪些?4 k' _1 m8 m" z% J6 y# n" Z
    我是老温,一名热爱学习的嵌入式工程师
    ! N/ P. ~. k7 A6 S关注我,一起变得更加优秀!
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表