這麼簡單做夢能笑醒,四部教你單片機實現真正的多線程的最優解

2022-04-14     大方老師單片機

原標題:這麼簡單做夢能笑醒,四部教你單片機實現真正的多線程的最優解

這麼簡單做夢能笑醒,四部教你單片機實現真正的多線程最優解

可以參考我的開源項目:基於循環時間的跨平台多任務管理系統(可用MCS51STM32等單片機)

1.簡介

1.1系統簡介

基於循環時間的跨平台任務管理系統(可用MCS51STM32等單片機)

///插播一條:我自己在今年年初錄製了一套還比較系統的入門單片機教程,想要的同學找我拿就行了免費的,私信我就可以~點我頭像黑色字體加我也能領取哦。最近比較閒,帶做畢///

1.2文件目錄說明

·TaskManager_cc語言實現的任務管理系統

·TaskManager_cppc++實現的任務管理系統

·Demo:提供多種示例,涵蓋電腦模擬器MSVCSTM328081等多種運行環境

2.用法C語言版)

2.1 API用法

系統配置TaskManager_config.h):

·MAX_TASK_NUM:最大任務數量,默認10個,根據自己的需要修改

·SYS_CYCLE_TIME:系統的循環時間(單位ms),默認1,表1ms

【注】MSVCSYS_CYCLE_TIME只能1,系統循環時間1s

·編譯器:目前支持的編譯器ARM_KILL (AC5AV6)WIN_MSVC

API接口TaskManager_c):

·TaskMsg:【結構體】任務信息,結構體成員任務函數,開始時間,周期時間,運行次數PID

任務函數:只能是無參數,無返回值的函數,不能是阻塞函數

開始時間:任務開始運行的時間,START_NOW表示立即開始運行

周期時間:任務每周期時間運行一次

運行次數:任務需要運行的次數,RUN_FOREVER表示無窮次

PID:任務編號號,初始化的時候傳PID_INIT

·void TM_init():系統初始化

·uint32_t TM_add_task(TaskMsg* new_task_msg):添加任務

·void TM_kill_by_PID(uint32_t PID):通過任務序號刪除任務

·void TM_kill_by_taskmsg(TaskMsg* task_msg):通過任務信息刪除任務

·void TM_run(void):運行系統

示例代1

#include "taskmanager.h"

#include "TaskManager_config.h"

#include "stdio.h"

//1

void task1(void)

{

printf("task1!\n");

}

//2

void task2(void)

{

printf("task2!\n");

}

void main(void)

{

TM_init();

//1立即啟動,2ms中運行一次,無休無止的運行

TaskMsg tasks_msg1 = { task1,START_NOW,2,RUN_FOREVER,0 };

TM_add_task(&tasks_msg1);

//21ms之後啟動,4ms運行一次,運5次自動結束

TaskMsg tasks_msg2 = { task2,1,4,5,0 };

TM_add_task(&tasks_msg2);

while (1)

{

//任務管理器啟動

TM_run();

}

}

示例代2[Demo/MSVC/c_language]

#include "../TaskManager/taskmanager.h"

#include "../TaskManager/TaskManager_config.h"

#include "stdio.h"

void task0(void)

{

static i = 1;

printf_s("\n%d:", i);

i++;

}

void task1(void)

{

printf_s("task1!");

}

void task2(void)

{

printf_s("task2!");

}

void main(void)

{

TM_init(1);

TaskMsg tasks_msg0 = { task0,START_NOW,1,RUN_FOREVER,0 };

int PID0 = TM_add_task(&tasks_msg0);

TaskMsg tasks_msg1 = { task1,START_NOW,2,RUN_FOREVER,0 };

int PID1 = TM_add_task(&tasks_msg1);

TaskMsg tasks_msg2 = { task2,START_NOW,4,RUN_FOREVER,0 };

int PID2 = TM_add_task(&tasks_msg2);

while (1)

{

TM_run();

if (get_systime() > 10)

tasks_msg1.period = 1;

if (get_systime() > 20)

TM_kill_by_PID(PID1);

if (get_systime() > 30)

TM_kill_by_taskmsg(&tasks_msg2);

if (get_systime() > 40)

return;

}

}

運行結:

1:task1!task2!

2:

3:task1!

4:

5:task1!task2!

6:

7:task1!

8:

9:task1!task2!

10:

11:task1!

12:

13:task1!task2!

14:task1!

15:task1!

16:task1!

17:task1!task2!

18:task1!

19:task1!

20:task1!

21:task2!

22:

23:

24:

25:task2!

26:

27:

28:

29:task2!

30:

31:

32:

33:

34:

35:

36:

37:

38:

39:

40:

C:\Users\Harry\Desktop\TaskManager\Demo\MSVC\c_language\Debug\c_language.exe ( 41888)已退出,返回代碼: 0

若要在調試停止時自動關閉控制台,請啟->->調->調試停止時自動關閉控制

按任意鍵關閉此窗...

2.2移植方法

TaskManager_c添加到程序目錄下,引taskmanager.hTaskManager_config.hsystime.h並配置時鐘即可。

以移STM32F107為例,說明如下:

Step1:添加項目文件

·c文件到項目目錄

·添加頭文件路徑

Step2:更改系統頭文件

TaskManager_config.h,查看如下代碼

//跨平台移植,處理編譯器

#ifdef ARM_KILL // kill編譯器

#include "stm32f10x_conf.h"

#endif

stm32f10x_conf.h換成系統相關的文件(標準庫)

如果使HAL庫,請根據以下內容自行修改

·uint32_tuint8_t等數據類型定義

·系統時鐘初始化,根據情況,更TM_init()函數SysTick_Config(SYS_CYCLE_TIME * 72000000 / 1000);,完成系統初始化

Step3:更改滴答計時器的初始化

stm32f10x_it.c中,覆蓋原有SysTick_Handler中斷服務函數

#include "systime.h"

void SysTick_Handler(void)

{

update_systime();

}

3.系統原理【有機會重寫】

·任務狀態:系統在一個循環時SYS_CYCLE_TIME內,根據時間判斷任務是否處於就緒狀態

判斷依據:每個任務都有一個【下次開始時間】的屬性,判斷該值是否等於系統現在的時間

for (uint32_t PID=0; PID

{

if (task_list[PID]->start_time == systime)

{

; //執行相應任務

}

}

·任務執行:系統在一個循環時SYS_CYCLE_TIME內,執行完所有就緒任務,並更新所有任務下次執行的時間

所以,循環時間不能太小,否則系統溢出造成未知錯誤

·其他:在一個循環時間內,如果所有任務執行完,還有額外的時間,系統空轉。

4.碎碎念

4.1 TODO

歡迎大家一起完成!

·STM32標準庫版本

· HAL庫版本

·c++版本程序

·支持帶形參的任務

·為更多平台提供移 demo

4.2 開源地址:

GitHub - sunshineharry/TaskManager: A cross-platform(STM32, MCS51, WIN, et al.) multitasking management system based on cycle time.基於循環時間的跨平台多任務管理系統(可用MCS51STM32等單片機)

文章來源: https://twgreatdaily.com/zh-my/05f81cbdb9802a12a2de0e59be7eeaaa.html