NXP LPC54101 E-Lock 软件框架设计

一、概述

1.1软件框架概述

上次我们分享了 LPC54101 E-Lock 的硬件设计,本次我们分享 LPC54101 E-Lock 系统软件框架设计。如果说硬件是骨骼,那么软件就是肌肉和皮肤,一个稳定的系统,软硬件都需要同样健壮。

常用的嵌入式 MCU 软件框架有三种:前后台顺序执行程序、状态机、操作系统。

(1)前后台顺序执行程序:

这种架构其实属于非常简单的逻辑顺序执行,所谓前台就是在主循环里面判断要处理哪些事务,所谓后台指的是中断,就是指不用刻意判断该做什么,系统会自动进入设置好的中断状态。

这种设计方式比较简单,按照业务逻辑顺序写就可以,一般用于测试驱动或者编写业务逻辑比较简单的状况,当业务逻辑趋于复杂,就不太适合用这种方式了,业务逻辑增加的同时,对于工程师来说容易混乱,也不利于以后的扩展和维护。


(2)状态机:

无论是根据定时器状态还是任务状态,只要是根据状态标志,从一种状态进入另外一种状态,如图 1.1 所示,用闹钟来举例。很多书籍中很多时候都是与操作系统一起出现,也就是说很多时候是操作系统中使用了这一方法。不过我们这里要说的这个状态机并不是挂在操作系统下,而是在前后台程序中使用此法。

 
图 1.1 状态机示意图

(3)操作系统:

常见的 MCU 操作系统有:Free RTOS、uC/OS、RT-Thread 等等,各个操作系统有各自的优缺点。

操作系统的本身是一个比较复杂的东西,任务的管理,执行本身并不需要我们去了解。但是单单是移植都是一件非常困难的事,虽然有人说过“你如果使用过系统,将不会在去使用前后台程序”。但是真正能使用操作系统的人并不多,不仅是因为系统的使用本身很复杂,而且有些跑在 MCU 上的操作系统还需要购买许可证。

1.2 E-Lock 软件框架选择

对于 E-Lock 应用,需要多个传感器,有中断,也有低功耗等需要考虑,整个项目还是比较复杂,所以前后台的顺序执行这种架构我们不考虑。那么状态机和操作系统,如何做选择呢,我们是单芯片的 E-Lock 方案,也就是指纹识别算法需要跑在 LPC54101 上,这会消耗比较多的 RAM,另外指纹存储也会存在 LPC54101,而且需要存 100 枚,这会消耗比较大的 Flash 空间,由于操作系统本身就会占用一定的 RAM、Flash 空间,所以我们也不考虑操作系统这个架构。

因此我们本次分享的 LPC54101 E-Lock 软件框架采用了状态机模式,能适应比较复杂的逻辑,资源占用量又相对较少。

 二、系统子任务设计框架

模块化、子系统化有助于协调团队中许多人的并行工作,管理项目各个部分之间的相互依赖关系,并使设计人员、系统集成人员能够以可靠的方式组装复杂的系统。 具体来说,它可以帮助设计人员实现和管理复杂性。 随着应用程序的大小和功能的增长,需要模块化才能将它们分成单独的部分(无论是作为“组件”,“模块”还是“子系统”)。 然后,每个这样分离的部分就成为模块化体系结构的一个元素。 这样,可以使用定义明确的界面隔离和访问每个组件。 此外,模块化编程可提高固件的可读性,同时简化固件的调试,测试和维护。

即便是一个人独立开发一个项目,这样做依然在代码的调试、可读性、可移植性方面是最佳实践的整体策略。如果代码设计良好,则在其他项目可以轻松应用。而且模块经过上一项目的测试验证,在新的项目中再次应用其缺陷风险将大幅降低。所以每做一个项目,以这种策略不断积累模块"轮子"组件,随着经验的增长,积累的“轮子”就越来越多,也越来越好。所以其优点是显而易见的,否则每做一个项目,都从轮子造起,开发时间长不说,开发水平也得不到提高,重复性工作也很枯燥。

2.1 软件架构图

 
图 2.1 LPC54101 E-Lock 软件架构框图

如图 2.1 所示,LPC54101 E-Lock 软件框架包含:驱动层,中间层,应用层。我们的状态机框架是应用层中使用。驱动层、中间的模块层,都是最终为了应用层所准备的,设计的目的是实现高内聚、低耦合,分清楚各个模块,当更换 MCU 时候,有时候仅仅需要替换驱动层,这样大大减少开发时间,提高开发效率,同时可维护性也变高。

 

