"); //-->
Author: chenzhufly
Email: chenzhufly@126.com
2010-05-04
这篇我将来玩玩多线程操作,体会一下其中的乐趣。实际上这也不能严格意义上称为多线程,只不过封装的比较好,感觉和多线程差不多,可以实现多任务而已。不过这还是需要您深入的研究才会明白的。欢迎您深入研究,欢迎您分享您的心得! Let’s go……………………….
一. 为什么需要用多线程
个人感觉是代码清晰,具有层次感,可读性强,增加任务或删减任务都很方便。JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
二. 为什么选择Protothreads
Protothrcads是由瑞典计算机科学研究所的科学家Adam Dunkels所创的一种新的线程编程方法。特别适用于资源受限的系统,非常适合我们的LPC1343,呵呵,这也是我选择它的原因。
欲了解详情,请访问主页:http://www.sics.se/~adam/pt/ 同时可下载相关源码!先介绍一下Protothreads吧,然大家有个直观的认识。
Protothreads具有的特性:
1. Very small RAM overhead - only two bytes per protothread and no extra stacks
非常少的RAM资源,每个Protothread仅需要2个字节,没有额外的栈
2. Highly portable - the protothreads library is 100% pure C and no architecture specific assembly code
很强的移植性 - protothreads库以纯C语言实现,无硬件依赖性
3. Can be used with or without an OS
可以用于有操作系统或无操作系统的场合
4. Provides blocking wait without full multi-threading or stack-switching
支持阻塞操作且没有栈的切换
Protothreads的典型应用:
1. Memory constrained systems
内存紧张的系统
2. Event-driven protocol stacks
时间驱动型协议栈,比如著名的uIP使用的就是Protothreads协议栈
3. Small embedded systems
小的嵌入式系统
4. Sensor network nodes
传感器网络节点
5. Portable C applications
具有移植性的c应用
接着我们从主页上下载pt-1.4.tar.gz并解压,目录结构如下图所示:
从目录中可以看出,主要是5个h文件:
lc-addrlabels.h : 以字符串方式实现Protothreads系统,占用的ram可能会多些
lc-switch.h :以标准C的switch结构实现Protothreads系统(默认)
lc.h :选择lc-addrlabels.h或lc-switch.h两种实现Protothreads系统
pt.h :在实际应用中一般只包含此文件就行了
pt-sem.h :附加的信号量操作的支持,不需要的话则不必包含他
其他三个是例子程序,可以作为系统设计很好的参考!
我在这里只不过只是点一个LED而已,所以理所当然的只包含了一个pt.h文件,代码结构如图所示:
这个时候如果点编译工程的话,会出错的,如下图所示; 怎么办呢LLLLLL
明明目录底下是有lc.h文件,为什么还说没有包含,气愤啊!!!
研究了半天发现,原来是忘了增加include路径,那么又怎么增加新的include路径呢?看到编译器右下角有个quick setting没?点它,出下以下界面。看到Include Paths没?呵呵,就是在这里设置!然后一切顺利。。。。J
经过简要的修改,编译下载,这个时候你就可以看到LED很欢快的闪起来啦!!
到这里还是简要的看看pt.h都实现了啥吧,具体的还是麻烦您自己去看看手册,哈哈!
pt.h中的宏定义:
PT_INIT(pt) 初始化任务变量,只在初始化函数中执行一次就行
PT_BEGIN(pt) 启动任务处理,放在函数开始处
PT_END(pt) 结束任务,放在函数的最后
PT_WAIT_UNTIL(pt, condition) 等待某个条件(条件可以为时钟或其它变量,IO等)如果成立,继续;否则直接退出本函数,下一次进入本 函数就直接跳到这个地方判断。
PT_WAIT_WHILE(pt, cond) 和上面一个一样,只是条件取反了
PT_WAIT_THREAD(pt, thread) 等待一个子任务执行完成
PT_SPAWN(pt, child, thread) 新建一个子任务,并等待其执行完退出
PT_RESTART(pt) 重新启动某个任务执行
PT_EXIT(pt) 任务后面的部分不执行,直接退出重新执行
PT_YIELD(pt) 锁死任务
PT_YIELD_UNTIL(pt, cond) 锁死任务并在等待条件成立,恢复执行
在pt中一共定义四种线程状态,在任务函数退出到上一级函数时返回其状态
PT_WAITING 等待
PT_EXITED 退出
PT_ENDED 结束
PT_YIELDED 锁死
废话就不多说,上代码才是王道!
三. 代码示例
这个代码是在pt-1.4中自带的example-small.c文件的基础上做的一些修改,主要是实现2个线程,一个线程做延时,一个线程做点LED操作。
#include "LPC13xx.h"
#include "gpio.h"
#include "config.h"
#include "pt.h" //包含的头文件
static int protothread1_flag, protothread2_flag;
int i;
char j=0;
static int
protothread1(struct pt *pt) //线程1,完成LED操作,每进一次,IO取反
{
PT_BEGIN(pt); //开始线程
while(1) {
protothread2_flag = 0;
protothread1_flag = 1;
j= ~j;
GPIOSetValue( LED_PORT, LED_BIT, j );
}
PT_END(pt); //接触线程
}
static int
protothread2(struct pt *pt) //线程2,完成延时操作
{
PT_BEGIN(pt);
while(1) {
protothread2_flag = 1;
PT_WAIT_UNTIL(pt, protothread1_flag != 0); //等待条件
protothread1_flag = 0;
for(i=0;i<500000;i++);
}
PT_END(pt);
}
static struct pt pt1, pt2;
int
main(void)
{
GPIOInit();
GPIOSetDir( LED_PORT, LED_BIT, 1 );
PT_INIT(&pt1); //初始化线程1
PT_INIT(&pt2); //初始化线程2
while(1) {
protothread1(&pt1); //调用线程1
protothread2(&pt2); //调用线程2
}
}
LED是不是又闪起来了?这里你学到了什么了呢?你是不是有更好的应用呢?或者更好的想法呢?欢迎您的参与,欢迎您的分享!
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。