protothread, 就是状态机!
本帖最后由 smset 于 2012-5-27 10:45 编辑protothread 是经典的状态机,只要看函数开头的switch(pt-﹥lc)进行散转,就一清二楚了。
因此说protothread是协程,实际很不准确,准确地说法是: protothread 就是状态机!
protothread使用行号代替人为设置的状态,如果使用1个Byte记忆状态,那么一个任务函数内代码行数不能超过255行,所以用了1个word来记忆.因此占用了两个字节.一个任务函数内代码行数不超过65535行(这完全够了).
这就是一个protothread任务消耗2个字节的原因: 就是状态变量的消耗. 只要使用状态机机制,谁能省掉这个呢?
protothread具备状态机的所有特性, 只要能使用状态机的地方,就可以使用protothread. 即可以单独使用,也可以结合其他多任务系统机制使用,也可以和时间调度触发联合使用
而protothread主要好处是: protothread任务函数的代码语法,无需人工设计各个状态, 非常类似于多线程环境下的任务代码,大大降低了代码的复杂度.
附带说下:
很多地方有说到protothread的,总提到protothread是协程,好像有很多问题,
但protothread根本不是协程,而是典型的状态机!
状态机的实时性本身不是问题,问题在于如何使用状态机这种机制
因此,protothread的实时性本身也根本不是问题,问题在于如何使用protothread
本帖最后由 BXAK 于 2012-5-30 00:15 编辑
看了LZ发了不少关于protothread的帖子,
还是一知半解的,要是提供个简单的程序实验就好了,
平时写程序也是用状态机原理,只是没有规范,
想看看按protothread写法会是怎样的,不知LZ是否可提供完整的简单实例(比如控制3个LED分别0.5s、1s、2s闪烁,最好是51的),有现成的完整简单实例直接上传也好 very interesting !!! BXAK 发表于 2012-5-30 00:13 static/image/common/back.gif
看了LZ发了不少关于protothread的帖子,
还是一知半解的,要是提供个简单的程序实验就好了,
平时写程序也 ...
传一个例子哦 不过是 VC++的 控制台程序。javascript:;
附件没法上传 就贴个 代码吧
#include <stdio.h>
#include <windows.h>
#include "pt.h"
static struct pt pt_h,pt_m,pt_s;
static int ihour=0,iminute=0,isecond=0;
static int c_s=0,c_m=0;
static int clk=0;
PT_THREAD(hour(struct pt *pt))
{
PT_BEGIN(pt);
PT_WAIT_UNTIL(pt,c_m==1);
c_m=0;
if(ihour==23)
ihour=0;
else
ihour++;
PT_END(pt);
}
PT_THREAD(minute(struct pt *pt))
{
PT_BEGIN(pt);
PT_WAIT_UNTIL(pt,c_s==1);
c_s=0;
if(iminute==59){
iminute=0;
c_m = 1;
}
else
iminute++;
PT_END(pt);
}
PT_THREAD(second(struct pt *pt))
{
PT_BEGIN(pt);
PT_WAIT_UNTIL(pt,clk==1);
clk=0;
if(isecond==59)
{
isecond=0;
c_s=1;
}
else
isecond++;
PT_END(pt);
}
int main(void)
{
printf("%d\n",__LINE__);
printf("%d\n",__LINE__);
printf("hello.pt\n");
PT_INIT(&pt_h);
PT_INIT(&pt_m);
PT_INIT(&pt_s);
while(1)
{
PT_SCHEDULE(hour(&pt_h));
PT_SCHEDULE(second(&pt_s));
PT_SCHEDULE(minute(&pt_m));
Sleep(1000);
clk=1;
Sysclr();
printf("Time---%d:%d:%d\n",ihour,iminute,isecond);
}
return 0;
} 楼主有protothread源码没,传一个 http://dunkels.com/adam/pt/download.html 源码是开源的,可网上搜。 本帖最后由 smset 于 2012-12-13 12:24 编辑
我已经基于这种原理,写了一个非常节省资源的调度器,已经无需pt源码了,参看另一个帖子:
http://www.amobbs.com/thread-5508723-6-1.html
/**********************************************************/
#include "STC89C51.h"
/****小小调度器开始**********************************************/
#define MAXTASKS 3
unsigned char currid;
unsigned char timers;
#define _SS static unsigned char lc=0; switch(lc){ case 0:
#define _EE ;}; lc=0;
#define WaitX(tickets) {lc=__LINE__; timers=tickets;} return ; case __LINE__:
#define RunTask(TaskName,TaskID) {currid=TaskID; if (timers==0){timers=255; TaskName();}}
#define CallSub(SubTaskName) WaitX(0); SubTaskName(); if (timers!=255) return;
/*****小小调度器结束*******************************************************/
sbit LED1 = P2^1;
sbit LED2 = P2^2;
void InitT0()
{
TMOD = 0x21;
IE |= 0x82;// 12t
TL0=0Xff;
TH0=0XDB;//22M---b7;
TR0 = 1;
}
void INTT0(void) interrupt 1 using 1
{
unsigned char i;
TL0=0Xff; //10ms 重装
TH0=0XDB;//b7;
for (i=0;i<MAXTASKS;i++){
if ((timers!=0)&&(timers!=255)) {
timers--;
}
}
}
voidtask1(){
_SS
while(1){
WaitX(50);
LED1=!LED1;
}
_EE
}
voidtask2(){
_SS
while(1){
WaitX(100);
LED2=!LED2;
}
_EE
}
void main()
{
InitT0();
while(1){
RunTask(task1,1);
RunTask(task2,2);
}
}
谢谢楼主分享 状态机是广泛的,协程是具体的,可以说任何程序都有状态机的思想和用法。
PT主要是模拟操作系统的编程方式 看看,有用 学习学习。。。。。 protothread 状态机 MARK
MARK
MARK 学习一下.. 好像为了做到高响应速度必须在长的任务里面多插入几个点? 有点晕... 多谢楼主分享! 学习了,谢谢楼主 斯郭依 喜欢楼主的小小调度器 学习了,谢谢楼主 了解一下。 对状态机还是蛮感兴趣的,我也在研究这些。 lc的数据类型用u8可能出问题(如果程序函数太多),最好是用u32 路过,支持一下{:hug:} 看看这篇文章吧:
http://www.kankanews.com/ICkengine/archives/107079.shtml
原理到实现,一步一步 探讨一个问题:
关于楼主位: “protothread使用行号代替人为设置的状态,如果使用1个Byte记忆状态,那么一个任务函数内代码行数不能超过255行,” 这句话
楼主的理解可能有问题,行号对应的是每一个任务 case __LINE__ 这行 ,也就是 WaitX 对应的行号,而不是任务里函数内代码的行号,1byte 表示最多255个任务,而不是“一个任务函数内代码行数不能超过255行”,其实任务函数内代码函数行数并不受限制,因为任务函数内的代码是在 case __LINE__: 运行,其实是switch的一个分支
反正我用着感觉不错 学习下。谢谢! 学习学习。。。。。
页:
[1]