发光二极管(LED),是科学物理世界最重要的发明之一,三原色RGB-LED灯有一段经典的发展历史,具体可以在网络上搜索相关资料进行了解,特别是得益于蓝色 LED 灯的发明创造,才能有今天如此缤纷多彩的世界。
扫描关注一起学嵌入式,一起学习,一起成长
本篇文章,我们基于面向对象的设计思想,配合简单工厂设计模式,编写一个单片机通用的LED显示模块。
1、通用的单片机LED显示模块,主要是把LED引脚相关的驱动接口抽象出来,因为不同的LED效果,会有不同的驱动方式,比如MCU引脚电平翻转驱动,PWM驱动,LED芯片驱动,等等,整个模块的源码文件,如下图所示。
2、先看一下led_driver.h文件,在这里文件里面,主要是声明了一个枚举变量,有多少个物理LED灯就有多少个编号,这个编号是操作驱动层的索引值,因此LED_MAX_NUM通常表示物理LED灯珠的总数。
同时还声明了一个颜色值结构体以及一些LED驱动接口,如下图所示。
5、在led_drv_ws2812b.h文件里面,声明了一个led_drv_ws2812b_t结构体里面,这个结构体主要是包含了led_driver_t驱动接口,同时也包含了ws2812b灯珠的某些特定参数,比如亮度参数,颜色值参数,以及对外提供一些必要的操作接口,等等,具体代码如下图所示。
6、在led_drv_ws2812b.c文件里面,主要是对led_driver_t接口的实现,包括MCU驱动引脚的初始化配置,以及ws2812b的时序控制,然后根据这些接口,分别填充led_driver_t结构体里面的各个成员接口,代码如下图所示。
7、在源文件的led_drv_ws2812b_create里面,主要是用上面的函数,填充led_drv_ws2812b结构体对象,记住这个对象,很重要,会被外部的led_module进行调用,具体实现代码如下图所示。
8、完成了LED驱动程序设计后,再来考虑一下LED模块的设计,在led_module.h文件里面,声明一个LED模块结构体,led_module_t,在这个结构体里面,定义了一个led_drv驱动程序接口,并且对外提供了模块初始化接口,模块启动接口,模块状态机处理接口,等等。
同时还提供了一个配置信息结构体,led_module_cfg_t,主要用来对led_module进行参数配置的,具体代码实现如下图所示。
9、在led_module.c文件里面,_init()函数主要是初始化模块的驱动程序接口,_start()函数主要是用来启动状态机,_handler()函数主要是用来进行状态机管理(待完善),然后使用led_module_create()函数,创建一个LED模块实例,具体代码如下图所示。
10、对于led_module_create() 函数主要是对外部接口进行赋值初始化,并且使用简单工厂设计模式,根据应用层不同的配置(通过cfg配置信息判断),从而选择不同的驱动程序,对于应用层来说,其LED驱动接口都是一致的(面向接口编程),这样就可以完全做到“设备”与“驱动”分离,提高程序模块化的内聚程度。
11、在应用层main.c文件,调用led_module的时候,一般先定义一个led_module_cfg配置信息结构体,然后调用led_module_create函数创建一个led模块实例,然后调用init()函数接口对模块进行初始化,随后调用start接口启动模块,最后调用handler()接口,周期调用LED模块的状态机进行处理,代码如下图所示。
12、美中不足的是,目前这个LED显示模块的状态机还在完善当中,现在只是简单地在状态机处理函数_handler()里面翻转LED灯,用来验证驱动接口的可行性,感兴趣的同学可以下载模块源码,对状态机进行完善,或者持续关注该模块的源码仓库。
源码地址(复制到浏览器打开):
https://gitee.com/embediot/led_module
关注【一起学嵌入式】,回复“加群”进技术交流群。
觉得文章不错,点击“分享”、“赞”、“在看” 呗!