吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

嵌入式軟件架構設計之任務調度

汽車電子技術 ? 來源:大橙子瘋嵌入式 ? 作者:大橙子瘋 ? 2023-02-15 14:44 ? 次閱讀

1、前言

嵌入式MCU軟件開發過程中,程序任務調度架構的搭建尤為重要,直接關系到該程序能支持多少功能(隨著功能越多系統響應能力越弱,好的任務調度架構能夠在保持相同的系統響應能力前提下支持更多的功能),下面介紹三種常用的程序任務調度框架設計方案:

2、程序框架設計

前后臺順序執行法

這是初學者們常用的程序框架設計方案,不用考慮太多東西,代碼簡單,或者對系統的整體實時性和并發性要求不高;初始化后通過 while(1){ } 或 for(;;){ } 循環不斷調用自己編寫完成的函數,也基本不考慮每個函數執行所需要的時間,大部分情況下函數中或多或少都存在毫秒級別的延時等待。

優點 :對于初學者來說,這是最容易也是最直觀的程序架構,邏輯簡單明了,適用于邏輯簡單,復雜度比較低的軟件開發。

缺點 :實時性低,由于每個函數或多或少存在毫秒級別的延時,即使是1ms,也會造成其他函數間隔執行時間的不同,雖然可通過定時器中斷的方式,但是前提是中斷執行函數花的時間必須短。當程序邏輯復雜度提升時,會導致后來維護人員的大腦混亂,很難理清楚該程序的運行狀態。

以下是我在學校期間做的寢室防盜系統的主函數代碼(當時也存在部分BUG,沒有解決。現在再看,其實很多問題,而且比較嚴重,比如中斷服務函數內竟然有3000ms延時,這太可怕了,還有串口發送等等;由于實時性要求不算太高,因此主函數中的毫秒級別延時對系統運行沒有多大影響,當然除BUG外;若是后期需要維護,那就是一個大工程,還不如推翻重寫):

int main(void)
 {    
    u8 temperature;          
    u8 humidity;   
    int a;
    delay_init();
    uart2_Init(9600);     
    TIM3_Int_Init(4999,7199);
    ds1302_init();
    while(DHT11_Init());    //DHT11初始化    
    a1602_init();        
    lcd12864_INIT();
    LcdInit();

    while(1)
    {
        for(a=0;a<11;a++)
        {
            num[a+3]=At24c02Read(a+2)-208;
            delay_us(10);                    
        }
        for(a=0;a<6;a++)
        {
            shuru[a]=At24c02Read(a+13)-208;
            delay_us(10);                
        }        
        delay_ms(10);  
        RED_Scan();
        Ds1302ReadTime();                    //讀取ds1302的日期時間
        shi=At24c02Read(0);                //讀取鬧鐘保存的數據
        delay_ms(10);
        fen=At24c02Read(1);                //讀取鬧鐘保存的數據            
        usart2_scan();                        //藍牙數據掃描
        usart2_bian();                        //藍牙處理數據
        nao_scan();
        k++;
        if(k<20)
        {
            if(k==1)
                LcdWriteCom(0x01);  //清屏
            LcdDisplay();                            //顯示日期時間
        }
        if(RED==0)
            RED_Scan();

        if(k>=20&&k<30)
        {
            if(k==20)
                LcdWriteCom(0x01);  //清屏
            Lcddisplay();                            //顯示溫濕度
            LcdWriteCom(0x80+6);    
            DHT11_Read_Data(&temperature,&humidity);    //讀取溫濕度值    
            Temp=temperature;Humi=humidity;
            LcdWriteData('0'+temperature/10);
            LcdWriteData('0'+temperature%10);
            LcdWriteCom(0x80+0X40+6);    
            LcdWriteData('0'+humidity/10);
            LcdWriteData('0'+humidity%10);
        }
        if(k==30)
            k=0;
        lcd12864();                                //顯示防盜鬧鐘狀態

    }        
}


//定時器3中斷服務程序
void TIM3_IRQHandler(void)   //TIM3中斷
{
    int i;
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //檢查TIM3更新中斷發生與否
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中斷標志 
        if(key1==1&&FEN-fen==0&&SHI-shi==0)                //時間一到鬧鐘響起
        {
            f=1;                        
        }
        else
        {
            f=0;
        }    
        if(USART_RX_BUF[0]=='R'&&USART_RX_BUF[1]=='I'&&USART_RX_BUF[2]=='N'&&USART_RX_BUF[3]=='G')
        {
            key0=1;
            for(i=0;i<17;i++)
            {
                USART_SendData(USART1, num[i]);//向串口1發送數據
                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
                USART_RX_STA=0;    
            }    
            delay_ms(3000);
            for(i=0;i<3;i++)
            {
                USART_SendData(USART1, num1[i]);//向串口1發送數據
                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
                USART_RX_STA=0;    
            }            
        }
    }
}

