前言:前段时间分享的文章【单片机裸机代码框架设计思路】,很多读者给我留言,觉得很不错,对于初学者而言,这是一个进阶的技巧,对于我而言,这是对自己总结和表达能力的一个提升。

本文章我们再谈谈单片机代码的模块化设计思想是如何设计的。之前的【单片机裸机代码框架设计思路】文章为了尽量简洁的表达,我几乎所有代码都放在了main.c中,这个在实际项目中,或者说当任务比较多的时候,几乎是不太现实的。

模块化设计的目的是让代码高内聚,低耦合,是为了降低程序复杂度,使程序设计、调试和维护等操作简单化

第一点:单独的功能模块各自独立建立xxx.c和xxx.h文件

这一点相信大家可能都知道,因为51单片机的书都有讲,如果您已经知道了,请跳过第一点。

下面以之前的文章单片机裸机代码为例进行说明:如下图所示

我把功能代码分成了4大块:

  • 定时器功能代码:timer0.c、timer0.h
  • Task裸机框架功能代码:task.c、task.h
  • 中断函数功能代码:interrupt.c、interrupt.h(任务很少,也可以不分出来,看具体情况)
  • 公共函数功能代码:public.c、public.h(存放一些公共的函数和全局变量)

(1)定时器功能代码:timer0.c、timer0.h

可以看出:timer0.c包含了3个常用函数,和1个定时器结构体变量,定时器中断是放在interrupt.c里面

timer0.h包含一些常用的宏定义,和结构体变量类型定义,对于常用的2ms/5ms/10ms定义初始值,可以使用宏定义,修改起来就会很方便,如下所示,这是一个小技巧

为什么使用TIMER_VALUE来代替T5ms时,是因为如果不使用这个宏,那么定时器初始化的时候要给TL0/TH0赋值T5ms,在定时器中断函数中还要赋值一次,我需要改动两个地方,中断赋值很容易被忽略掉,所以使用TIMER_VALUE宏定义代码,我就可以只需要改T5ms就可以一次性更改定时器中断的时间。

(2)Task裸机框架功能代码:task.c、task.h

task.c包含裸机代码框架中功能所有代码,心跳函数,初始化任务,启动任务,停止任务还有任务处理函数

task.h代码如下:包含任务的数组定义等等

(3)中断函数功能代码:interrupt.c、interrupt.h

这个范例代码比较简单,只有1个定时器的中断函数,如下所示

(4)公共函数功能代码:public.c、public.h

存放公共函数,比如禁止总中断,使能总中断,软件延时函数等等

要特别提到的一点,这是一个小技巧:public.h包含所有外设的头文件和常用的C语言库头文件,这样做的好处是,只需要修改这一个地方,其余.c文件只需要包含一条include "public.h"就可以了。

第二点:结构化封装外设

这个才是本文章我想提到的重点,对于一般初学者而言,可能写的最多的就是Timer0_Init(); 然后和Timer0_ISR() 函数,然后main.c调用就完事了。这种写法的确简单,也好理解,但是如果你的外设特别多,如果还有ADC,传感器,等等,你需要定义全局变量传递参数时,外设越多,那么全局变量就越多,后续修改起来,你就会发现太痛苦了,能把功能实现就不错了。

我们现在把定时器0就当做一个外设,

[1]、在外设对应头文件中,比如timer0.h中,声明一个结构体变量类型,如下图图所示,里面包含了3个函数指针,也可以在结构体中定义变量,比如浮点数,比如数组等等。不过定时器用不着。这里就只有函数指针了。

[2]、在外设对应的源文件中,比如timer0.c中,定义一个Timer0_t类型的结构体变量,并同时赋值,注意顺序不能错,因为前面定义的是函数指针,所以我们只需要用对应的函数名称赋值就好,这种做法,也可以称呼为注册回调函数.这些回调函数因为是通过结构体变量来调用,所以前面请加static修饰,表示只能在本文件中使用,如果是其他文件要使用,请直接通过结构体变量来调用,这就达到了封装的目的。

很多人不明白回调函数,这里简单提一下,将函数名称作为参数传递给函数指针,通过函数指针来调用该函数的功能,赋值的过程,就是注册回调函数.如果不注册,那么函数指针为null,指向空地址,就会出问题,我们定义的这个函数就是回调函数。

[3]、在外设对应头文件中,请一定写上 externTimer0_t timer0,表示外部文件可以调用 timer0结构体。

[4]、如果需要调用定时器的这些函数,只需要通过timer0结构来调用,如下所示,timer0.Init(TIMER_VALUE),

另外,VS Code的智能补全非常棒,你只需要输入结构体变量timer0.里面的函数或变量全部都出来了,如果这样封装,那么编辑代码体验也很棒。

根据结构体封装的思想,我再多举两个例子,假如对DHT11温湿度传感器进行封装,封装哪些会比较合理呢?如下所示

计算的湿度和温度浮点数,必不可少。

单总线40bits源数据,根据实际需求,如果你是和上位机通信,也必须发送这个源数据,那么就封装在这里,如果不需要,可以不封装。

读取湿度和温度的函数必须要封装.

调用的时候,就可以通过如下方式,通过串口打印出源数据和计算后的温湿度数据

