完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 carey123 于 2014-4-17 16:23 编辑
|
|
相关推荐
|
|
本帖最后由 carey123 于 2014-4-17 16:48 编辑
优化无止境!呵呵,330楼看似不能再优化了,但我再尝试做一次优化: 敬请评测该版本,看是否还能优化:
[color=rgb(51, 102, 153) !important]复制代码 在keil下编译,又减少了18字节的ROM(超过10%了)。应该运行效率会更高。 ------------------以下为说明----------------------------------- 小小调度器任务函数的写法主要注意的,主要有三点: 1) 任务函数内部变量,建议都用静态局部变量来定义。 2) 任务函数内不能用switch语句。 3) 任务函数内,不能用return语句。 因为return已经被赋予任务延时的特定意义。(这是返回型任务函数版本的一个强制要求) 这三点,并不会明显造成写程序的不方便。 --------------------------- 从裸奔到使用OS操作系统或调度系统的代价主要有: 硬件资源代价(对RAM和ROM的消耗),学习代价(学会其原理,并掌握其用法),移植代价(往不同cpu上移植的工作量),效率代价(使用调度系统后带来的额外cpu负担),商业代价(版权费用),稳定性代价(是否引入潜在不稳定因素,或者增大bug跟踪调试工作量)。 从这几方面来讲,应用小小调度器的代价,都是非常小的。 1) 硬件资源代价: 前面的优化版本已经说明问题。keil下,本例程ram消耗 : 22字节,rom消耗126字节. 2) 学习代价: 小小调度器总共只有十多行代码,如果我们做一个简单的解释说明,理解起来其实是很快的。我相信学习时间比其他调度系统要短。 3) 移植代价: 几乎没有什么移植工作量,对于各种cpu,几乎是通吃。 4) 效率代价: 我们一直在努力优化,相信调度效率已经不低了。比如任务切换时间,应该是可以做到uS级别,甚至亚uS级别。 5) 商业代价: 小小本调度器为免费使用,无需支付任何费用。 6) 稳定性代价:小小调度器本质上仅仅是几个宏而已,未涉及任何对内部寄存器或堆栈的操作,避免了引入不稳定风险因素,所有操作都在可预见,可把控的前提下进行。 -------------------------------------------------------------------------------- 问:如果用到串口通讯呢,如何处理 答 :接收和发送都是用中断资源,任务里面只是简单的处理接收和要发送的数据,同时控制发送开启功能,效率会很高,基本上不会对其他任务造成影响。 思路 : void UartInter(void) interrupt 5 /* 串口中断服务函数 不记得51的串口是不是5了 */ { if(接收到一个字节数据) { 将数据存放到定义好的缓冲区里 清除接收标志位 } else //发送数据中断启动了 一般启动发送中断后 只要发送缓冲器SBUF 为空就会产生中断申请 { SBUF = 发送的数据; if(i == 发送的个数) { i = 0; 关闭发送中断功能;//在任务里开启发送功能 } } }//完成 void task3(void) { 处理接收到的数据 或 把需要发送的数据写入自己定义的缓冲区 并且 确定个数 i = ?; 需要发送数据则开启发送中断 }//完成 |
|
|
|
|
|
整个工程只有一个文件 main.c, 上面的就是main.c的完整代码。
呵呵,也许是调度器太小了,连单独的.h文件和c文件都没有做。
定时器触发调度.zip
(31.82 KB, 下载次数: 82
)
|
|
|
|
|
|
优化无止境!呵呵,330楼看似不能再优化了,但我再尝试做一次优化: 敬请评测该版本,看是否还能优化:
[color=rgb(51, 102, 153) !important]复制代码 在keil下编译,又减少了18字节的ROM(超过10%了)。应该运行效率会更高。 ------------------以下为说明----------------------------------- 小小调度器任务函数的写法主要注意的,主要有三点: 1) 任务函数内部变量,建议都用静态局部变量来定义。 2) 任务函数内不能用switch语句。 3) 任务函数内,不能用return语句。 因为return已经被赋予任务延时的特定意义。(这是返回型任务函数版本的一个强制要求) 这三点,并不会明显造成写程序的不方便。 --------------------------- 从裸奔到使用OS操作系统或调度系统的代价主要有: 硬件资源代价(对RAM和ROM的消耗),学习代价(学会其原理,并掌握其用法),移植代价(往不同cpu上移植的工作量),效率代价(使用调度系统后带来的额外cpu负担),商业代价(版权费用),稳定性代价(是否引入潜在不稳定因素,或者增大bug跟踪调试工作量)。 从这几方面来讲,应用小小调度器的代价,都是非常小的。 1) 硬件资源代价: 前面的优化版本已经说明问题。keil下,本例程ram消耗 : 22字节,rom消耗126字节. 2) 学习代价: 小小调度器总共只有十多行代码,如果我们做一个简单的解释说明,理解起来其实是很快的。我相信学习时间比其他调度系统要短。 3) 移植代价: 几乎没有什么移植工作量,对于各种cpu,几乎是通吃。 4) 效率代价: 我们一直在努力优化,相信调度效率已经不低了。比如任务切换时间,应该是可以做到uS级别,甚至亚uS级别。 5) 商业代价: 小小本调度器为免费使用,无需支付任何费用。 6) 稳定性代价:小小调度器本质上仅仅是几个宏而已,未涉及任何对内部寄存器或堆栈的操作,避免了引入不稳定风险因素,所有操作都在可预见,可把控的前提下进行。 -------------------------------------------------------------------------------- |
|
|
|
|
|
本帖最后由 carey123 于 2014-4-17 16:42 编辑
问 再改改,去掉函数指针,这样在51下能工作得更好。 答 是的,可以自己改,无需函数指针也完全可以,这样每个任务只需1到2个字节。 我已经在此基础上,继续优化下一个版本: 已经实现的新增特点: 1) 整个调度器总共占用1个字节RAM。 (是的!只占1个字节的RAM! 实在想不出还有没有比这个更省资源的调度器),调度器本身占用的ROM在200字节以内。 2) 去掉函数指针,一个任务只占用1到2个字节,支持任务内延时函数。顶层任务数量最大为255个。 3) 支持子任务调用。 一个子任务只占用1个字节RAM,子任务内也支持延时函数,并支持子任务函数传递参数。支持多级嵌套子任务调用,子任务数量没有限制。 4) 任务函数语法更精炼,如WaitX(2,20)简化为WaitX(20),无需指定定时器编号。 我的目标是: 打造一个极小单片机均可用的,与CPU硬件型号无关的调度系统,让256字节RAM都显得宽敞! 调度器代码将全公开,全免费使用,让天下“贫民”的单片机都用起,而且用得好! 比裸奔都更省资源!让“贫民”单片机不再裸奔,也无需裸奔! 问:说明一下以下宏定义,为的就是能简单理解清楚。 #define _SS static char lc=0; switch(lc){ case 0: lc=0; #define _EE }; lc=0; #define WaitX(a,b) settimer(&lc,__LINE__,a,b); return ; case __LINE__: 答:第一个_SS是switch散转,第二个_EE只是一个括弧而已。 WaitX就是记住当前运行行号,然后设置下次任务函数被调用的时刻。 |
|
|
|
|
|
说明:以下是新版的程序,调度器只有十行左右代码,想看明白的,把宏替换了,然后多看几遍就明白了。 不想看得太明白的,跟着例程用也行。 这个调度器已经是可以正常使用了。 前提条件: 1) cpu支持c语言编译器 2)cpu支持产生定时器中断 ( 好像还没用过不支持这两个条件的单片机哈 ) 前面有个帖子说需要有一个监测机制,监测那些占用时间过多的任务,这个我已经实现了一个方案----(在大脑里)。下个版本将一起公布。 我希望大家先测试和应用下这个调度器,调度器再好,没有投入实际应用,也等于零。 所以我希望在各种cpu下做些实验,能反馈一些信息才好。 毕竟这个调度器的一个特点是与单片机无关,所以也需要多种cpu例程供大家一起参考。 希望大家多多发扬莫大提倡的开源精神,发布一些应用例子,不要藏着自己独享。独乐乐,不如众乐乐。 如果能avr或者lgt下,能有些测试用例,大家一起探讨就更好,以此表示对莫大的敬意,和对lgt的支持。 我希望下个版本能够以多种cpu例程的方式来发布。希望得到大家的帮助。 小小调度器开始 #include /**************小小调度器开始 *********************************/ #define MAXTASKS 3 //顶层任务数量,可按需增加,最大为255个。 unsigned char timers[MAXTASKS]; char currid; //当前运行的任务号 #define _SS static char lc=0; switch(lc){ case 0: //跳转开始 #define _EE }; lc=0; //跳转结束 #define DelayX(b) settimer(&lc,__LINE__,b); return ; case __LINE__: //任务内延时等待“函数” #define RunTask(a,b) currid=b; if (timers==0){timers=-1; a();} //运行顶层任务 #define CallSub(x) DelayX(0);x(); if (timers[currid]!=-1) return; //调用子任务 void settimer(char *lc,char line,unsigned char d){//设置定时器 *lc=line; timers[currid]=d; } /****************小小调度器结束*** (我很短,但用起来很爽)******************************/ ***it KEY = P3^2; unsigned char code numtab[16]={0x24,0x6F,0xE0,0x62,0x2B,0x32,0x30,0x67,0x20,0x22,0x21,0x38,0xB4,0x68,0xB0,0xB1}; sfr IAP_CONTR = 0xC7; sfr WDT_CONTR = 0xC1; //清除看门狗 void clr_wdt() { WDT_CONTR =0x3C; } //初始化定时器,产生10ms中断 void InitT0() { TMOD = 0x21; IE |= 0x82; // 12t TL0=0Xff; TH0=0Xb7; TR0 = 1; } //定时器中断处理函数 void INTT0(void) interrupt 1 using 1 { unsigned char i; TL0=0Xff; //10ms 重装 TH0=0Xb7; //逻辑定时器处理 for (i=0;i timers--; } } } ***it LED1= P2^4; //任务一,状态机写法 void ontimer0(){ LED1=!LED1; // LED1引脚接在发光管负极,LED1=0 为亮,LED1=1为灭 if (LED1) timers[currid]=45; //450mS 灭 else timers[currid]=5; //50ms 亮 } //任务二,状态机写法 char keycount=0; void task1(){ if(KEY==0) { keycount++; if (keycount>20) IAP_CONTR = 0x60; } else{ keycount=0; } timers[currid]=5; //重装定时器 } //这是一个子任务函数 void subtask() { static char i; _SS for(i=0;i<=5;i++){ DelayX(20); P1=numtab; } _EE } //任务三,“线程”写法,复杂任务请用这种方式来写,比传统状态机写法更简单,更自然,而且更省ROM! void task2() { static char i; //变量请申明为静态的。 _SS while(1){ for(i=0;i<=9;i++){ //先从0--9快速显示,间隔200mS DelayX(20); P1=numtab; } for(i=0;i<=9;i++){//然后从0--9慢速显示,间隔500mS DelayX(50); P1=numtab; CallSub(subtask); //顶层任务的任何地方都可以调用子任务 } //CallSub(subtask); //顶层任务的任何地方都可以调用子任务 } _EE } void main() { P3M0 = 0x00; P3M1 =0x00; P1 = 0xff; //关LED数码管显示 InitT0(); //初始化定时器,以便产生10ms中断 KEY =1; //按键IO口 while(1){ clr_wdt(); //清除看门狗 //这里,只需运行顶层任务即可 RunTask(ontimer0,0); //ontimer0任务放在第0个任务槽 RunTask(task1,1); //task1任务放在第1个任务槽 RunTask(task2,2); //task2任务放在第2个任务槽 //...还可以增加更多任务 } } |
|
|
|
|
|
本帖最后由 carey123 于 2014-4-17 16:51 编辑
数码管不论是动态还是静态扫描,都支持。 这是一个时间多任务调度器。 我把文件
main.rar
(1.5 KB, 下载次数: 62
)
仿真:
thread.rar
(78.72 KB, 下载次数: 45
)
这个仿真可以看到task2里的三种运行状态
thread2.rar
(92.96 KB, 下载次数: 41
)
|
|
|
|
|
|
利用了Pt的语法,并非简单照搬,而是改造了原Pt的延时模式,大幅节省任务所需资源,从原Pt任务的10B Ram到现在的2B Ram.原Pt任务每状态35~40 ROM消耗字节到现在的13字节,一切都为了追求更小巧自然。
其实这个调度器的重点并不真正在于与Pt的语法,而是对节省CPU资源的极致追求。 以前,裸奔之所以一直存在,是因为,裸奔对资源的要求几乎小于所有嵌入式操作系统。 在设计这个调度器之前,一直在想一个问题: 状态机有多“便宜”?,有没有比“状态机”更便宜的?如果有比状态机更“便宜”的编程方法,那裸奔还有什么意义么? 另外,设计一个调度器,不仅仅是框架本身对资源的要求要小,还有一个方面就是任务函数内部的处理过程,对资源的要求也要小。 我以前用ProtoThread来做了多种产品,确实也算很省RAM, 但是我发现了ProtoThread的一个最大的问题: 任务函数内每个状态消耗的字节太高,比状态机还高,也就是说编译出来的CODE比用状态机方式要大。 对于ROM资源紧张的单片机来说(比如2K,4K或8K字节Flash),这个可能是一个不小的问题。 传统状态机的优点在于: 当状态很简单时,确实是最省ROM的。比如一个LED闪烁,只需10多个字节就可以了。另外一个优点是,高度可移植性,与cpu无关,任何cpu编程,都可以用状态机来做。 睡着任务的复杂化,状态增多时,状态机的ROM消耗就会变大。 所以我在本调度器里面,保留了两种语法: 一种是传统状态机,用于简单的任务。比如LED闪烁等。 另一种就是经过改良的PT语法,经过我实际测试,改良的PT语法,一个状态的平均消耗是13字节,当状态量达到4个左右时,改良的PT语法所消耗的ROM就会小于传统状态机语法了, 而且任务越复杂,状态量越多,改良的PT语法比传统状态机语法苏所节省资源越多。 那么,这就实现了一个逆转! 在复杂任务面前,传统状态机语法“输了”! 改良的PT语法不仅仅是写起来更自然,更易懂,而且还更“便宜”,而且同样与cpu无关,具备高度移植性。 基于大部分产品而言,任务不会简单到只闪烁一个LED,从总体来讲,使用本调度器,确实是比裸奔更省资源了。 这个才是本调度器的真正意义所在。 |
|
|
|
|
|
/*****************小小调度器部分开始********************************************/ #define _SS static char lc=0; switch(lc){ case 0: lc=0; #define _EE }; lc=0; #define WaitX(a,b) settimer(&lc,__LINE__,a,b); return ; case __LINE__: struct TASK { char td; void (*fp)(); }; #define MAXTASKS 5 struct TASK tasks[MAXTASKS]; //设置定时器 void settimer(char *lc,char line,char tmrid,int d){ *lc=line; tasks[tmrid].td=d; } //逻辑定时器处理,在定时器中断里调用 void dectimers() { unsigned char i; for (i=0;i } } //任务调度函数,在main里面运行 void runtasks() { unsigned char i; for(i=0;i if (tasks[i].fp!=0){ if (tasks[i].td==0){ tasks[i].td=-1; tasks[i].fp(); } } } } /****************小小调度器部分结束*******************************************************/ lc 的数据类型是 char,而lc是用来保持任务的—LIN—,这个数最是可以超过255的,比如这个__LINE__ = 256 = 0x100,那case __LINE__时,这个值就是 case 0: 这样 __SS中定义的 lc = 0 就一样了,一个switch语句中有可能出现两个case 0; |
|
|
|
|
|
我发一个在楼主上面改好的例程一个是C51,一个是sonix MCU下的
先发下C51,并贴上全文: /********************************* Titel : pTask.h Mcu : 8-32 bit RAM : bytes: 5 * (D_TASKS_MAX)+6 ROM : bytes: < 0.5K Complier : Support of c compiler Author : Eddie Version : V1.3 Updata : 2012-12-05 **********************************/ /* Note: Note: (1).add task multithreading mode(PTM) (2).add taks Time-triggered mode(TTM) (3).change: ptm to pt/tt Mixed-mode (4).debug:Task_tick() (5).Optimization; (6).add func: void Task_start(u8 tid) (7).add subcall() */ #ifndef _pTask_h_ #define _pTask_h_ //--------------------user define------------------ #define D_TASKS_MAX 3 #define lc_type u8 #define ENI() EA = 1 //---------------data type------------------------ #define u8 unsigned char #define u16 unsigned int #define u32 unsigned long //------------------------------------------------ //---------------task constant define------------- #define D_Task0_ID 0 #define D_Task1_ID 1 #define D_Task2_ID 2 #define D_Task3_ID 3 #define D_Task4_ID 4 #define D_Task5_ID 5 #define D_Task6_ID 6 #define D_Task7_ID 7 #define D_Task8_ID 8 //------------------------------------------------ #define D_Delay_ever ((u8)-1) #define D_period_ever ((u8)-1) #define D_wait_ever ((u8)-1) //-----------------function define---------------- void ptk_set_timer(lc_type *lc,lc_type line,u8 timeover); void Task_create(void (*pFunc)() ,u8 tid); void Task_start(u8 tid); //----------------------------------------------- struct { void (* pTask)(void); }func[D_TASKS_MAX]; u8 taskSleep[D_TASKS_MAX]; u8 taskID,taskEvenRdy; u8 tIndex,eIndex; bit task_Wait_flag; /****************************************************** Micro : PTK_BEGIN Note : 启动任务处理,放在函数开始处 Updata : 2012-12-03 *******************************************************/ #define PTK_BEGIN static lc_type lc=0; switch(lc){ case 0: /****************************************************** Micro : PTK_END Note : 结束任务,放在函数的最后 Updata : 2012-12-03 *******************************************************/ #define PTK_END } lc=0; /************************************************ Function : ptk_set_lc Stacks : Note : 线程任务lc设定 Updata : 2012-12-03 ************************************************/ #define ptk_set_lc() *lc = (lc_type)__LINE__ /****************************************************** Micro : Task_ReInit Stacks : Note : 重新初始化进程. Updata : 2012-12-03 *******************************************************/ #define Task_ReInit() *lc = 0; return /************************************************ Micro : Task_setsleep Stacks : Note : 设置指定的进程为休眠状态 Updata : 2012-12-04 ************************************************/ #define Task_setsleep(tid, timeover) taskSleep[tid] = timeover /****************************************************** Micro : Task_sleep Stack : 1 Note : 进程立即进入休眠 Updata : 2012-12-03 *******************************************************/ #define Task_sleep(timeover) do{ ptk_set_timer(&lc,(lc_type)__LINE__,timeover); case (lc_type)__LINE__: if(taskSleep[taskID]) return; }while(0) /************************************************ Micro : Task_delay Stacks : Note : 进程内延时 Updata : 2012-12-04 ************************************************/ #define Task_delay(timeover) Task_sleep(timeover) /************************************************ Micro : Task_period Stacks : Note : 进程运行周期 Updata : 2012-12-04 ************************************************/ #define Task_period(timeover) Task_sleep(timeover) /****************************************************** Micro : Task_condic_wait Stacks : Note : 等待条件或超时 Updata : 2012-12-04 *******************************************************/ #define Task_condic_wait(condiction,timeover) do{ ptk_set_timer(&lc,(lc_type)__LINE__,timeover); case (lc_type)__LINE__: if((!(condiction))&& taskSleep[taskID]) return; task_Wait_flag = (condiction)? 1:0; }while(0) /****************************************************** Micro : Task_event_wait Stacks : Note : 等待事件或超时 Updata : 2012-12-03 *******************************************************/ #define Task_event_wait(timeover) do{ ptk_set_timer(&lc,(lc_type)__LINE__,timeover); case (lc_type)__LINE__: if((!(taskEvenRdy & (1< task_Wait_flag = (taskEvenRdy & (1< /************************************************ Micro : Ints_event_send Stacks : Note : 中断或进程向进程传事件消息 Updata : 2012-12-04 ************************************************/ #define Ints_event_send(tid) do{ taskEvenRdy |= (1< }while(0) /************************************************ Micro : Ints_even_clear Stacks : Note : 清除进程传事件消息 Updata : 2012-11-21 ************************************************/ #define Ints_even_clear() taskEvenRdy &= 0xff ^ (1< /************************************************ Micro : Task_event_send Stacks : Note : 向进程传事件消息,并切换到等待此事件的任务 Updata : 2012-12-04 ************************************************/ #define Task_event_send(tid) do{ taskEvenRdy |= (1< ptk_set_lc(); return; case (lc_type)__LINE__: taskID = taskID; }while(0) /****************************************************** Micro : Task_switch Stacks : Note : 任务切换 Updata : 2012-12-04 *******************************************************/ #define Task_switch() do{ ptk_set_lc(); return; case (lc_type)__LINE__: taskID = taskID; }while(0) /************************************************ Micro : Task_setsuspend Stacks : Note : 设置指定的进程为休眠状态. Updata : 2012-11-19 ************************************************/ #define Task_setsuspend(tid) taskSleep[tid] = D_Delay_ever /************************************************ Micro : task_suspend Stacks : Note : 进程立即进入休眠 Updata : 2012-12-04 ************************************************/ #define Task_suspend() do{ ptk_set_timer(&lc,(lc_type)__LINE__,D_Delay_ever); case (lc_type)__LINE__: if(taskSleep[taskID]) return; }while(0) /************************************************ Micro : Task_resume Stacks : Note : 唤醒指定的进程. Updata : 2012-11-22 ************************************************/ #define Task_resume(tid) do{ if(tid != taskID) taskSleep[tid] = 0; }while(0) /******************************************************* Micro : Task_subCall Stacks : Note : 调用子任务 Updata : 2012-12-03 *******************************************************/ #define Task_subCall(subTask) do{ ptk_set_timer(&lc,(lc_type)__LINE__,0); return ; case (lc_type)__LINE__: subTask(); if(taskSleep[taskID]) return; }while(0) /************************************************ Micro : Task_tick Stacks : Note : 更新进程定时器 Updata : 2012-12-03 ************************************************/ #define Task_tick() do{ for(tIndex = 0; tIndex < D_TASKS_MAX; tIndex++) { if(taskSleep[tIndex] != D_Delay_ever) { if(taskSleep[tIndex]){ taskSleep[tIndex]--;} } } }while(0) /************************************************ Micro : Task_schedule Stacks : Note : 进程调度,事件触发优先 Updata : 2012-12-04 ************************************************/ #define Task_schedule() do{ for(eIndex = 0; eIndex < D_TASKS_MAX; eIndex++) { if(taskEvenRdy & (1< taskID = eIndex; goto L_Sch; } } if(taskSleep[taskID] == 0) { L_Sch: (*func[taskID].pTask)(); } if(++taskID >= D_TASKS_MAX){taskID = 0;} }while(0) /************************************************ Function : ptk_set_timer Stacks : Note : 线程任务定时设定 Updata : 2012-12-03 ************************************************/ void ptk_set_timer(lc_type *lc,lc_type line,u8 timeover) { *lc=line; taskSleep[taskID] = timeover; } /************************************************ Function : Task_create Stacks : Note : 初始化任务 Updata : 2012-11-26 ************************************************/ void Task_create(void (*pFunc)() ,u8 tid) { func[tid].pTask = pFunc; } /************************************************ Function : Task_start Stacks : Note : 从指定任务开始运行 Updata : 2012-11-26 ************************************************/ void Task_start(u8 tid) { u8 i; for(i = 0;i < D_TASKS_MAX;i++) { taskSleep = 1+i; } taskID = tid; ENI(); } //-----------------------End of file--------------- #endif #include #include "pTask[v13].h" sfr IAP_CONTR = 0xC7; sfr WDT_CONTR = 0xC1; ***it KEY = P3^2; ***it LED1= P2^4; u8 code numtab[16]={ 0x24,0x6F,0xE0,0x62, 0x2B,0x32,0x30,0x67, 0x20,0x22,0x21,0x38, 0xB4,0x68,0xB0,0xB1 }; u8 keycount = 0; /************************************************ Function : WDTC Input : Output : Return : Stacks : 1 Note : Updata : 2012-12-04 ************************************************/ void WDTC() { WDT_CONTR =0x3C; } /************************************************ Function : Init_IO Input : Output : Return : Stacks : 1 Note : Updata : 2012-12-04 ************************************************/ void Init_IO() { P3M0 = 0x00; P3M1 =0x00; P1 = 0xff; //关LED数码管显示 KEY = 1; } /************************************************ Function : Init_TMR0 Input : Output : Return : Stacks : 1 Note : 初始化定时器,产生10ms中断 Updata : 2012-12-04 ************************************************/ void Init_TMR0() { TMOD = 0x21; IE |= 0x82; TL0 = 0Xff; TH0 = 0Xb7; TR0 = 1; } /************************************************ Function : INTT0 interrupt Input : Output : Return : Stacks : 1 Note : 定时器中断处理函数 Updata : 2012-12-04 ************************************************/ void INTT0(void) interrupt 1 using 1 { TL0=0Xff; TH0=0Xb7; Task_tick(); } /************************************************ Function : Task0_led Input : Output : Return : Stacks : Note : 任务一, LED1引脚接在发光管负极, LED1=0 为亮,LED1=1为灭 Updata : 2012-12-04 ************************************************/ void Task0_led() { PTK_BEGIN while(1) { LED1 = !LED1; if (LED1) Task_delay(45); else Task_delay(5); } PTK_END } /************************************************ Function : Task0_led Input : Output : Return : Stacks : Note : 任务二 Updata : 2012-12-04 ************************************************/ void Task1_key() { static bit SameKey_F = 0; PTK_BEGIN while(1) { if(KEY) { if((++keycount >= 20)&&(!SameKey_F)) { IAP_CONTR = 0x60; SameKey_F = 1; } } else { keycount = 0; SameKey_F = 0; } Ints_event_send(D_Task2_ID); Task_delay(5); } PTK_END } /************************************************ Function : subtask Input : Output : Return : Stacks : Note : 这是一个子任务函数 Updata : 2012-12-04 ************************************************/ void subtask() { static char i; PTK_BEGIN while(1) { for(i=0;i<=5;i++) { P1=numtab; Task_event_wait(D_wait_ever); } } PTK_END } /************************************************ Function : Task2_display Input : Output : Return : Stacks : Note : 任务三,“线程”写法,复杂任务请用这种 方式来写,比传统状态机写法更简单, 更自然,而且更省ROM! 顶层任务的任何地方都可以调用子任务 Updata : 2012-12-04 ************************************************/ void Task2_display() { static char i; PTK_BEGIN while(1) { for(i=0;i<=9;i++) //先从0--9快速显示,间隔200mS { P1=numtab; Task_delay(20); } for(i=0;i<=9;i++) //然后从0--9慢速显示,间隔500mS { P1=numtab; Task_event_wait(50); if(task_Wait_flag) { Task_subCall(subtask); } } } PTK_END } /************************************************************* main program zone *************************************************************/ void main() { Init_IO(); Init_TMR0(); Task_create(Task0_led, D_Task0_ID); Task_create(Task1_key, D_Task1_ID); Task_create(Task2_display,D_Task2_ID); Task_start(D_Task0_ID); while(1) { WDTC(); Task_schedule(); } }
ptask[v13]定时器触发调度.rar
(113.54 KB, 下载次数: 68
)
|
|
|
|
|
|
下面是用在sonix 上的一个智能家居控制上的例子: /******************************************** Title : main McuBody : SN8F26E611 RAM : 128*8Bit ROM : 2K*16Bit STACKS : 8 level I/O PORT : 11 PWM PORT : 3(P17/16/P15) T0 : 8bit base timer T1 : 16bit TC0-2 : 3* 8bit timer/count with pwm/cout_out(auto load) EXINT : 2(INT0/INT1) ADC : 8 channel(12bit) INTS : 11(INT0/T0/T1/TC0/TC1/TC2/CMP/URX/UTX/SIO/WAKEUP) OPTION : Security-------Enable High Fcpu------Fosc/2 High_clk-------IHRC_16M Low Fcpu-------FLosc/1 Watchdog-------Enable LVD------------LVD_L Resetpin-------P02 WDT_CLK--------Flosc/4 WDT TIME : about 512ms_3v/256ms_5v WORK_VCC : 3.3V IDE : SN8 C Studio_V146(572.015) Author : Eddie Updata : 2012-12-04 Verison : A/01 ********************************************/ /* Note: (1).debug:Confirm Communication() 0x02 to 0x03 (2).change: nTask.h to pTask[v13].h ;-------------------------------------------- ;P00 ----- [O]TEST1 ;P01 ----- [I]TEST2 ;P02 ----- [I]NC2 ;P10 ----- [O]UTX ;P11 ----- [I]URX ;P12 ----- [I]URTS ;P13 ----- [O]UCTS ;P14 ----- [I]NC3 ;P15 ----- [I]NC4 ;P16 ----- [I]NC5 ;P17 ----- [I]TRIG_IN ;-------------------------------------------- */ #include #include "SN26E611_USER.h" #include "typedef.h" #include "pTask[v13].h" //==================================================================== //---------------------------uart rx/tx------------------------------ volatile u8 RxBuf[12],TxBuf[12],RxIndex,TxCnt,TxWaitT2ms,WdtT2ms; volatile u8 __ROM *TxPrt; volatile u8 TxCodeNum; volatile bit RxPackageOK_F,TxPackage_F; volatile bit RxConnectOK_F; volatile bit Task0Runing_F,Task1Runing_F,Task2Runing_F; volatile bit beTrig_F; /******************************************************************************** Interrupts Program Zone ********************************************************************************/ //=============================================================================== void __interrupt [0x08] ISR_WakeInt(void) {} void __interrupt [0x09] ISR_INT0 (void) {} void __interrupt [0x0A] ISR_T0 (void) {} void __interrupt [0x0C] ISR_TC1 (void) {} void __interrupt [0x0D] ISR_TC2 (void) {} void __interrupt [0x0E] ISR_T1 (void) {} void __interrupt [0x0F] ISR_CM0 (void) {} void __interrupt [0x10] ISR_SIO (void) {} //=============================================================================== void __interrupt [0x0B] ISR_TC0(void) { static u8 T60msBase = 10; static bit TrigInOld_F; FTC0IRQ = 0u; //--------------------------------------- TxWaitT2ms++; WdtT2ms++; //-------------trig in check------------ if(!(--T60msBase)) { T60msBase = 30; if(!beTrig_F) { if(TrigInOld_F && (!TRIG_IN)) { beTrig_F = 1; Ints_event_send(D_Task1_ID); } } TrigInOld_F = TRIG_IN; } //------------task time check------------ Task_tick(); } void __interrupt [0x11] ISR_UART_RX(void) { u8 FccSum ,i; //-------------------------Uart process------------------------- //if((FUFMER == 0)&&(RxPackageOK_F == 0)) if(RxPackageOK_F == 0) { RxBuf[RxIndex++] = URXD; if(RxIndex > 12) {RxIndex = 0;} //rx burrer size max as 12 else { if(RxBuf[0] == D_Frame_STX) { if((RxBuf[1] == 0x00)&&(RxBuf[2] >= 0x6)&&(RxBuf[2] <= 0x0A)&&(RxIndex == RxBuf[2]+2)) { FccSum = 0x00; for(i = 1;i < RxIndex;i++) {FccSum += RxBuf;} if(FccSum == 0) { Disable_Rx(); RxIndex = 0; RxPackageOK_F = 1; Ints_event_send(D_Task0_ID); } else {RxIndex = 0;} } } else {RxIndex = 0;} } } //---------Clear signs on the last----------- FURXIRQ=0; //------------------------------------------- } void __interrupt [0x12] ISR_UART_TX(void) { FUTXIRQ = 0; if(TxCnt > 0) { UTXD = *TxPrt; TxPrt++; TxCnt--; } else { TxPackage_F = 0; } //TxCnt == 0 mains the last byte trans completed} } /******************************************************************************** Sub Program Zone ********************************************************************************/ /************************************************ Function : IO_Init Input : Output : Return : Stacks : 1 Note : IO initalization "1"----output "0"----input Updata : 2012-11-07 ************************************************/ void IO_Init(void) { P0CR = (1< P1CR = (0< //--------------- P0PHCR = 0xffu; // P1PHCR = 0xffu ^ (1< //--------------- PORT0 = (0< PORT1 = (1< } /************************************************ Function : Timer_Init Input : Output : Return : Stacks : 1 Note : Fcpu =HIRC(16MHz)/2 = 8MHz tc0 timeout period as 2ms Updata : 2012-11-06 ************************************************/ void Timer_Init(void) { //disable all interrutps first,and clr all irq flag DISI(); //--------------enable t0 for delay()------------- T0CR = T0Prescale_128; //t0clk period as 8us FT0IEN = 0; //disable t0 interrupt FT0ENB = 1; //--------------enable tc1 timerover interrupt------- TC0CR = (TCxPrescale_128 | AS_TIMER | TCxCLK_AS_FCPU | DS_TCxOut | DS_PWMx); TC0 = TC0R = D_TC0_Preset; FTC0IEN = 1; //enable tc0 interrupt FTC0ENB = 1; //enable use tc0 } /************************************************ Function : Uart_Init Input : Output : Return : Stacks : 1 Note : Fhosc =HIRC(16MHz) Fcpu = Fhosc/2 = 8MHz 9.6K baud rate Updata : 2012-11-08 ************************************************/ void Uart_Init(void) { FUTXPEN = 0; // Disable UART TX parity bit check function FURXPEN = 0; // Disable UART RX parity bit function. URRX = D_URS_BR_9600; URCR = D_URC_BR_9600; // Set UART baud rate as 9600bps. FUTXEN = 1; // Enable UART TX FURXEN=1; // Enable UART RX FUTXIEN=1; // Enable UART TX interrupt function. FUTXIRQ = 0; // Clear UART TX interrupt flag. FURXIEN = 1; // Enable RX interrupt FURXIRQ =0; // clear RX interrupt request flag } /************************************************ Function : Delay2Ms Input : Output : Return : Stacks : 2 Note : Fosc = 16MHz Fcpu = Fosc/1=16MHz Updata : 2012-11-05 ************************************************/ void Delay2Ms(u8 ms) { while(ms--) { WDTC(); T0 = 0x06; while(T0); } } /************************************************ Function : Commun_Response Input : Output : Return : Stacks : 1 Note : fire alerm Updata : 2012-12-04 ************************************************/ u8 __ROM Commun_Response[11] = { //0x02, 0x00, 0x0a, 0x43, 0x4e, 0x4e, 0x54, 0x0b, 0x03, 0x00, 0x00, 0xb6}; /************************************************ Function : State_Normal Input : Output : Return : Stacks : 1 Note : Updata : 2012-10-08 ************************************************/ u8 __ROM State_Normal[9] = { //0x02, //STX 0x00, //LenghtH 0x08, //LenghtL 'R', //0x52 'G', //0x47 'A', //0x41 'L', //0x4C 'N', //0x4E 'A', //0x41 0x43}; //fcc 下面是源码:
源码.rar
(143.28 KB, 下载次数: 63
)
soft.rar
(143.28 KB, 下载次数: 42
)
|
|
|
|
|
|
接上一个程序 /************************************************ Function : State_Ringing Input : Output : Return : Stacks : 1 Note : Updata : 2012-11-05 ************************************************/ u8 __ROM State_Ringing[9] = { //0x02, //STX 0x00, //LenghtH 0x08, //LenghtL 'R', //0x52 'G', //0x47 'A', //0x41 'L', //0x4C 'O', //0x4F 'N', //0x4E 0x35}; //fcc /************************************************ Function : State_RxError Input : Output : Return : Stacks : 1 Note : Updata : 2012-10-08 ************************************************/ u8 __ROM State_RxError[9 ] = { //0x02, //STX 0x00, //LenghtH 0x08, //LenghtL 'R', //0x52 'G', //0x47 'A', //0x41 'L', //0x4C 'E', //0x45 '1', //0x31 0x5C}; //fcc /************************************************ Function : Prefix_Body_Check Input : Output : Return : Stacks : 1 Note : prefix_body bytes[10:3] Updata : 2012-11-07 ************************************************/ u8 Prefix_Body_Check(char __ROM *string,u8 length) { u8 i; length = length +3; for(i = 3;i < length;i++) { if(RxBuf != (u8)*string) break; string++; } if(i < length) {i = 0x00;} return i; } /************************************************ Function : TrigInLevelChk Input : Output : Return : Statcks : 1 Note : Updata : 2012-11-07 ************************************************/ u8 TrigInLevelChk(u8 times) { u8 i = 0; while(times--) { if(!TRIG_IN) i++; } return i; } /************************************************ Function : Tx_SenMsg Input : Output : Return : Stacks : 1 Note : Updata : 2012-11-08 ************************************************/ void Tx_SenMsg(u8 CodeNum) { switch(CodeNum) { case 0: { TxPrt = Commun_Response; TxCnt = 11; break; } case 1: { TxPrt = State_Ringing; TxCnt = 9; break; } case 2: { TxPrt = State_Normal; TxCnt = 9; break; } case 3: { TxPrt = State_RxError; TxCnt = 9; break; } } //---------------trans code----------- if(CodeNum < 4) { TxWaitT2ms = 0; while((URTS == 0)||(TxPackage_F == 1)) //wait reqest to send singal { if(TxWaitT2ms >= 150) return; //timeover as 300ms } TxPackage_F = 1; UTXD = D_Frame_STX; //STX } //------------------------------------ } /************************************************ Function : Task_Start Input : Output : Return : Stacks : 2 Note : Updata : 2012-12-04 ************************************************/ void Task_Init(void) { Delay2Ms(250); Enable_Rx(); } /************************************************ Function : Task0_Rxdecoded Input : Output : Return : Stacks : 2 Note : Updata : 2012-12-04 ************************************************/ void Task0_Rxdecoded(void) { PTK_BEGIN while(1) { Task_event_wait(D_wait_ever); //-----------Confirm Communication------- if(Prefix_Body_Check("CNNT",4)) { Enable_Rx(); TxCodeNum = D_Commun_Response; Tx_SenMsg(TxCodeNum); RxConnectOK_F = 1; } //-----------Command send from RF--------- else if(Prefix_Body_Check("SGAL0000",8)) { Enable_Rx(); if(TrigInLevelChk(20) >= 5) { TxCodeNum = D_State_As_Ringing; Tx_SenMsg(TxCodeNum); } else { TxCodeNum = D_State_As_Normal; Tx_SenMsg(TxCodeNum); } } //-----------Command Reply from RF--------- else if(Prefix_Body_Check("CGWLOK",6)) { Enable_Rx(); } else if(Prefix_Body_Check("CGWLE1",6)) { Enable_Rx(); Tx_SenMsg(TxCodeNum); } //------------Communication Error --------- else { Enable_Rx(); Tx_SenMsg(D_State_RxError); } } PTK_END } /************************************************ Function : Task1_TxTrigsigle Input : Output : Return : Stacks : 2 Note : task perid as 50ms Updata : 2012-12-04 ************************************************/ void Task1_TxTrigsigle(void) { PTK_BEGIN while(1) { Task_event_wait(25); if(task_Wait_flag) { beTrig_F = 0; TxCodeNum = D_State_As_Ringing; Tx_SenMsg(TxCodeNum); } } PTK_END } /******************************************************************************** Main Program Zone ********************************************************************************/ void main(void) { DISI(); WDTC(); IO_Init(); Uart_Init(); Timer_Init(); Task_Init(); Task_create(Task0_Rxdecoded, D_Task0_ID); Task_create(Task1_TxTrigsigle,D_Task1_ID); Task_start(D_Task0_ID); //----------------------------main loop----------------------------------- while(1) { Task_schedule(); WDT_Clear(); } } |
|
|
|
|
|
养成看帖回帖的好习惯!~这个老帖子还是这么火, |
|
|
|
|
|
有时间细细的过一遍,应该非常有益。谢谢分享。 |
|
|
|
|
|
谢谢分享谢谢分享谢谢分享 谢谢分享谢谢分享 谢谢分享 谢谢分享谢谢分享 谢谢分享 谢谢分享 谢谢分享谢谢分享谢谢分享 谢谢分享 谢谢分享 谢 谢 谢谢分享 谢谢分享 谢 谢 谢谢分享 谢谢分享 分 分 谢谢分享 谢谢分享 享 享 谢谢分享 谢谢分享 谢 谢 谢谢分享 谢谢分享 谢 谢 谢 谢谢分享 谢谢分享 分 分 谢谢 谢谢分享 谢谢分享 享 享 谢谢分 谢谢分享 谢谢分享 谢 谢 谢谢分 谢谢分享 谢 谢 谢谢分谢谢分享 谢 谢 谢谢 谢谢 分 分 |
|
|
|
|
|
使用stm32l451片子,对ad7606进行3通道100k采样值跳动问题?
957 浏览 1 评论
STM32进行DMA数据转运,为什么只有A组最后一位数据被转运到B组去?
1461 浏览 2 评论
1775 浏览 3 评论
1373 浏览 0 评论
嵌入式开发 Win11安装ST-Link 提示 设备描述符请求失败 怎么处理?
1512 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-23 03:21 , Processed in 1.540283 second(s), Total 109, Slave 89 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号