前言

       该内容是工作一年来通过上网或其他方式不断搜索、实践、总结出来的嵌入式软件开发经验(本文仅适用于单片机的裸机开发),希望能帮到正在学习这方面的朋友,如有不好的地方,请多多见谅。

在嵌入式软件开发过程中,在程序架构的搭建完成之后,为了提高项目代码的可读性和可维护性等,应对程序代码分层。


分层介绍

硬件抽象层(Hardware Abstract Layer)      

       嵌入式开发的核心就是芯片,它提供固定的片内资源(常用的有I/O,ISR,TIMER等,稍微好点的还有ADC,SPI等硬件资源,不需要芯片外围ADC采集芯片或模拟SPI)共开发者使用。而且它具有一个很重要的特点就是,不随项目的新增需求变动而变动。所以应将其作为最底层,为上层提供基础支持。

       大部分情况下该层都会有芯片厂商提供相应的库函数包或者配置工具生成对应API函数,基本只要知道如何配置和使用就行,当然,也有可能存在芯片厂商提供的库函数包或配置工具配置/使用自由度不高,需要自己查看芯片寄存器手册增加自己需要的API函数。

硬件驱动层(Hardware Driver Layer)     

        嵌入式开发基本都会使用片外资源,如AT24C02,W25Q128等常见的外围EEPROM芯片,需要SPI通信(硬件SPI或I/O模拟的SPI)发送相应指令驱动该芯片,实现该芯片能正常工作。因此驱动这部分的API函数实现程序即为硬件驱动层。即使换了MCU,也只需将调用过硬件抽象层的API函数替换即可。

功能模块层(Functional Module Layer)

        硬件抽象层和驱动层主要就是为功能模块层提供的,实现该项目需要的功能,比如KEY、LED和EEPROM等功能,其中LEY、LED基本调用硬件抽象层的API函数(更复杂的可能通过片外芯片获取/控制等,因此可能也需要使用硬件驱动层),EEPROM调用硬件驱动层的API函数,即使EEPROM芯片更换(AT24C02或W25Q128等),也不影响EEPROM之前编写含的功能代码程序(前提是AT24C02,W25Q128提供的API函数提供的是统一标准)。

应用程序层(Application Layer)

        应用程序层主要负责的就是功能模块的使用和之间的逻辑关系处理等等,比如用户交互界面应用程序可能需要按键(KEY)、指示灯(LED)、显示屏(LCD)等,实现一系列的人机交互功能,通常应用程序层相对于功能模块层而言独立性较低。

        一般情况下也可细分出应用业务层,但是对于单片机产品来说,这一层的必要性反而不高,分层太多,反而显得臃肿。


总结

硬件抽象层和硬件驱动层的主要区别

        硬件抽象层使用的芯片内本身的资源(芯片手册都有介绍),而硬件驱动层使用的是芯片本身不存在的资源,而且需要编写相应代码才能实现的资源。

        比如正点原子STM32中CAN使用的TJA1050芯片,CAN属于STM32的片内资源,TJA1050属于片外资源,但由于TJA1050不需要额外的代码就能通过STM32中CAN本身提供API函数正常 工作;因此可以认为TJA1050不属于硬件驱动层,而若使用TJA1041,则需要编写额外代码才能使正常工作才能使STM32中CAN本身提供API函数正常工作,因此可以将TJA1041归为硬件驱动层。

        若不要分这么细,可以将硬件抽象层和硬件驱动层统一归为硬件抽象层。

嵌入式分层程序架构 嵌入式软件分层设计_功能模块

         

嵌入式分层程序架构 嵌入式软件分层设计_硬件驱动_02

功能模块层和硬件抽象层、硬件驱动层的主要区别

       功能模块层是按照项目需求提取出来的功能,需要硬件抽象层和硬件驱动层的硬件支持才能实现,功能模块层根据项目的功能需求改变而改变,而硬件抽象层和硬件驱动层则是项目需求书中的功耗等硬件相关的需求变动而改变,当然,若子功能的增加而硬件不支持,则也需更换硬件驱动。

        比如项目中的数据储存功能,硬件支持有AT24C02、W25Q128和芯片本身的FLASH,都可以支持数据储存功能,即使后期因为功耗或节约成本等问题,硬件的更换也不影响数据储存功能的实现(前提规划好标准规范的API函数定义)且避免了重写该功能代码所带来的各种问题,保证了该功能的稳定性。


分层结构示意图

嵌入式分层程序架构 嵌入式软件分层设计_硬件驱动_03


下篇:嵌入式软件开发之模块化程序设计(三)