查看原文
其他

【连载】通过"库文件"学单片机驱动编程(2)

bug菌 最后一个bug 2021-01-31

1、简单一聊

    今天周六在家休息,上午看看书,中午简单的推了一下自己的公众号,晚上开始今天写作,可能对于写代码的同志们,夜晚的宁静更是一种兴奋剂吧!下午遇到了非常多在自己领域有自己见解的小伙伴,同时也遇到了一些在努力向上初学者们,大家相互交流真的挺好的,也许这也是我开公众号的一个原因吧!大家给我分享的文章评价还是挺高的,这里非常高兴,我觉得这些都是让我燃烧写作内容的动力。

    作者以共同进步的目标来经营好这个公众号,初学者可以好好看看这些享受作者的每一篇心血,同时各位经验丰富的小伙伴也多跟我提一些比较好的建议,我也会不断的学习加强自己,提高文章质量和水平。好了,不矫情了,开始今天我们的连载文章主题。

2、库编程VS寄存器编程

    大部分学习单片机进入嵌入式的小伙伴们,应该有用过STC89C52芯片也就是我们的51单片机吧。如果学习过STM32的小伙伴们都知道51单片机多大部分驱动外设都是使用的IO进行模拟的,比如说模拟IIC,SPI等等,而我们的STM32把这些功能都是集成到了芯片上成为了一个外设。其实51单片机的大部分编程就是寄存器的编程,如果抛去STM32固件库那么其编程方式和风格几乎和51一样,仅仅是寄存器更加丰富,并且内核更加强大而已。   

    由于51单片机外设寄存器并不多,并且主频不高,所以采用库编程实在是没有必要,而我们STM32由于寄存器非常多并且有些命名还比较晦涩,所有就有了固件库编程。

    固件库说白了就是把所有的驱动都为大家封装成了一个个的函数供大家调用。这样便能够加快我们平时的产品开发,同时让开发者快速上手,同时固件库把应用层驱动层进行了分离,也增强了代码的移植性;不过固件库编程毕竟多了一些东西,编译的程序会相对寄存器大一些,并且程序由于不断的由应用程向驱动层调用也会带来不小的性能损失不过作者觉得如果系统确实在某些模块对时间等要求非常严格可以采用库调用与寄存器使用相结合的方式进行开发,平时一般的项目推荐使用库吧。

3、剖析stm32库的模块设计

    大家应该在学习51单片机就应该学习过模块化设计,可能大部分小伙伴们都会有一些基本的模块化设计吧,比如说我们常说的一个.c和一个.h就封装成一个模块供应用层使用等等,那么我们知道stm32库都是大佬写的,他们怎样来进行程序模块化设计的呢?好了,下面我将带大家分析分析(还是以STM32F4xx_StdPeriph_Driver这个为例):

1)库文件模块化设计构成

    下面是我简单为大家画的一个结构简图:

    1)首先我们打开stm32f4xx.h文件,该文件里面就是stm32所有的寄存器和地址,可以说stm32的核心。我们进行寄存器编程他就是我们主要依赖的文件,那么固件库的其他文件都需要依赖该文件。并且我们在该文件中发现了如下图所以代码,所以我们在以后应用层就只需要包含该头文件即可使用各外设。

   2)然后core_cm4.h中是与编译器和内核相关的寄存器等内容,system_stm32f4xx.h系统时钟配置等,这里不多讲有点复杂。

    3)我们外设的所有头文件都会汇集在这里,如下图,我们可以通过这个文件屏蔽到相应的头文件把一些不用的外设进行剔除

    同样下面我们分别截取了部分外设文件的结构图,我们从下图看到这些文件都是把所有外设分类,并且以.h和.c来进行封装,以后可以借鉴这种结构。

2)分析外设.h和.c如何制作

    这里我们以stm32f4xx_gpio.cstm32f4xx_gpio.h,我们可以打开这个两个文件,因为我们前面介绍了库函数是把所有的寄存器都进行了封装,可以说对用户而言,我们在库的接口中不可能看到寄存器,也就是我们模块化编程中寄存器相当于私有数据等,我们通过封装不会让外界访问,而可以访问的都是通过函数等形式进行开放。

    1)以GPIO为例子,这些都是头文件向外提供的接口函数,我们只需要调用即可。

    2)而函数的相关参数都是通过如下图所示的宏定义枚举供用户原则使用,如果我们传入了非法参数,函数会进行出错判断。

    3).h文件中需要使用预编译符号防止重复包含而导致的编译错误。

3)总结

    好了,上面就是今天的主要内容,大家应该对固件库中的模块设计有一定的概念和框架了吧,下去了可以好好研究,这就是软件上的设计方式,大家以后都可以模仿,后面我会继续挖掘库中值得学习的东西分享给大家。最后再总结一些模块化编程注意的地方:

模块化编程小节:

1).c中实现内部的实现,并隐藏内部的数据,.h实现对外的接口;

2)头文件名和源文件名最好是做成一样;

3)头文件的包含关系要有层次,可以先画关系图再编码;

4)文件在文件夹的位置也要分类一般分为src和inc,不过也有按模块分类的不过那样的话需要在编译器中添加相应路径等等。

    今天的内容就到这里,这里是公众号:“最后一个bug”,感谢大家的关注,大家的分享转发再看是我创作的动力。感谢大家!我们下期

推荐阅读

【连载】通过"库文件"学单片机驱动编程(1)

嵌入式编程之动态接口技术(经验干货)

嵌入式编程之"重构"代码(C语言版本)

嵌入式编程必备之多方法测定程序运行时间(经验篇)

单片机常用程序框架之分时轮询(详注代码)

看门狗你确定会用了?(经验干货满满)

单片机开发之节省内存大法(C语言版本)

一种 “ 超强 ” 队列的C语言实现(附代码)

一文搞定通信协议中CRC校验(附代码)

【连载】嵌入式测试驱动开发(9)

C语言数值常量的“那些事”(细节分析)

向Modbus协议说"So easy!"

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存