图1 带两级任务按钮和部分功能(仿照驾驶舱)的效果
本着分享和开源精神,也为了给往后的参赛学生循规蹈矩的辅导,于是就有了这个实战条记系列。希望自己摸索的过程能给更多的嵌入式学习者一些指引,也为国产嵌入式处理器和国产嵌入式操作系统的推广助一点力。

由于个人能力和精力的限定,再加上龙芯嵌入式的开拓资料十分有限,很多问题没法像STM32那样深入到库文件和寄存器的程度,还希望有见地的网友在这些问题上能给与点评和分享。末了,我想说的是,这个实战条记不是面向0根本的朋友,最少得有龙芯嵌入式裸机的开拓履历,理解RT-Thread操作系统的线程、定时器、旗子暗记量、邮箱等干系知识,知道LVGL图形用户界面开拓的基本套路。
前三篇我们实现了任务1下的三个子任务:1.1的三色闪烁灯、1.2的呼吸灯、1.3的按键掌握无源蜂鸣器,也初步展示了利用线程和定时器进行管理和调度。从这一篇开始,我们切换到任务2,开始数码管各种显示效果。首先,当然从最大略的静态显示开始,按下“子任务2.1”按钮,显示出工位编号,效果如图2所示。
图2 数码管上显示工位号
一、准备工程和文件
如图3所示,我们把上一次全体工程复制另存一份,作为2.0的版本,并在 src 目录下新建两对文件:seg595.c 和 seg595.h(数码管硬件驱动)、task2.c 和 task2.h(任务2中的各项子任务)。当然,别忘了把 .c 文件添加进工程,如图4所示。
图3 准备新工程和新文件
图4 把新的 .c 文件添加进工程
二、数码管电路事理图
数码管电路并未在底板上,而因此扩展板的形式插接到底板上的,如图5所示。在事理图中找到干系的部分(如图6所示),可以创造4位共阴数码管是通过两片74HC595芯片级联来驱动的,这是一款十分常用的串入并出转换芯片。这样一来,只占用了3个GPIO端口,就办理了数码管4位位选和8位段选的驱动问题。
图5 数码管模块以及底板上的插座
图6 数码管事理图
至于74HC595芯片的基本功能,就不在这里占用篇幅去解读了,建议不理解该芯片功能的朋友先大致去看一下芯片手册,这样在阅读驱动代码的时候才有支撑。
三、编写源码
我们把掌握数码管显示的底层逻辑和时序写在 seg595.c 和 seg595.h 中,把任务2的干系线程掌握写在 task2.c 和 task2.h 文件中,顺便再回顾一下图7所示的工程文件和线程的框架示意。当然,主线程所在的 rtt_lvgl_top.c 文件,以及主函数所在的 main.c 文件,也须要针对性的修正。
图7 工程文件和线程的框架
3.1 seg595.h文件源码
如代码清单1所示,该文件里利用带参数的宏来实现595芯片输入真个电平掌握,并宏定义了每个数码管的位选编码。此外,开辟了两个数组:一个是 num_code[10],存放0~9十个数字的段码;内容固定;另一个是 disp_tab[4],存放每个数码管须要显示的内容,由于涉及到跨文件调用,因此用声明为 extern。当然,函数声来日诰日然是少不了的,每个函数的详细定义,请阅读后面的 seg595.c 源码。
代码清单1 seg595.h文件源码
3.2 seg595.c文件源码
该文件紧张是各驱动函数的定义,实在现逻辑已在注释中表示,下面进行了分别呈现:头文件和全局变量部分(代码清单2)、HC595_Init 函数(代码清单3)、HC595_SendData 函数(代码清单4)、HC595_Display 函数(代码清单5)。
代码清单2 seg595.c源码(头文件与全局变量)
代码清单3 seg595.c源码(HC595_Init函数)
代码清单4 seg595.c源码(HC595_SendData函数)
代码清单5 seg595.c源码(HC595_Display函数)
3.3 task2.h文件源码
这个头文件跟之前的 task1.h 是类似的,我们把任务2子线程 task2_thread 声明为全体工程的全局变量,其余便是声明一下创建和启动该线程的函数,如代码清单6所示。
代码清单6 task2.h文件源码
3.4 task2.c文件源码
该文件的源码较多,新加入的子线程都在该文件中,下面将按功能块的划分依次贴出:头文件部分(代码清单7)、数码管显示定时器部分(代码清单8)、任务2子线程部分(代码清单9)。
代码清单7 task2.c源码(头文件部分)
代码清单8 task2.c源码(数码管显示定时器部分)
代码清单9 task2.c源码(任务2子线程部分)
3.5 rtt_lvgl_top.c源码修正
首先,肯定是须要在该文件中补充任务2的头文件,如代码清单10所示。
代码清单10 rtt_lvgl_top.c源码(补充的头文件)
其次,对主按钮事宜回调函数 mbtnm_event_cb 进行了修正,表示在任务切换的逻辑上。如代码清单11所示,若是从任务1切换至任务2,那么先结束任务1子线程,再启动任务2子线程,如果添加了任务3、任务4......也是同样的切换逻辑。这样设计的缘故原由便是考虑到后续随着任务数量的增加,若没有结束前面任务的机制,会让子任务的实行变得卡顿乃至内存溢出。
代码清单11 rtt_lvgl_top.c源码(修正后的mbtnm_event_cb函数)
3.5 main.c源码修正
该文件里补充数码管的头文件和初始化即可,如代码清单12所示。
代码清单12 main.c源码(补充数码管头文件和初始化)
四、编译和测试
编译并下载程序后,厥后果已在本文开篇的图2中呈现了。当然,在串口终端依然可以通过 list_thread 命令查看当前正在运行的线程。各位在测试时请把稳不雅观察,当从任务1切换至任务2,线程列表中的任务1线程是否退出了,从任务2切换至任务1是不是同样如此。
(本文完)








