一種輕便的裸機(jī)多任務(wù)實(shí)現(xiàn)方法
時間:2021-08-19 15:51:25
手機(jī)看文章
掃描二維碼
隨時隨地手機(jī)看文章
[導(dǎo)讀]關(guān)注「嵌入式大雜燴」,選擇「星標(biāo)公眾號」一起進(jìn)步!來源:嵌入式實(shí)驗(yàn)基地前言你是否還在為一大堆任務(wù)放在while中,通過一個個標(biāo)志,做一大堆if...else...switch...case...煩惱,想跑個freertos或者ucos,發(fā)現(xiàn)芯片空間有限,添加不進(jìn)去了...那本文小...
關(guān)注「嵌入式大雜燴」,選擇「星標(biāo)公眾號」一起進(jìn)步!
添加(創(chuàng)建)任務(wù)
來源:嵌入式實(shí)驗(yàn)基地
前言
你是否還在為一大堆任務(wù)放在while中,通過一個個標(biāo)志,做一大堆if...else...switch...case...煩惱,想跑個freertos或者ucos,發(fā)現(xiàn)芯片空間有限,添加不進(jìn)去了...那本文小飛哥推薦你一種裸機(jī)多任務(wù)的實(shí)現(xiàn)方法,讓你告別繁瑣的while(1),有錯誤之處,煩請指出,一起交流~模型分析
剛開始寫代碼的時候,習(xí)慣這種寫法,這種方法首先是沒有問題的,但是在實(shí)時性方面可能會差那么點(diǎn)意思,比如,任務(wù)2是需要頻繁刷新的任務(wù),任務(wù)1不是很緊急,但是執(zhí)行時間比較長,那么就只能等待任務(wù)1執(zhí)行完才會去執(zhí)行任務(wù)2,任務(wù)2的數(shù)據(jù)刷新不及時。隨著任務(wù)的增多,這種完全等待一個任務(wù)完成再去執(zhí)行下一個任務(wù)的弊端會體現(xiàn)的更加明顯。??while?(1)
??{
????if?(task_flag1)
????{
??????task_flag1?=?0;
??????task01();//任務(wù)1
????}
????else?if?(task_flag2)
????{
??????task_flag2?=?0;
??????task02();//任務(wù)2
????}
????else?if?()
????{
????}
????...?else...
????{
??????taskn();//任務(wù)n
????}
??}
用過freertos或者其他系統(tǒng)的小伙伴一定知道,對于多任務(wù)的處理讓系統(tǒng)運(yùn)行看起來系統(tǒng)似乎是“并行”的,那么受限于單片機(jī)資源的情況下,能不能實(shí)現(xiàn)類似的功能,答案是肯定的,接下來就一起來聊聊如何實(shí)現(xiàn)。其實(shí),在日常的開發(fā)中我們已經(jīng)有用到過這種思想,比如我們需要在不影響任務(wù)執(zhí)行的情況下,在while(1)循環(huán)中實(shí)現(xiàn)LED 周期閃爍,提示系統(tǒng)正常運(yùn)行,用定時器當(dāng)然可以。。。今天不聊定時器,就用點(diǎn)比較接地氣的來舉例:?ledFlashCount ;
??if?(ledFlashCount?%?500?==?0)
??{
????ledFlashCount?=?0;
????HAL_GPIO_TogglePin(LED_GPIO_Port,?led_pin);
??}
??HAL_Delay(1);
如果直接延時500ms,想想while(1)會怎么樣,老板看了直接走人~,所以我們采用一種時間分割的方式,每次執(zhí)行1ms,到500次時,執(zhí)行相應(yīng)功能,這樣雖然還有1ms的阻塞延時,但想比于500ms,顯然是個巨大的飛躍。根據(jù)上面的思想,我們也可以采取時間分割的方式去處理不同的任務(wù),把一個完整的任務(wù)分割成一段一段時間片,單次執(zhí)行一段,不斷周期性掃描,如此一來,我們就能夠保證任務(wù)能夠得到較為及時的刷新,在CSDN上有個小伙伴描述的挺不錯。一個任務(wù)的線程:假設(shè)一個任務(wù)的執(zhí)行代碼有50步,通常編程只會一次執(zhí)行完畢,但是我們現(xiàn)在需要想想,因?yàn)槲覀儠舆@個任務(wù)總占用著ALU的時間而影響其他任務(wù)的執(zhí)行效果,所以就可以對任務(wù)進(jìn)行劃分,把它分為5份,每份10步,這樣我們每次執(zhí)行其中的一個程序片–每次正在運(yùn)行的程序片我們稱為線程。(CSDN博客:https://blog.csdn.net/qq_37272520/article/details/88916568)代碼實(shí)現(xiàn)
首先定義一個跟任務(wù)相關(guān)的結(jié)構(gòu)體,Delay正是時間片執(zhí)行的時長,Period是任務(wù)的執(zhí)行周期//?------?Public?data?type?declarations?----------------------------
//?User-defined?type?to?store?required?data?for?each?task
typedef?struct
{
???//?Pointer?to?the?task
???//?(must?be?a?'uint32_t?(void)'?function)
???uint32_t?(*pTask)(void);
???//??void?(*pTask)?(void);
???//?Delay?(ticks)?until?the?task?will?(next)?be?run
???uint32_t?Delay;
???//?Interval?(ticks)?between?subsequent?runs.
???uint32_t?Period;
}?sTask_t;
添加(創(chuàng)建)任務(wù)
//?Add_Task
void?SCH_Add_Task(uint32_t?(*pTask)(),
??????????????????const?uint32_t?DELAY,
??????????????????const?uint32_t?PERIOD)
{
???uint32_t?Task_id?=?0;
???//?Check?pre-conditions?(START)
???//?First?find?a?gap?in?the?array?(if?there?is?one)
???while?((SCH_tasks_g[Task_id].pTask?!=?SCH_NULL_PTR)?