久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 23885|回復: 14
收起左側(cè)

玩兒大了~給arduino上操作系統(tǒng)了~!

  [復制鏈接]
ID:112317 發(fā)表于 2016-4-9 20:08 | 顯示全部樓層 |閱讀模式
恩。。好久沒發(fā)帖了,不過這幾天也沒閑著
前幾天我在求助區(qū)發(fā)了個關(guān)于定時器的問題,結(jié)果沒有讓我滿意的答案
于是自己百度+谷歌,終于找到了一個非常強大的庫--ProtoThreads!
一個非常強大的多任務庫,非常適合arduino這種資源非常有限的單片機
別急,先上一段簡單的代碼look look
  1.     #include <pt.h>
  2.      
  3.     static int counter1,counter2,state1=0,state2=0;
  4.      
  5.     static int protothread1(struct pt *pt)
  6.     {  
  7.       PT_BEGIN(pt);  
  8.       while(1)
  9.       {  
  10.         PT_WAIT_UNTIL(pt, counter1==1);
  11.         digitalWrite(12,state1);
  12.         state1=!state1;
  13.         counter1=0;   
  14.       }
  15.       PT_END(pt);
  16.     }
  17.      
  18.      
  19.     static int protothread2(struct pt *pt)
  20.     {
  21.       PT_BEGIN(pt);
  22.       while(1) {   
  23.         PT_WAIT_UNTIL(pt, counter2==5);
  24.         counter2=0;
  25.         digitalWrite(13,state2);
  26.         state2=!state2;
  27.       }
  28.       PT_END(pt);
  29.     }
  30.      
  31.      
  32.     static struct pt pt1, pt2;
  33.     void setup()
  34.     {
  35.      
  36.       pinMode(12,OUTPUT);
  37.       pinMode(13,OUTPUT);
  38.       PT_INIT(&pt1);
  39.       PT_INIT(&pt2);
  40.     }
  41.      
  42.     void loop ()
  43.     {
  44.         protothread1(&pt1);
  45.         protothread2(&pt2);
  46.         delay(1000);
  47.         counter1++;
  48.         counter2++;
  49.       }
復制代碼

此段代碼演示了如何使用PT庫來實現(xiàn)12、13腳led分別隔1秒、5秒閃爍,已經(jīng)在arduino09上測試通過
sorry,無注釋。。別急,這只是個演示
這篇文章會不斷更新,分別講述PT庫的原理和應用
讓大家能開發(fā)出更復雜的程序

好介紹開始了~
Protothread是專為資源有限的系統(tǒng)設計的一種耗費資源特別少并且不使用堆棧的線程模型,其特點是:  
◆ 以純C語言實現(xiàn),無硬件依賴性;  
◆ 極少的資源需求,每個Protothread僅需要2個額外的字節(jié);  
◆ 可以用于有操作系統(tǒng)或無操作系統(tǒng)的場合;  
◆ 支持阻塞操作且沒有棧的切換。
使用Protothread實現(xiàn)多任務的最主要的好處在于它的輕量級。每個Protothread不需要擁有自已的堆棧,所有的Protothread 共享同一個堆棧空間,這一點對于RAM資源有限的系統(tǒng)尤為有利。相對于操作系統(tǒng)下的多任務而言,每個任務都有自已的堆棧空間,這將消耗大量的RAM資源,而每個Protothread僅使用一個整型值保存當前狀態(tài)。  
咱們來結(jié)合一個最簡單的例子來理解ProtoThreads的原理吧,就拿上面的閃爍燈代碼來說
  1.     #include <pt.h>//ProtoThreads必須包含的頭文件

  2.     static int counter1,counter2,state1=0,state2=0; //counter為定時計數(shù)器,state為每個燈的狀態(tài)

  3.     static int protothread1(struct pt *pt) //線程1,控制燈1
  4.     {  
  5.       PT_BEGIN(pt);  //線程開始
  6.       while(1) //每個線程都不會死
  7.       {  
  8.         PT_WAIT_UNTIL(pt, counter1==1); //如果時間滿了1秒,則繼續(xù)執(zhí)行,否則記錄運行點,退出線程1
  9.         digitalWrite(12,state1);
  10.         state1=!state1;//燈狀態(tài)反轉(zhuǎn)
  11.         counter1=0; //計數(shù)器置零
  12.       }
  13.       PT_END(pt); //線程結(jié)束
  14.     }


  15.     static int protothread2(struct pt *pt) //線程2,控制燈2
  16.     {
  17.       PT_BEGIN(pt); //線程開始
  18.       while(1) {    //每個線程都不會死
  19.         PT_WAIT_UNTIL(pt, counter2==5); //如果時間滿了5秒,則繼續(xù)執(zhí)行,否則記錄運行點,退出線程2
  20.         counter2=0;  //計數(shù)清零
  21.         digitalWrite(13,state2);
  22.         state2=!state2; //燈狀態(tài)反轉(zhuǎn)
  23.       }
  24.       PT_END(pt);  //線程結(jié)束
  25.     }


  26.     static struct pt pt1, pt2;
  27.     void setup()
  28.     {

  29.       pinMode(12,OUTPUT);
  30.       pinMode(13,OUTPUT);
  31.       PT_INIT(&pt1);  //線程1初始化
  32.       PT_INIT(&pt2);  //線程2初始化
  33.     }

  34.     void loop () //這就是進行線程調(diào)度的地方
  35.     {
  36.         protothread1(&pt1);  //執(zhí)行線程1
  37.         protothread2(&pt2);  //執(zhí)行線程2
  38.         delay(1000);  //時間片,每片1秒,可根據(jù)具體應用設置大小
  39.         counter1++;
  40.         counter2++;
  41.       }