時間片論法

介于“前后臺順序執行法”和“操作系統”之間的一種程序架構設計方案。該設計方案需能幫助嵌入式軟件開發者更上一層樓,在嵌入式軟件開發過程中,若遇到以下幾點,那么該設計方案可以說是最優選擇,適用于程序較復雜的嵌入式系統;

  1. 目前的需求設計需要完全沒有必要上操作系統
  2. 任務函數無需時刻執行,存在間隔時間(比如按鍵,一般情況下,都需要軟件防抖,初學者的做法通常是延時10ms左右再去判斷,但10ms極大浪費了CPU的資源,在這段時間內CPU完全可以處理很多其他事情)
  3. 實時性有一定的要求

該設計方案需要使用一個定時器,一般情況下定時1ms即可(定時時間可隨意定,但中斷過于頻繁效率就低,中斷太長,實時性差),因此需要考慮到每個任務函數的執行時間,建議不能超過1ms(能通過程序優化縮短執行時間則最好優化,如果不能優化的,則必須保證該任務的執行周期必須遠大于任務所執行的耗時時間),同時要求主循環或任務函數中不能存在毫秒級別的延時。

如何確定每個函數的任務周期呢?根據任務的耗時和效果決定、如按鍵掃描任務周期為 10ms(為了提高響應),指示燈控制任務周期為 100ms(通常情況下最高100ms的閃爍頻率正好,特殊需求除外),LCD/OLED 顯示周期為 100ms(通過這種通過SPI/IIC接口的方式耗時大約在 1~10ms,甚至更長,所以任務周期必須遠大于耗時,同時為了滿足人眼所能接受的刷屏效果,也不能太長,100ms 的任務周期比較合適)等

以下介紹兩種不同的實現方案,分別針對無函數指針概念的朋友和想進一步學習的朋友。

① 無函數指針的設計方式

  1. 首先定義計時標志變量,以1毫秒為時間片,在定時器中斷函數中累計計時,同時將對應時間標識置1 。
void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
    {
        sg_1msTic++;

        sg_1msTic % 1 == 0 ? TIM_1msFlag = 1 : 0;
        sg_1msTic % 10 == 0 ? TIM_10msFlag = 1 : 0;
        sg_1msTic % 20 == 0 ? TIM_20msFlag = 1 : 0;
        sg_1msTic % 100 == 0 ? TIM_100msFlag = 1 : 0;
        sg_1msTic % 500 == 0 ? TIM_500msFlag = 1 : 0;
        sg_1msTic % 1000 == 0 ? (TIM_1secFlag  = 1, sg_1msTic = 0) : 0;
    }

    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
  1. 然后在主函數循環中判斷時間標識,標識被置1則代表時間已到,可以執行相應的函數,全部執行完畢后將標識置0 ,等待下次觸發。
int main(void)
{
    System_Init();

    while (1)
    {

        if (TIM_1msFlag)
        {
            CAN_CommTask();// CAN通信任務

            TIM_1msFlag = 0;
        }

        if (TIM_10msFlag)
        {
            KEY_ScanTask();// 按鍵掃描任務
            Hmi_Task();// 人機交互任務

            TIM_10msFlag = 0;
        }

        if (TIM_100msFlag)
        { 
            LED_CtrlTask();// 指示燈任務

            TIM_100msFlag = 0;
        }    

        if (TIM_1secFlag)
        {
            WDog_Task();// 喂狗任務

            TIM_1secFlag = 0;
        }  
    }
}

② 含函數指針的設計方式

  1. 定義含有函數指針的結構體,用來指向需要周期執行的函數。
typedef struct{
    uint8 m_runFlag;/*!< 程序運行標記:0-不運行,1運行 */
    uint16 m_timer;/*!< 計時器 */
    uint16 m_itvTime;/*!< 任務運行間隔時間 */
    void (*m_pTaskHook)(void);/*!< 要運行的任務函數 */
} TASK_InfoType;
  1. 實現函數指針任務基本調度功能:任務調度管理和任務調度執行 。
/**
  * @brief      任務函數運行調度管理.
  */
