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

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

3天內(nèi)不再提示

LEDs狀態(tài)燈任務(線程)設計 (基于RTOS)

黃工的嵌入式技術圈 ? 來源:網(wǎng)站整理 ? 2020-03-12 11:30 ? 次閱讀

我們學習MCU開發(fā),大部分都是面向過程的開發(fā),但實際項目一般要求我們有面向對象(模塊化)的方式來開發(fā)。

剛學習C語言開發(fā)的朋友,應該常常聽說面向對象,但實際對于面向對象開發(fā)可能還是不太了解。

為了初學者進一步理解,本文結合實際項目(LEDs狀態(tài)燈)給大家?guī)肀容^基礎的模塊化設計。

Ⅰ關于C語言的模塊化

對于MCU的開發(fā),大部分人都還是習慣性用的C語言,原因之一在于C語言具有高效的特點。

可以了解一下,許多操作系統(tǒng)的內(nèi)核使用的編程語言,其實都用到了C語言,這就是C語言的優(yōu)點,也是C語言這么多年不衰敗的原因。

說回來,對于MCU的開發(fā),除了C語言,當然還可以其它語言,像C++有許多人就用上了。

C++語言本身就是面向對象的開發(fā)語言,定義一個類,可以包含許多成員。站在C語言的角度,可以理解成定義一個結構體,里面包含許多數(shù)據(jù)類型。如下面要說的LEDs數(shù)據(jù)結構體:

typedef struct { uint8_t Mode; //模式(常滅 常亮 閃爍) uint8_t Status; //當前狀態(tài)(滅 亮) uint16_t OffTimes; //滅時間(xLED_COUNT_PERIOD毫秒) uint16_t OnTimes; //亮時間 uint16_t Counter; //計數(shù)(計時) void (*OffFun)(void); //滅函數(shù)接口 void (*OnFun)(void); //亮函數(shù)接口 }LED_TypeDef;

可以看到,結構體里面包含整型變量,函數(shù)指針。

補充,指針函數(shù)與函數(shù)指針的區(qū)別:

1、指針函數(shù):本質是一個函數(shù),函數(shù)返回類型是某一類型的指針。

格式: 類型標識符 *函數(shù)名(參數(shù)表)

如:int *f(x,y);

2、函數(shù)指針:本質是一個指針,指向函數(shù)的指針變量。

格式:類型說明符 (*函數(shù)名)(參數(shù))

如:int (*f) (int x);

Ⅱ為什么要模塊化設計

假如一個系統(tǒng)中做的事情非常多,比如:采集兩個增量式編碼器、兩個絕對值編碼器、控制4個電機、控制多個LED狀態(tài)燈、通信收發(fā)數(shù)據(jù),采集溫度、濕度、超聲波雷達等···許多模塊,那么問題來了,這么多模塊,你的軟件該如何設計?

答案就是需要模塊化設計。

模塊化設計,包含底層驅動,中間接口函數(shù),應用程序等。對于MCU級別的開發(fā),為了規(guī)范,建議大家從底層設計到應用層設計都按照模塊化的方式來設計。

簡單的來說,模塊化就是源文件、數(shù)據(jù)結構、變量、函數(shù)命名等需要按照模塊的方式來設計。比如LEDs狀態(tài)燈:IO口的定義用LED(模塊),文件名用led,變量、函數(shù)名抬頭用LED,定義一個LED數(shù)據(jù)結構(模塊的數(shù)據(jù)結構)等。

模塊化的設計優(yōu)點在于:便于源代碼管理、移植、理解等等。(相信有許多自己寫的代碼,放一段時間之后,重新再次閱讀,可能看了半天都不明白源代碼的意思。)

ⅢLEDs實例講述

為方便大家理解,拿一個簡單的LEDs狀態(tài)燈的實例來分析。里面使用到了RTOS簡單系統(tǒng)延時(本文不講述關于RTOS的知識)。文末提供例程下載地址。

1.描述

綠、黃、紅三個(可以自己添加許多個)LED狀態(tài)燈,可獨自實現(xiàn)常滅、常亮、閃爍三個模式。

閃爍:滅、亮時間可設置(提供函數(shù)接口修改)。

在一個線程(任務)里面執(zhí)行。

3個LED不同亮滅時間效果:

2.數(shù)據(jù)結構

typedef struct { uint8_t Mode; //模式(常滅 常亮 閃爍) uint8_t Status; //當前狀態(tài)(滅 亮) uint16_t OffTimes; //滅時間(xLED_COUNT_PERIOD毫秒) uint16_t OnTimes; //亮時間 uint16_t Counter; //計數(shù)(計時) void (*OffFun)(void); //滅函數(shù)接口 void (*OnFun)(void); //亮函數(shù)接口 }LED_TypeDef;

為了方便理解,只使用一個數(shù)據(jù)結構(實際大的項目可能有多個包含,類似C++繼承關系)。

3.底層LED函數(shù)接口

void LEDGreen_Off(void);

void LEDGreen_On(void);

void LEDYellow_Off(void);

void LEDYellow_On(void);

void LEDRed_Off(void);

void LEDRed_On(void);

主要就是亮滅函數(shù)接口,這里提供三組LED(根據(jù)需求可添加)。

4.定義局部變量

static LED_TypeDef sLEDG_Structure; //綠燈 static LED_TypeDef sLEDY_Structure; //黃燈 static LED_TypeDef sLEDR_Structure; //紅燈

5.初始化變量

/************************************************函數(shù)名稱 : LED_Data_Init功 能 : 數(shù)據(jù)初始化參 數(shù) : 無返 回 值 : 無作 者 : strongerHuang*************************************************/ static void LED_Data_Init(void){ /* 綠燈 */ sLEDG_Structure.Mode = LED_MODE_FLICKER; //初始化為閃爍 sLEDG_Structure.OffTimes = 50; //滅亮時間 sLEDG_Structure.OnTimes = 50; sLEDG_Structure.Counter = 0; //計數(shù)歸零 sLEDG_Structure.OffFun = LEDGreen_Off; //滅函數(shù)接口 sLEDG_Structure.OnFun = LEDGreen_On; //亮函數(shù)接口 /* 黃燈 */ sLEDY_Structure.Mode = LED_MODE_ON; //初始化為常亮 sLEDY_Structure.OffTimes = 0; //滅亮時間 sLEDY_Structure.OnTimes = 0; sLEDY_Structure.Counter = 0; //計數(shù)歸零 sLEDY_Structure.OffFun = LEDYellow_Off; //滅函數(shù)接口 sLEDY_Structure.OnFun = LEDYellow_On; //亮函數(shù)接口 /* 紅燈 */ sLEDR_Structure.Mode = LED_MODE_ON; //初始化為常亮 sLEDR_Structure.OffTimes = 0; //滅亮時間 sLEDR_Structure.OnTimes = 0; sLEDR_Structure.Counter = 0; //計數(shù)歸零 sLEDR_Structure.OffFun = LEDRed_Off; //滅函數(shù)接口 sLEDR_Structure.OnFun = LEDRed_On; //亮函數(shù)接口 /* 對外調用接口(例子) */ LEDG_Set(LED_MODE_FLICKER, 50, 50); LEDY_Set(LED_MODE_FLICKER, 50, 10); LEDR_Set(LED_MODE_FLICKER, 20, 30);}

這里重要的就是要初始化滅亮函數(shù)接口。

6.LEDs任務(線程)

/************************************************函數(shù)名稱 : LED_Task_Proc功 能 : 狀態(tài)燈任務程序參 數(shù) : pvParameters --- 可選參數(shù)返 回 值 : 無作 者 : strongerHuang*************************************************/ static void LED_Task_Proc(void *pvParameters){ static TickType_t xLastWakeTime; xLastWakeTime = xTaskGetTickCount(); for(;;) { //間隔固定計數(shù)周期(采樣時間) vTaskDelayUntil(&xLastWakeTime, LED_COUNT_PERIOD); /* 瀏覽LEDs */ LED_Scan(&sLEDG_Structure); LED_Scan(&sLEDY_Structure); LED_Scan(&sLEDR_Structure); }}

流程圖:

7.LED瀏覽(或者說處理)

/************************************************函數(shù)名稱 : LED_Scan功 能 : 狀態(tài)燈掃描(修改狀態(tài))參 數(shù) : LED_Struct --- 狀態(tài)燈數(shù)據(jù)結構返 回 值 : 無作 者 : strongerHuang*************************************************/ static void LED_Scan(LED_TypeDef *LED_Struct){ /* 1.常滅模式 */ if(LED_MODE_OFF == LED_Struct->Mode) { LED_Struct->Status = LED_STATUS_OFF; //狀態(tài)置為"滅" LED_Struct->OffFun(); //滅燈 } /* 2.常亮模式 */ else if(LED_MODE_ON == LED_Struct->Mode) { LED_Struct->Status = LED_STATUS_ON; //狀態(tài)置為"亮" LED_Struct->OnFun(); //亮燈 } /* 3.閃爍模式 */ else if(LED_MODE_FLICKER == LED_Struct->Mode) { /* 在滅的狀態(tài) */ if(LED_STATUS_OFF == LED_Struct->Status) { LED_Struct->Counter++; if(LED_Struct->Counter >= LED_Struct->OffTimes) { LED_Struct->Counter = 0; LED_Struct->OnFun(); //亮燈 LED_Struct->Status = LED_STATUS_ON; //狀態(tài)置為"亮" } } /* 在亮的狀態(tài) */ else if(LED_STATUS_ON == LED_Struct->Status) { LED_Struct->Counter++; if(LED_Struct->Counter >= LED_Struct->OnTimes) { LED_Struct->Counter = 0; LED_Struct->OffFun(); //滅燈 LED_Struct->Status = LED_STATUS_OFF; //狀態(tài)置為"滅" } } else { LED_Struct->Status = LED_STATUS_OFF; //狀態(tài)置為"滅" } } /* 4.未知模式 */ else { LED_Struct->Status = LED_STATUS_OFF; //狀態(tài)置為"滅" LED_Struct->OffFun(); //滅燈 }}

源代碼工程下載地址:

鏈接:https://pan.baidu.com/s/1cNtwJDdCOfyYwsvKCclFyw

密碼:kk74

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

    關注

    146

    文章

    16796

    瀏覽量

    349331
  • LEDs
    +關注

    關注

    1

    文章

    38

    瀏覽量

    25498
  • RTOS
    +關注

    關注

    21

    文章

    807

    瀏覽量

    119288
  • 線程
    +關注

    關注

    0

    文章

    502

    瀏覽量

    19613
收藏 人收藏

    評論

    相關推薦

    rtthread是搶占式的rtos,那么線程的timeout參數(shù)具體的作用是什么呢?

    查閱相關說明,rtthread是搶占式的rtos,那么線程的timeout參數(shù)具體的作用是什么呢, 假如線程A,B的優(yōu)先級分別是1和2,timeout是10ms。當線程B 在運行中,還
    發(fā)表于 09-27 08:39

    驅動指示leds

    電子發(fā)燒友網(wǎng)站提供《驅動指示leds.pdf》資料免費下載
    發(fā)表于 09-18 11:50 ?0次下載
    驅動指示<b class='flag-5'>燈</b><b class='flag-5'>leds</b>

    鴻蒙開發(fā):【線程模型】

    管理其他線程的ArkTS引擎實例,例如使用TaskPool(任務池)創(chuàng)建任務或取消任務、啟動和終止Worker線程
    的頭像 發(fā)表于 06-13 16:38 ?310次閱讀
    鴻蒙開發(fā):【<b class='flag-5'>線程</b>模型】

    請問CMSIS-RTOS RTX的任務調度鎖在哪里?

    請問一下,CMSIS-RTOS RTX的任務調度鎖在哪里?謝謝!
    發(fā)表于 05-13 08:28

    FreeRTOS系統(tǒng)使用xTaskCreate產(chǎn)生的任務與osThreadDef 產(chǎn)生的線程有什么不同?

    請教下是要 FreeRTOS系統(tǒng), 使用 xTaskCreate 產(chǎn)生的任務 與 osThreadDef產(chǎn)生的線程有什么不同?
    發(fā)表于 04-29 07:20

    鴻蒙OS開發(fā)實例:【ArkTS類庫多線程CPU密集型任務TaskPool】

    CPU密集型任務是指需要占用系統(tǒng)資源處理大量計算能力的任務,需要長時間運行,這段時間會阻塞線程其它事件的處理,不適宜放在主線程進行。例如圖像處理、視頻編碼、數(shù)據(jù)分析等。 基于多
    的頭像 發(fā)表于 04-01 22:25 ?735次閱讀
    鴻蒙OS開發(fā)實例:【ArkTS類庫多<b class='flag-5'>線程</b>CPU密集型<b class='flag-5'>任務</b>TaskPool】

    基于RTOS的應用進程中的典型線程

    RTOS中的關鍵因素是最小的中斷延遲和最小的線程切換延遲。RTOS的價值在于它的響應速度或可預測性,而不是它在給定時間段內(nèi)可以執(zhí)行的工作量。
    發(fā)表于 03-05 09:32 ?471次閱讀
    基于<b class='flag-5'>RTOS</b>的應用進程中的典型<b class='flag-5'>線程</b>

    線程池七大核心參數(shù)執(zhí)行順序

    以及它們的執(zhí)行順序。 corePoolSize(核心線程數(shù)): 線程池中一直存活的線程數(shù)量。在線程池初始化或者任務提交后,
    的頭像 發(fā)表于 12-04 16:45 ?862次閱讀

    如何設定RTOS中的任務棧(線程棧)大小呢?

    首先說明的是,在 `RT-Thread` 中,將本文提及的 `任務` 稱之為 `線程`。
    的頭像 發(fā)表于 12-01 16:40 ?1471次閱讀

    RTOS內(nèi)功修煉記(一)— 任務到底應該怎么寫?

    本篇文章講述了任務的三大元素:任務控制塊、任務棧、任務入口函數(shù),并講述了編寫RTOS任務入口函數(shù)
    的頭像 發(fā)表于 12-01 16:36 ?660次閱讀
    <b class='flag-5'>RTOS</b>內(nèi)功修煉記(一)— <b class='flag-5'>任務</b>到底應該怎么寫?

    新手必看的RTOS基礎知識

    時間片調度保證每個線程都有一個要執(zhí)行的槽。這種類型的調度通常不利于實時應用。如果需要,TI-RTOS內(nèi)核支持使用任務進行時間切片調度。
    的頭像 發(fā)表于 11-20 16:06 ?2232次閱讀
    新手必看的<b class='flag-5'>RTOS</b>基礎知識

    JDK如何優(yōu)雅退出一個線程?

    需要線程退出的常見場景 任務執(zhí)行完成,或異常終止,任務認為無需再占用線程。 線程池根據(jù)當前任務
    的頭像 發(fā)表于 11-17 10:02 ?393次閱讀
    JDK如何優(yōu)雅退出一個<b class='flag-5'>線程</b>?

    RTOS中的線程、進程和協(xié)程詳解

    看到有小伙伴在討論【RTOS任務屬于線程還是進程】的話題,這里就來分析一下OS中的線程、進程和協(xié)程的這幾個概念,同時一起看看RTOS中的
    的頭像 發(fā)表于 11-09 12:36 ?1717次閱讀
    <b class='flag-5'>RTOS</b>中的<b class='flag-5'>線程</b>、進程和協(xié)程詳解

    SCP線程模型特點

    線程 混合協(xié)作調度模型-調度在具有相同優(yōu)先級的線程之間是協(xié)作的。 ?無需鎖 ?使代碼更簡單,避免了死鎖的情況。 ?它消除了對執(zhí)行上下文/RTOS的依賴,并防止了開銷。 ?事件在線程上下
    的頭像 發(fā)表于 11-02 17:07 ?481次閱讀
    SCP<b class='flag-5'>線程</b>模型特點

    RTOS相比裸機有什么優(yōu)點?RTOS相比裸機更方便嗎?

    理實時任務。在本文中,我們將探討使用RTOS而不是裸金屬系統(tǒng)的優(yōu)點,以及它是否更方便。 RTOS相對于裸機系統(tǒng)的優(yōu)勢 1.多任務處理 RTOS
    的頭像 發(fā)表于 10-29 16:33 ?1493次閱讀