復制代碼

看上面的代碼,你會發(fā)現(xiàn)很多大寫的函數(shù),其實那些都是些宏定義(宏定義用大寫是約定俗成的..),如果把這些宏都展開你就能更好的理解他的原理了:
  1.     #include <pt.h>//ProtoThreads必須包含的頭文件

  2.     static int counter1,counter2,state1=0,state2=0; //counter為定時計數(shù)器,state為每個燈的狀態(tài)

  3.     static int protothread1(struct pt *pt) //線程1,控制燈1
  4.     {  
  5.       { char PT_YIELD_FLAG = 1;
  6.                     switch((pt)->lc) {//用switch來選擇運行點
  7.                      case 0: //此乃初始運行點,線程正常退出或剛開始都從這開始運行
  8.                                     while(1) //每個線程都不會死
  9.                                     {
  10.                                             do {      
  11.                                                             (pt)->lc=12;//記錄運行點
  12.                                                             case 12:
  13.                                                                     if(!(counter1==1))
  14.                                                                     {
  15.                                                                             return PT_WAITING;        //return 0
  16.                                                                     }                                               
  17.                                             } while(0)
  18.                                             digitalWrite(12,state1);
  19.                                             state1=!state1;//燈狀態(tài)反轉(zhuǎn)
  20.                                             counter1=0; //計數(shù)器置零
  21.                                     }
  22.                     }
  23.       PT_YIELD_FLAG = 0;
  24.       pt->lc=0;
  25.       return PT_ENDED; // return 1
  26.       }
  27.     }


  28.     static int protothread2(struct pt *pt) //線程2,控制燈2
  29.     {
  30.       { char PT_YIELD_FLAG = 1;
  31.                     switch((pt)->lc) {//用switch來選擇運行點
  32.                      case 0:     //線程開始
  33.                                     while(1) //每個線程都不會死
  34.                                     {
  35.                                             do {      
  36.                                                             (pt)->lc=39;
  37.                                                             case 39://記錄運行點
  38.                                                                     if(!(counter2==5))
  39.                                                                     {
  40.                                                                             return PT_WAITING;        //return 0
  41.                                                                     }                                               
  42.                                             } while(0)
  43.                                             counter2=0;  //計數(shù)清零
  44.                                             digitalWrite(13,state2);
  45.                                             state2=!state2; //燈狀態(tài)反轉(zhuǎn)
  46.                                     }
  47.                     }
  48.                     PT_YIELD_FLAG = 0;
  49.                     pt->lc=0;
  50.                     return PT_ENDED; // return 1
  51.             }
  52.     }


  53.     static struct pt pt1, pt2;
  54.     void setup()
  55.     {

  56.       pinMode(12,OUTPUT);
  57.       pinMode(13,OUTPUT);
  58.       pt1->lc=0;  //線程1初始化
  59.       pt2->lc=0;  //線程2初始化
  60.     }

  61.     void loop () //這就是進行線程調(diào)度的地方
  62.     {
  63.         protothread1(&pt1);  //執(zhí)行線程1
  64.         protothread2(&pt2);  //執(zhí)行線程2
  65.         delay(1000);  //時間片,每片1秒,可根據(jù)具體應用設置大小
  66.         counter1++;
  67.         counter2++;
  68.       }
復制代碼