void TASK_Remarks(void)
{
    uint8 i;

    for (i = 0; i < TASKS_MAX; i++)
    {
        if (sg_tTaskInfo[i].m_timer)
        {
            sg_tTaskInfo[i].m_timer--;

            if (0 == sg_tTaskInfo[i].m_timer)
            {
                 sg_tTaskInfo[i].m_timer = sg_tTaskInfo[i].m_itvTime;
                 sg_tTaskInfo[i].m_runFlag = 1;
            }
        }
   }
}

/**
  * @brief      任務函數調度執行.
  */
void TASK_Process(void)
{
    uint8 i;

    for (i = 0; i < TASKS_MAX; i++)
    {
        if (sg_tTaskInfo[i].m_runFlag)
        {
             sg_tTaskInfo[i].m_pTaskHook(); // 運行任務
             sg_tTaskInfo[i].m_runFlag = 0; // 標志清0
        }
    }   
}
  1. 分別在定時器中斷函數和主函數中調用任務調度管理和任務調度執行 。
int main(void)
{
    System_Init();

    while (1)
    {
        TASK_Process();
    }
}

/**
  * @brief      定時器3中斷服務函數.
  */
void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
    {
        TASK_Remarks();
    }

    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
  1. 添加需要執行的任務函數即可。
#define TASKS_MAX     5    // 定義任務數目


/** 任務函數相關信息 */
static TASK_InfoType sg_tTaskInfo[TASKS_MAX] = {
    {0, 1, 1, CAN_CommTask},     // CAN通信任務
    {0, 10, 10, KEY_ScanTask},   // 按鍵掃描任務
    {0, 10, 10, LOGIC_HandleTask}, // 邏輯處理任務
    {0, 100, 100, LED_CtrlTask},// 指示燈控制任務
    {0, 1000, 1000, WDog_Task},  // 喂狗任務
};

操作系統

嵌入式操作系統EOS(Embedded OperatingSystem)是一種用途廣泛的系統軟件,過去它主要應用于工業控制和國防系統領域,而對于單片機來說,比較常用的有 UCOSFreeRTOS、RT-Thread Nano 和 RTX 等多種搶占式操作系統(其他如 Linux 等操作系統不適用于單片機)

操作系統和“時間片論法”,在任務執行方面來說,操作系統對每個任務的耗時沒有過多的要求,需要通過設置每個任務的優先級,在高優先級的任務就緒時,會搶占低優先級的任務;操作系統相對復雜,因此這里沒有詳細介紹了。

關于如何選擇合適的操作系統([RTOS]uCOS、FreeRTOS、RTThread、RTX等RTOS的對比之特點):

UCOS :網上資料豐富,非常適合學習,但是在產品上使用則需要收費

FreeRTOS :使用免費,因此很多產品都在用

RT-Thread :國產物聯網操作系統,有著十分豐富的組件,也免費,資料:RT-Thread 文檔中心

RTX :為ARM和Cortex-M設備設計的免版稅,確定性的實時操作系統

借網上一張對比圖:

圖片

3、總結

從上述的對比中可以看出,時間片輪詢法的優勢還是比較大的,它既有前后臺順序執行法的優點,也有操作系統的優點。結構清晰,簡單,非常容易理解,所以這種是比較常用的單片機設計框架。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • mcu
    mcu
    +關注

    關注

    146

    文章

    17317

    瀏覽量

    352635
  • 嵌入式
    +關注

    關注

    5092

    文章

    19177

    瀏覽量

    307653
  • 軟件開發
    +關注

    關注

    0

    文章

    624

    瀏覽量

    27444
