|
本帖最后由 shower.xu 于 2015-5-1 09:57 编辑
最近工作上的事很多,一直没抽出时间赶进度,为了过好五一,今天下午抽时间移植了一个状态机系统上去,实现多任务的运行,为下一步菜单系统打下基础。
下面简单介绍一下这个状态机系统:
这个状态机是从隔壁论坛里网友的分享里copy过来的,试了几次,很好用,所以打算在小资源的单片机系统里面用下去。
它需要一个时钟,支持多个任务分时并发,支持信号量传递,简单的优先级等等。
- #ifndef TINYOS
- #define TINYOS
- #define MAXTASKS 5 //顶层任务数量最大为255个,顶层任务的任何地方都可以调用子任务.
- extern volatile unsigned char timers[MAXTASKS];
- #define _SS static unsigned char _lc=0; switch(_lc){default:
- #define _EE ;}; _lc=0; return 255;
- #define WaitX(tickets) do {_lc=(__LINE__+((__LINE__%256)==0))%256; return tickets ;} while(0); case (__LINE__+((__LINE__%256)==0))%256:
- #define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0) timers[TaskID]=TaskName(); } while(0);
- #define RunTaskA(TaskName,TaskID) { if (timers[TaskID]==0) {timers[TaskID]=TaskName(); continue;} } //前面的任务优先保证执行
- #define CallSub(SubTaskName) do {unsigned char currdt; _lc=(__LINE__+((__LINE__%256)==0))%256; return 0; case (__LINE__+((__LINE__%256)==0))%256: currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
- #define InitTasks() {unsigned char i; for(i=MAXTASKS;i>0 ;i--) timers[i-1]=0; }
- #define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=255)) timers[i-1]--;}}
- #define SEM unsigned int
- //初始化信号量
- #define InitSem(sem) sem=0;
- //等待信号量
- #define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
- //等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
- #define WaitSemX(sem,tickets) do { sem=tickets+1; WaitX(0); if(sem>1){ sem--; return 1;} } while(0);
- //发送信号量
- #define SendSem(sem) do {sem=0;} while(0);
- #endif//终止
复制代码首先包含头文件和声明函数和变量
- //TinyOS
- #include "tinyOS.h"
- /* 信号量传递 */
- SEM keyPressed;
- /* 系统定时器 */
- void toggle_OS_timer(void);
- //unsigned char task0();
- unsigned char task1(void);
- unsigned char task2(void);
- unsigned char task3(void);
- unsigned char task4(void);
复制代码编写任务代码,系统需要一个时钟
- /* TinyOS task function */
- void toggle_OS_timer(void)
- {
- UpdateTimers();
- //RunTask(task0,0); //任务0具有精确按时获得执行的权限
- }
- /* 按键扫描任务,15ms一次 */
- unsigned char task1(){
- _SS
- while(1)
- {
- key_scan();
- if(key_status) SendSem(keyPressed);
- WaitX(15);
- key_flag_clr();
- }
- _EE
- }
- /* 菜单响应程序 */
- unsigned char task2(){
- _SS
- while(1)
- {
- WaitSem(keyPressed);
- MenuIndex_switch();
- }
- _EE
- }
- /* 闪烁标题栏程序 */
- unsigned char task3(){
- _SS
- while(1)
- {
- GUI_RectangleFill(0+1, 0+1,0+12,0+12, Magenta);
- GUI_RectangleFill(0+12, 0+1,0+24-1,0+12, Red);
- GUI_RectangleFill(0+12, 0+12,0+24-1,0+24-1, Yellow);
- GUI_RectangleFill(0+1, 0+12,0+12,0+24-1, Green);
- WaitX(250);
- GUI_RectangleFill(0+1, 0+1,0+12,0+12, Green);
- GUI_RectangleFill(0+12, 0+1,0+24-1,0+12,Magenta );
- GUI_RectangleFill(0+12, 0+12,0+24-1,0+24-1,Red );
- GUI_RectangleFill(0+1, 0+12,0+12,0+24-1,Yellow );
- WaitX(250);
- GUI_RectangleFill(0+1, 0+1,0+12,0+12,Yellow );
- GUI_RectangleFill(0+12, 0+1,0+24-1,0+12, Green);
- GUI_RectangleFill(0+12, 0+12,0+24-1,0+24-1,Magenta );
- GUI_RectangleFill(0+1, 0+12,0+12,0+24-1, Red);
- WaitX(250);
- GUI_RectangleFill(0+1, 0+1,0+12,0+12, Red);
- GUI_RectangleFill(0+12, 0+1,0+24-1,0+12, Yellow);
- GUI_RectangleFill(0+12, 0+12,0+24-1,0+24-1, Green);
- GUI_RectangleFill(0+1, 0+12,0+12,0+24-1,Magenta );
- WaitX(250);
- }
- _EE
- }
- /* 动画切换程序 */
- unsigned char task4(){
- static uint8 ts=0;
- _SS
- while(1)
- {
- ts++;
- Board_LED_SetPortState(1<<(ts&0x03));
- WaitX(250); //25fps
- }
- _EE
- }
复制代码好,一切就绪,初始化并运行任务即可
- /*tinyOS start here */
- InitTasks(); //初始化任务,实际上是给timers清零
- InitSem(keyPressed);//初始化信号量
- MenuIndex_switch();
- while(1)
- {
- RunTaskA(task1,1);//按键扫描
- RunTaskA(task2,2);//菜单相应
- RunTaskA(task4,4);//界面切换动画
- RunTaskA(task3,3);//闪烁标题栏
- }
复制代码是不是很简单呢,那我们看实现了哪些功能。
task1进行按键的周期扫描,并把结果传递给task2。
task2平时不运行,直到task1告知有按键按下。这个时候执行界面切换程序来响应按键。
task3闪烁窗口左上角标题栏,告知系统运行。
task4控制桌面流水灯。
代码
TinyOS.rar
(1.5 MB, 下载次数: 49, 售价: 1 分芯积分)
运行界面
视频
|
赞赏
-
2
查看全部赞赏
-
|