喜欢这篇文章,帮忙点个“关注 + 收藏”哦,谢谢

本文章的例子是基于STC89C52单片机来调试的,想获取源码,请“”关注 + 收藏“后,私信给我,发送文字 [单片机代码模块化设计思想浅谈]。

单片机sleep函数的头文件_单片机代码模块化设计思想浅谈相关推荐

  1. 单片机sleep函数的头文件_单片机学习day8—单片机IO扩展

    74HC165芯片-并转串 74HC165中文资料.pdf 267.6K · 百度网盘 8位移位寄存器(并行输入,互补串行输出) 时钟输入端 CLK,CLK INK (上升沿有效) A-H 并行数据输 ...

  2. 单片机sleep函数的头文件_单片机空项目代码解析

    头文件▲▲▲这个是头文件,后面需要调用的东西都在里面,下面两个头文件只要是51单片机都可以使用,写的时候随便选一个就可以了. #include #include main函数▲▲▲main为程序的启动 ...

  3. 单片机sleep函数的头文件_C语言中的sleep() 函数

    展开全部 关于sleep()函数在windows系统和linux系统下是两个不同的函数,差别较大,但功能是相同的,都是将进程挂起e68a8462616964757a686964616f31333337 ...

  4. 单片机sleep函数的头文件_c语言的 sleep函数到底在哪个头文件里啊

    展开全部 在里面. 在VC中使用时,sleep函数的头文件为windows.h,在Linux下,gcc编译器中,使用的头文件因gcc版本62616964757a686964616fe59b9ee7ad ...

  5. 单片机sleep函数的头文件_C语言之Sleep函数

    Sleep函数: 功 能: 执行挂起一段时间 用 法: unsigned sleep(unsigned seconds); 注意: 在VC中使用带上头文件#include ,在Linux下,gcc编译 ...

  6. 延时函数、数码管显示头文件(单片机)

    延时函数.数码管显示头文件(单片机) 在单片机程序的编写过程中,我们常常要写一段相同的代码,此时我们可以给它做成头文件封装起来,在使用的时候直接调用,在此文章中以常用的延时函数和数码管显示函数为例 数 ...

  7. STC15F2K60S2单片机入门:编写头文件

    单片机入门:编写头文件 引言 具体操作 引言 软件知识小白,分享单片机入门的一些经验知识 问题描述 在STC15F2K60S2单片机开发使用过程中,常常会遇到使用单片机多种模块的情况.比如,同时使用D ...

  8. 【Android 内存优化】libjpeg-turbo 函数库交叉编译与使用 ( 交叉编译脚本编写 | 函数库头文件拷贝 | 构建脚本配置 | Android Studio 测试函数库 )

    文章目录 一.交叉编译 Shell 脚本参考 二.NDK r16b 版本配置 三.libjpeg-turbo 交叉编译 Shell 脚本 四.执行 libjpeg-turbo 交叉编译 Shell 脚 ...

  9. c++万能头文件_初学Python,与C对比

    ✎背景学了一学年的C的基础,下学年开课Python,现在正在自学中...C也不是不学了,而是之前买了一本<C++Primer>在学校里,就准备先学一下Python,下学期利用自由时间接着学 ...

最新文章

  1. github 思维导图开元软件_画思维导图记笔记的工具软件
  2. Git的多人协作和分支处理测试
  3. 前端学习(1648):前端系列实战课程之任务功能清单思路
  4. 读《财务自由之路》教会我的道理
  5. 报错注入是什么?一看你就明白了。报错注入原理+步骤+实战案例
  6. 第四章:Django模型——添加 Event发布会的表 报错
  7. href 和 src 区别
  8. Java中类与对象的定义与使用
  9. 机器学习中的数据不平衡解决方案大全
  10. 我的Verilog HDL学习历程(二) 组合逻辑电路的一个实例:基于EGO1板子
  11. 计算机应用bsp什么意思,bsp文件是什么?bsp文件怎么打开?
  12. OpenCv图像处理之颜色通道分离与多通道融合、图像线性融合
  13. 示波器的带宽、带宽检定方法
  14. Axure RP 10怎么卸载干净,Axure RP 10怎么在注册表卸载清除
  15. ESN学习笔记——echotorch(1)介绍
  16. 2021-2027全球与中国双断面隔离器市场现状及未来发展趋势
  17. java 吸血鬼数字_java编程思想之吸血鬼数字
  18. Windows与网络基础:Windows基本命令-目录文件操作
  19. 用java画一个小猪佩奇_python 画个小猪佩奇
  20. 通过Spire-java实现word和pdf文件相互转换

热门文章

  1. 快速提示:使用Chrome开发工具调试GWT应用程序
  2. c#编译时提高兼容性_幻像类型提高了编译时的安全性
  3. 在AWS中设置Cassandra集群
  4. Eclipse MicroProfile:您需要了解的5件事
  5. 琥珀项目:较小的,面向生产力的Java语言功能
  6. Java中使用ArrayList的10个示例–教程
  7. 使用Selenide进行有效的UI测试
  8. Spring 3使用JUnit 4进行测试– ContextConfiguration和AbstractTransactionalJUnit4SpringContextTests...
  9. 初始化懒惰关系以及何时使用它们的5种方法
  10. 大型布线:Java云应用程序缺少的技术