收藏 人收藏

    評論

    相關推薦

    嵌入式軟件架構設

      本篇介紹了嵌入式系統編程軟件架構方面的知識,主要包括模塊劃分、多任務還是單任務選取、單任務
    發表于 06-23 23:15

    誠聘嵌入式軟件架構

    ,本科以上學歷;2、三年以上嵌入式軟件系統架構設計經驗,同時有通信行業軟件開發經驗;3、精通C/C++語言,精通數據結構;熟悉QT\linux\android
    發表于 03-01 10:20

    嵌入式系統的軟件架構設計!

    軟件架構設計!2. 嵌入式環境下軟件設計的特點要談嵌入式軟件
    發表于 08-10 07:46

    為何要進行嵌入式軟件架構設計?如何設計?

    為何要進行嵌入式軟件架構設計?如何進行嵌入式軟件架構設計?
    發表于 11-01 06:31

    嵌入式軟件架構設計的目的及思路

    【1】架構設計的目的1.應用的代碼邏輯清晰,且避免重復造輪子。2.方便軟件的移植。3.最大限度地復用。4.高內聚低耦合。 【2】嵌入式架構思路1.功能模塊化設計獲得需求------->
    發表于 11-08 06:41

    嵌入式系統中的架構設計的理解

    【閱讀這篇文章,你能了解到什么】1. 從事嵌入式開發12年的我,對架構設計的理解;2. 對嵌入式系統中的架構設計要刻意訓練;3. 嵌入式系統
    發表于 11-08 08:23

    決定嵌入式系統軟件架構的因素和架構的影響

    嵌入式系統軟件架構設計目錄1.前言42.決定架構的因素和架構的影響42.1.常見的誤解52.1.1.小型的系統不需要
    發表于 11-08 06:54

    嵌入式系統任務管理與調度

    慕課電子科技大學.嵌入式系統.第七章.任務管理與調度.任務管理3-任務管理機制0 目錄7 任務
    發表于 12-21 08:00

    嵌入式軟件架構設計資料分享

    作為程序員,我覺得如果要走的更遠必須要成為工程師,畢竟年齡和資歷都擺在那里了。所以就讓我這個老程序員淺談一下嵌入式軟件架構設計。我參考的也是一篇博文。原圖如下![在這里插入圖片描述](?x-oss-process=image/w
    發表于 12-24 07:09

    嵌入式軟件架構設

    嵌入式軟件架構的設計,幫助我們建立合理,有效的軟件架構
    發表于 11-09 17:34 ?19次下載

    實時多任務嵌入式軟件架構方式的設計應用

    分享到:標簽:軟總線 嵌入式軟件 實時多任務 1.引言 隨著大型嵌入式系統向著集成化和多元化方向的發展,嵌入式
    發表于 10-25 14:46 ?1次下載
    實時多<b class='flag-5'>任務</b><b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b>的<b class='flag-5'>架構</b>方式的設計應用

    探究嵌入式開發是否需要架構設計?

    閱讀這篇文章,你能了解到什么 1. 從事嵌入式開發12年的我,對架構設計的理解; 2. 對嵌入式系統中的架構設計要刻意訓練; 3. 嵌入式
    的頭像 發表于 04-05 09:49 ?3557次閱讀
    探究<b class='flag-5'>嵌入式</b>開發是否需要<b class='flag-5'>架構設</b>計?

    嵌入式UI架構設計漫談

    嵌入式UI架構設計漫談
    發表于 11-03 17:36 ?15次下載
    <b class='flag-5'>嵌入式</b>UI<b class='flag-5'>架構設</b>計漫談

    嵌入式系統軟件架構設

    嵌入式系統軟件架構設計目錄1.前言42.決定架構的因素和架構的影響42.1.常見的誤解52.1.1.小型的系統不需要
    發表于 11-03 18:21 ?30次下載
    <b class='flag-5'>嵌入式</b>系統<b class='flag-5'>軟件</b><b class='flag-5'>架構設</b>計

    任務調度開源代碼是什么

    通過[嵌入式軟件架構設計-任務調度]了解到 MCU 的三種任務
    的頭像 發表于 02-15 14:53 ?973次閱讀
    百家乐官网如何捕捉长龙| 百家乐真人娱乐城| 大赢家比分| 百家乐官网技巧何为百家乐官网之路| 百家乐一起多少张牌| 博野县| 乐百家乐彩现金开户| 尊龙娱乐开户| 海立方百家乐海立方| 云林县| 百家乐洗码全讯网| 新澳博国际娱乐| 阳宅64卦与24山| 足球平台开户| 百家乐官网下注法| 金都娱乐场| 百家乐翻天粤语下载| 大发888扑克合营商| 真人百家乐官网蓝盾| 大发888-娱乐网| 免费百家乐官网倍投| 一二博网| 百家乐秘诀| 澳门百家乐官网家用保险柜| 联合百家乐的玩法技巧和规则| 真人百家乐官网出千| 百家乐平的概率| 哪个百家乐官网投注好| 扑克百家乐麻将筹码防伪| 百家乐官网如何盈利| 真人娱乐城送体验金18| 百家乐论坛百科| 百家乐官网机器二手| 全讯网百家乐的玩法技巧和规则| 广州百家乐官网赌博机| 百家乐赌机破解| 百家乐官网开户送8彩金| 百家乐视频画面| 百家乐官网真人现场| 百家乐官网心态研究| 威尼斯人娱乐城--老品牌值得您信赖 |