2.2 驱动层

一款 MCU 底层开发一般指利用单片机的固有资源完成的控制功能的软硬件开发,比如时钟、UART、SPI、I2C、CAN、IR、定时器、AD 转换、GPIO、LED 和 LCD 显示等。我们需要根据时钟树图,观察初始化时钟时需要用到哪些寄存器及各种外设需要的时钟源。

(1)当 MCU 内部有几种不同的时钟源时,必须配置相应的寄存器配置需要的时钟源,如果不进行配置,将会使用单片机上电默认的时钟源。

(2)时钟源决定着系统的工作频率、定时器定时时间和通信时的波特率。

(3)定时器分频是为了获得更长的定时时间,如果采用标志位累加的方式来延长定时时间,将会消耗 MCU 的 RAM 资源,在低端 MCU 中,由于 RAM 资源非常珍贵,因此只能采用定时器分频来延长定时时间。

 

2.3 中间层

驱动层只对寄存器的数值进行操作并封装成简单的 API,完成相对单一的功能,比如配置 UART 的起始位、校验位、波特率等。中间层有时候也成为硬件抽象层,这一层封装出来的 API 就脱离了具体的 MCU 硬件,具备了为应用层提供“驱动”的功能,例如 FP API 是指纹识别的 API,通过调用这些 API 可以完成指纹存储、识别等功能。

 

2.4 应用层

应用层就不得不说到状态机,状态机做为软件编程的主要架构已经在各种语言中应用,在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。灵活的应用状态机不仅是程序更高效,而且可读性和扩展性也很好。状态无处不在,状态中有状态,只要掌握了这种思维,让它成为您编程中的一种习惯,相信您会受益匪浅。

  状态机可归纳为 4 个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果联系的考虑。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:

  (1)现态:是指当前所处的状态。

  (2)条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。

  (3)动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

  (4)次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。



三、软件框架设计注意事项

3.1 任务拆分

做工程开发,一定是需求驱动的。第一件事需要对需求有比较清晰的认知,然后才能设计一个比较合理的框架。我们需要实现什么?大体思路如图 3.1 所示。另外还需要思考这个项目要实现什么主要功能?这个来自哪里?如果是实际产品开发,则可能来自市场的需求,如果是自己的练手项目,也一定会给出一个大致的想法。总之不管源自何方,需求总要先梳理清楚。那么需求一般意义上包含:

(1)哪些是硬件 IO 接口需求,比如开关量输入,ADC 采样,I2C/SPI 通信等等

(2)哪些是业务逻辑需求,比如要采集一个传感器量数据,控制一个加热装置,那么这是高内聚的需求。

(3)哪些是算法相关的技术需求,比如产品中哪些信号需要滤波处理,哪些需要做频域分析等等。

(4)是否有对外的通信协议需求。

(5)是否有业务数据需要历史存储,或者设备参数需要掉电保存

(6)是否需要有日志打印需求。

结合固件模块原理以及相关指导原则,那么将相关性高的需求,抽象实现在一系列的模块中,在由这一系列模块配合实现某个相关性高的业务需求,再进一步这些模块就变成一个子系统。多个子系统在 main.c 的调度下,协调完成产品的整体功能。

 
图 3.1 任务拆分

 

3.2 应用层如何调度

我们在主循环内判断状态标志,当符合某种状态则进入该状态对应的任务处理函数进行处理,处理完成会生成新的状态标志并推出原任务处理函数,这样循环不断地判断状态,状态不断切换,最终完成整个业务逻辑,如图 3.2 所示。

 
图 3.2 调度流程

3.3 低功耗处理

关于低功耗处理,在设计 E-Lock 软件的时候需要特别注意,这部分我们这篇先不展开,下篇再说。

四、参考文献

(1) NXP 官网:www.nxp.com.cn

(2) LPC5410X Datasheet

(3) MFRC630 Datasheet

(4) 谈谈怎样架构你的单片机程序https://wenku.baidu.com/view/9eea5cd1a58da0116c1749d4.html

(5) https://blog.csdn.net/shan614667793/article/details/85061270

(6) https://zhuanlan.zhihu.com/p/138200091

(7) https://blog.csdn.net/bornpride/java/article/details/87692446

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论