好了,終于擴展完了。。
  分析一下上面的代碼,就知道其實ProtoThreads是利用switch case 來選擇運行點的,每個線程中的堵塞,其實就是判斷條件是否成立,不成立則return,所以說每個線程都很有雷鋒精神,舍己為人,呵呵。有一點要注意那就是每個線程只能夠在我們指定的地方堵塞,至于堵塞點,那就要看具體應用了。
  由于線程是反復被調(diào)用的,因此,寫程序的時候不能像寫一般的函數(shù)一樣使用局部變量,因為每次重新調(diào)用都會把變量初始化了,如果要保持變量,可以把它定義為static的
  在pt.h中定義了很多功能:
PT_INIT(pt)   初始化任務變量,只在初始化函數(shù)中執(zhí)行一次就行
PT_BEGIN(pt)   啟動任務處理,放在函數(shù)開始處
PT_END(pt)   結(jié)束任務,放在函數(shù)的最后
PT_WAIT_UNTIL(pt, condition) 等待某個條件(條件可以為時鐘或其它變量,IO等)成立,否則直接退出本函數(shù),下一次進入本     函數(shù)就直接跳到這個地方判斷
PT_WAIT_WHILE(pt, condition)  和上面一個一樣,只是條件取反了
PT_WAIT_THREAD(pt, thread) 等待一個子任務執(zhí)行完成
PT_SPAWN(pt, child, thread) 新建一個子任務,并等待其執(zhí)行完退出
PT_RESTART(pt)   重新啟動某個任務執(zhí)行
PT_EXIT(pt)   任務后面的部分不執(zhí)行,直接退出重新執(zhí)行
PT_YIELD(pt)   鎖死任務
PT_YIELD_UNTIL(pt, cond) 鎖死任務并在等待條件成立,恢復執(zhí)行
在pt中一共定義四種線程狀態(tài),在任務函數(shù)退出到上一級函數(shù)時返回其狀態(tài)
PT_WAITING  等待
PT_EXITED  退出
PT_ENDED  結(jié)束
PT_YIELDED  鎖死

比如PT_WAIT_UNTIL(pt, condition) ,通過改變condition可以運用的非常靈活,如結(jié)合定時器的庫,把condition改為定時器溢出,那就是個時間觸發(fā)系統(tǒng)了,再把condition改為其他條件,就是事件觸發(fā)系統(tǒng)了
暫時寫這么多吧
***2014.3.16  這里有一另一篇關(guān)于protothread的文章,寫的挺好,感謝網(wǎng)友vincent_jie 的推薦:
http://www.kankanews.com/ICkengine/archives/107079.shtml



Devuino代表在 Arduino基礎上的開發(fā)平臺,Muti代表多線程


ProtoThread相比其他RTOS有什么突出的優(yōu)點呢?貌似它已經(jīng)停止更新了。

優(yōu)點挺多的
1、超輕量級,他的庫基本上都是些宏定義,大小可以忽略不計,而且每個線程只占用2個字節(jié)
2、無機器碼,純c實現(xiàn),所以可移植性很好
3、無堆棧
4、簡單使用可以只把他當個調(diào)度程序,復雜點也能把他當操作系統(tǒng)來使
恩。。其實我也才接觸。。了解不全
現(xiàn)在邊研究邊更新吧,主要是這幾天太忙了。。
PT作者的首頁http://www.sics.se/~adam/pt/

問:新手,求教一下,看了下示例,不知這定時準確度如何?執(zhí)行中斷后,這定時器時間是否會延長?
答:上面的示例只是用了一個delay()來設定時間片,用來演示一個簡單的程序罷了
寫程序最好不要用delay,一delay程序就不能干別的事了,最好的辦法是一遇到要delay就去干別的事,時間到了再接著運行剛才的代碼,所以PT結(jié)合定時器可以很大的提高程序的實時性
上面的定時器庫采用的是內(nèi)部定時器,至于是TCN幾我也沒仔細看,不過他們與PT結(jié)合的不是很好,下次我再發(fā)一個定時器庫吧
中斷肯定會有影響的,只是影響的大小罷了,所以在中斷里一般都不會放大的程序,我用中斷一般都是用來計數(shù)、改變狀態(tài),這點時間可以忽略
附錄:
官方原版庫1.4
pt-1.4.zip (256.5 KB, 下載次數(shù): 50)
arduino版1.4.01
ProtoThreads.rar (12.31 KB, 下載次數(shù): 56)
新發(fā)現(xiàn)了幾個定時器庫,還沒來得及試用,都是arduino Library上下載的,大家可以先拿過去試試

