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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 23658|回復: 14
收起左側

玩兒大了~給arduino上操作系統了~!

  [復制鏈接]
ID:112317 發表于 2016-4-9 20:08 | 顯示全部樓層 |閱讀模式
恩。。好久沒發帖了,不過這幾天也沒閑著
前幾天我在求助區發了個關于定時器的問題,結果沒有讓我滿意的答案
于是自己百度+谷歌,終于找到了一個非常強大的庫--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庫來實現12、13腳led分別隔1秒、5秒閃爍,已經在arduino09上測試通過
sorry,無注釋。。別急,這只是個演示
這篇文章會不斷更新,分別講述PT庫的原理和應用
讓大家能開發出更復雜的程序

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

  2.     static int counter1,counter2,state1=0,state2=0; //counter為定時計數器,state為每個燈的狀態

  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秒,則繼續執行,否則記錄運行點,退出線程1
  9.         digitalWrite(12,state1);
  10.         state1=!state1;//燈狀態反轉
  11.         counter1=0; //計數器置零
  12.       }
  13.       PT_END(pt); //線程結束
  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秒,則繼續執行,否則記錄運行點,退出線程2
  20.         counter2=0;  //計數清零
  21.         digitalWrite(13,state2);
  22.         state2=!state2; //燈狀態反轉
  23.       }
  24.       PT_END(pt);  //線程結束
  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 () //這就是進行線程調度的地方
  35.     {
  36.         protothread1(&pt1);  //執行線程1
  37.         protothread2(&pt2);  //執行線程2
  38.         delay(1000);  //時間片,每片1秒,可根據具體應用設置大小
  39.         counter1++;
  40.         counter2++;
  41.       }
復制代碼

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

  2.     static int counter1,counter2,state1=0,state2=0; //counter為定時計數器,state為每個燈的狀態

  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;//燈狀態反轉
  20.                                             counter1=0; //計數器置零
  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;  //計數清零
  44.                                             digitalWrite(13,state2);
  45.                                             state2=!state2; //燈狀態反轉
  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 () //這就是進行線程調度的地方
  62.     {
  63.         protothread1(&pt1);  //執行線程1
  64.         protothread2(&pt2);  //執行線程2
  65.         delay(1000);  //時間片,每片1秒,可根據具體應用設置大小
  66.         counter1++;
  67.         counter2++;
  68.       }
復制代碼

好了,終于擴展完了。。
  分析一下上面的代碼,就知道其實ProtoThreads是利用switch case 來選擇運行點的,每個線程中的堵塞,其實就是判斷條件是否成立,不成立則return,所以說每個線程都很有雷鋒精神,舍己為人,呵呵。有一點要注意那就是每個線程只能夠在我們指定的地方堵塞,至于堵塞點,那就要看具體應用了。
  由于線程是反復被調用的,因此,寫程序的時候不能像寫一般的函數一樣使用局部變量,因為每次重新調用都會把變量初始化了,如果要保持變量,可以把它定義為static的
  在pt.h中定義了很多功能:
PT_INIT(pt)   初始化任務變量,只在初始化函數中執行一次就行
PT_BEGIN(pt)   啟動任務處理,放在函數開始處
PT_END(pt)   結束任務,放在函數的最后
PT_WAIT_UNTIL(pt, condition) 等待某個條件(條件可以為時鐘或其它變量,IO等)成立,否則直接退出本函數,下一次進入本     函數就直接跳到這個地方判斷
PT_WAIT_WHILE(pt, condition)  和上面一個一樣,只是條件取反了
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_WAIT_UNTIL(pt, condition) ,通過改變condition可以運用的非常靈活,如結合定時器的庫,把condition改為定時器溢出,那就是個時間觸發系統了,再把condition改為其他條件,就是事件觸發系統了
暫時寫這么多吧
***2014.3.16  這里有一另一篇關于protothread的文章,寫的挺好,感謝網友vincent_jie 的推薦:
http://www.kankanews.com/ICkengine/archives/107079.shtml



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


ProtoThread相比其他RTOS有什么突出的優點呢?貌似它已經停止更新了。

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

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

評分

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

查看全部評分

回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

ProtoThreads.rar

56.95 KB, 下載次數: 7, 下載積分: 黑幣 -5

回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品丝袜日韩 | 两性午夜视频 | 不卡在线视频 | 婷婷久久五月 | 日本在线播放一区二区 | 正在播放国产精品 | 人人性人人性碰国产 | 精品麻豆剧传媒av国产九九九 | 日韩成人免费av | 18性欧美| 国产精品久久久久久久久久久久久 | 婷婷毛片 | 一区福利视频 | 亚洲精品久久久久久久久久久 | 欧美一级片在线看 | 久久久一二三区 | 秋霞国产 | 一区二区三区四区电影 | av香港经典三级级 在线 | 一区二区视频在线 | 日本福利视频免费观看 | 欧美在线视频一区二区 | 国产精品国产精品国产专区不片 | 久久久久精 | 亚洲欧美综合网 | 久久99这里只有精品 | 亚洲国产欧美日韩 | 国产欧美日韩精品在线观看 | 欧美视频在线一区 | 国产一区二区三区在线免费 | 九九热在线视频观看这里只有精品 | 国产无套一区二区三区久久 | 老牛嫩草一区二区三区av | 中文字幕中文字幕 | 国产不卡一区在线观看 | 韩日在线 | 国产在线网址 | 99精品久久 | 亚洲成人久久久 | 成人久久久 | 国产中文字幕网 |