SimpleTimer.rar (4.27 KB, 下載次數(shù): 18)
TimedAction-1_6.zip (3.92 KB, 下載次數(shù): 20)
TimerOne-v9.zip (5.71 KB, 下載次數(shù): 18)


評分

參與人數(shù) 1黑幣 +15 收起 理由
xljxlj + 15 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:165672 發(fā)表于 2017-2-21 09:55 | 顯示全部樓層
謝謝分享!學些
回復

使用道具 舉報

ID:158981 發(fā)表于 2017-3-7 22:03 | 顯示全部樓層
非常感謝樓主分享
回復

使用道具 舉報

ID:152999 發(fā)表于 2017-3-12 20:40 | 顯示全部樓層
謝謝分享,怎么用呢?
回復

使用道具 舉報

ID:174361 發(fā)表于 2017-3-22 00:26 | 顯示全部樓層
學習了
回復

使用道具 舉報

ID:187329 發(fā)表于 2017-4-8 08:49 | 顯示全部樓層
感謝分享,最近在學習arduino,的確資源緊缺啊
回復

使用道具 舉報

ID:224986 發(fā)表于 2017-8-5 15:31 | 顯示全部樓層
不造這個一樣嗎

ProtoThreads.rar

56.95 KB, 下載次數(shù): 7, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:239822 發(fā)表于 2017-10-21 19:38 | 顯示全部樓層
貌似arduino能用的多線程也就這個了,只是這個多線程任務管理功能還有待加強,做的更精細點,極可能的減少線程假死或者沖突,沒辦法,誰讓單片機的內(nèi)存太小呢
回復

使用道具 舉報

ID:243053 發(fā)表于 2017-10-26 10:29 | 顯示全部樓層
謝謝分享!黑幣不足啊
回復

使用道具 舉報

ID:244729 發(fā)表于 2017-10-31 21:28 | 顯示全部樓層
謝謝分享!黑幣不足
回復

使用道具 舉報

ID:252134 發(fā)表于 2017-11-22 14:27 | 顯示全部樓層
16位單片機還能玩這么強,膜拜,大神
回復

使用道具 舉報

ID:255376 發(fā)表于 2017-12-6 22:01 | 顯示全部樓層
謝謝分享!
回復

使用道具 舉報

ID:39808 發(fā)表于 2018-1-21 10:47 來自觸屏版 | 顯示全部樓層
想知道這個庫是否為通用庫,比如可以在不同的環(huán)境好不同核心使用。
回復

使用道具 舉報

ID:39808 發(fā)表于 2018-1-21 10:50 來自觸屏版 | 顯示全部樓層
我現(xiàn)在玩arduino用的是stm32的核,外設和avr完全不同,目前使用的系統(tǒng)是freertos,這個系統(tǒng)好處是標準系統(tǒng),功能完善,但是缺點顯而易見,占空間比較大,所以不懂樓主這個系統(tǒng)能否通用,占用空間如何?
回復

使用道具 舉報

ID:10784 發(fā)表于 2018-6-9 18:47 | 顯示全部樓層
謝謝分享!好東西
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美色综合| 久久久91 | 在线看av的网址 | 国产精品夜间视频香蕉 | 一区二区三区在线 | 欧 | 日本精a在线观看 | 中文字幕在线视频一区二区三区 | 国产欧美一区二区三区日本久久久 | 一区二区三区久久 | 国产美女精品视频免费观看 | 国产精品视频一区二区三区不卡 | 日本在线一二 | 狠狠综合久久av一区二区小说 | 91av视频在线免费观看 | gav成人免费播放视频 | www.亚洲一区二区三区 | 国产成人一区二区三区久久久 | 99久久精品国产麻豆演员表 | 欧美一区二区综合 | 97超碰在线免费 | 亚洲精品一区二区三区中文字幕 | 黄色国产| 91在线视频免费观看 | 欧美理论片在线 | 四虎成人免费视频 | 欧美日韩在线观看视频网站 | 丁香色婷婷 | 欧美一级二级在线观看 | 日韩欧美精品一区 | 男女视频在线观看网站 | 午夜免费影视 | 日韩成年人视频在线 | 中文字幕 国产精品 | 9191在线播放 | 在线看av网址 | 精品久久久久久久人人人人传媒 | 国产亚洲一区二区三区在线观看 | 三级在线免费 | 手机看片在线播放 | 国产成人久久久 | 国产精品免费一区二区三区 |