<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一種面向?qū)ο笏季S的單片機(jī)程序框架

          共 8122字,需瀏覽 17分鐘

           ·

          2021-09-27 08:11

          關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容

          來(lái)源:網(wǎng)絡(luò)素材


          大家好,單片機(jī)編碼中稍不注意就會(huì)陷入一種混沌狀態(tài),函數(shù)、變量、文件分類用的多了就會(huì)亂了,對(duì)初學(xué)者尤其如此,實(shí)現(xiàn)功能是簡(jiǎn)單的,但是讓程序變得可移植性好,一目了然,架構(gòu)清晰才是進(jìn)階必經(jīng)之路,今天分享一篇單片機(jī)程序框架的文章,希望對(duì)大家有幫助。


          程序架構(gòu)重要性

          很多人尤其是初學(xué)者在寫代碼的時(shí)候往往都是想一點(diǎn)寫一點(diǎn),最開(kāi)始沒(méi)有一個(gè)整體的規(guī)劃,導(dǎo)致后面代碼越寫越亂,bug不斷。

          最終代碼跑起來(lái)看似沒(méi)有問(wèn)題(有可能也真的沒(méi)有問(wèn)題),但是系統(tǒng)的可擴(kuò)展性很差,添加一個(gè)功能的時(shí)候會(huì)浪費(fèi)大量的時(shí)間,甚至導(dǎo)致整個(gè)代碼的崩潰。

          所以,在一個(gè)項(xiàng)目開(kāi)始的時(shí)候多花一些時(shí)間在代碼的架構(gòu)設(shè)計(jì)上是十分有必要的代碼架構(gòu)確定好了之后你會(huì)發(fā)現(xiàn)敲代碼的時(shí)候會(huì)特別快,并且在后期調(diào)試的時(shí)候也不會(huì)像無(wú)頭蒼蠅一樣胡亂找問(wèn)題。當(dāng)然,調(diào)試也是一門技術(shù)。

          在學(xué)習(xí)實(shí)時(shí)操作系統(tǒng)的過(guò)程中,發(fā)現(xiàn)實(shí)時(shí)操作系統(tǒng)框架與個(gè)人的業(yè)務(wù)代碼之間的耦合性就非常低,都是只需要將業(yè)務(wù)代碼通過(guò)一定的接口函數(shù)注冊(cè)好后就交給操作系統(tǒng)托管了,十分方便。

          但是操作系統(tǒng)的調(diào)度過(guò)于復(fù)雜,這里就使用操作系統(tǒng)的思維方式來(lái)重構(gòu)這個(gè)時(shí)間片輪詢框架。實(shí)現(xiàn)該框架的完全解耦,用戶只需要包含頭文件,并且在使用過(guò)程中不需要改動(dòng)已經(jīng)寫好的庫(kù)文件。

          Demo

          首先來(lái)個(gè)demo,該demo是使用電腦開(kāi)兩個(gè)線程:一個(gè)線程模擬單片機(jī)的定時(shí)器中斷產(chǎn)生時(shí)間片輪詢個(gè)時(shí)鐘,另一個(gè)線程則模擬主函數(shù)中一直運(yùn)行的時(shí)間片輪詢調(diào)度程序。
          #include <thread>#include <stdio.h>#include <windows.h>#include "timeslice.h"
          // 創(chuàng)建5個(gè)任務(wù)對(duì)象TimesilceTaskObj task_1, task_2, task_3, task_4, task_5;
          // 具體的任務(wù)函數(shù)void task1_hdl(){ printf(">> task 1 is running ...\n");}
          void task2_hdl(){ printf(">> task 2 is running ...\n");}
          void task3_hdl(){ printf(">> task 3 is running ...\n");}
          void task4_hdl(){ printf(">> task 4 is running ...\n");}
          void task5_hdl(){ printf(">> task 5 is running ...\n");}
          // 初始化任務(wù)對(duì)象,并且將任務(wù)添加到時(shí)間片輪詢調(diào)度中void task_init(){ timeslice_task_init(&task_1, task1_hdl, 1, 10); timeslice_task_init(&task_2, task2_hdl, 2, 20); timeslice_task_init(&task_3, task3_hdl, 3, 30); timeslice_task_init(&task_4, task4_hdl, 4, 40); timeslice_task_init(&task_5, task5_hdl, 5, 50); timeslice_task_add(&task_1); timeslice_task_add(&task_2); timeslice_task_add(&task_3); timeslice_task_add(&task_4); timeslice_task_add(&task_5);}

          // 開(kāi)兩個(gè)線程模擬在單片機(jī)上的運(yùn)行過(guò)程void timeslice_exec_thread(){ while (true) { timeslice_exec(); }}
          void timeslice_tick_thread(){ while (true) { timeslice_tick(); Sleep(10); }}
          int main(){ task_init();
          printf(">> task num: %d\n", timeslice_get_task_num()); printf(">> task len: %d\n", timeslice_get_task_timeslice_len(&task_3));
          timeslice_task_del(&task_2); printf(">> delet task 2\n"); printf(">> task 2 is exist: %d\n", timeslice_task_isexist(&task_2));
          printf(">> task num: %d\n", timeslice_get_task_num());
          timeslice_task_del(&task_5); printf(">> delet task 5\n");
          printf(">> task num: %d\n", timeslice_get_task_num());
          printf(">> task 3 is exist: %d\n", timeslice_task_isexist(&task_3)); timeslice_task_add(&task_2); printf(">> add task 2\n"); printf(">> task 2 is exist: %d\n", timeslice_task_isexist(&task_2));
          timeslice_task_add(&task_5); printf(">> add task 5\n");
          printf(">> task num: %d\n", timeslice_get_task_num());
          printf("\n\n========timeslice running===========\n");
          std::thread thread_1(timeslice_exec_thread); std::thread thread_2(timeslice_tick_thread);
          thread_1.join(); thread_2.join();

          return 0;}


          運(yùn)行結(jié)果如下:



          由以上例子可見(jiàn),這個(gè)框架使用十分方便,甚至可以完全不知道其原理,僅僅通過(guò)幾個(gè)簡(jiǎn)單的接口就可以迅速創(chuàng)建任務(wù)并加入到時(shí)間片輪詢的框架中,十分好用。

          時(shí)間片輪詢架構(gòu)


          其實(shí)該部分主要使用了面向?qū)ο蟮乃季S,使用結(jié)構(gòu)體作為對(duì)象,并使用結(jié)構(gòu)體指針作為參數(shù)傳遞,這樣作可以節(jié)省資源,并且有著極高的運(yùn)行效率。


          其中最難的部分是侵入式鏈表的使用,這種鏈表在一些操作系統(tǒng)內(nèi)核中使用十分廣泛,這里是參考RT-Thread實(shí)時(shí)操作系統(tǒng)中的侵入式鏈表實(shí)現(xiàn)。

          h文件:
          #ifndef _TIMESLICE_H#define _TIMESLICE_H
          #include "./list.h"
          typedef enum { TASK_STOP, TASK_RUN} IsTaskRun;
          typedef struct timesilce{ unsigned int id; void (*task_hdl)(void); IsTaskRun is_run; unsigned int timer; unsigned int timeslice_len; ListObj timeslice_task_list;} TimesilceTaskObj;
          void timeslice_exec(void);void timeslice_tick(void);void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len);void timeslice_task_add(TimesilceTaskObj* obj);void timeslice_task_del(TimesilceTaskObj* obj);unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj);unsigned int timeslice_get_task_num(void);unsigned char timeslice_task_isexist(TimesilceTaskObj* obj);
          #endif

          c文件:
          #include "./timeslice.h"
          static LIST_HEAD(timeslice_task_list);
          void timeslice_exec(){ ListObj* node; TimesilceTaskObj* task;
          list_for_each(node, &timeslice_task_list) { task = list_entry(node, TimesilceTaskObj, timeslice_task_list); if (task->is_run == TASK_RUN) { task->task_hdl(); task->is_run = TASK_STOP; } }}
          void timeslice_tick(){ ListObj* node; TimesilceTaskObj* task;
          list_for_each(node, &timeslice_task_list) { task = list_entry(node, TimesilceTaskObj, timeslice_task_list); if (task->timer != 0) { task->timer--; if (task->timer == 0) { task->is_run = TASK_RUN; task->timer = task->timeslice_len; } } }}
          unsigned int timeslice_get_task_num(){ return list_len(&timeslice_task_list);}
          void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len){ obj->id = id; obj->is_run = TASK_STOP; obj->task_hdl = task_hdl; obj->timer = timeslice_len; obj->timeslice_len = timeslice_len;}
          void timeslice_task_add(TimesilceTaskObj* obj){ list_insert_before(&timeslice_task_list, &obj->timeslice_task_list);}
          void timeslice_task_del(TimesilceTaskObj* obj){ if (timeslice_task_isexist(obj)) list_remove(&obj->timeslice_task_list); else return;}

          unsigned char timeslice_task_isexist(TimesilceTaskObj* obj){ unsigned char isexist = 0; ListObj* node; TimesilceTaskObj* task;
          list_for_each(node, &timeslice_task_list) { task = list_entry(node, TimesilceTaskObj, timeslice_task_list); if (obj->id == task->id) isexist = 1; }
          return isexist;}
          unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj){ return obj->timeslice_len;}

          底層侵入式雙向鏈表

          該鏈表是linux內(nèi)核中使用十分廣泛,也十分經(jīng)典,其原理具體可以參考文章:
          https://www.cnblogs.com/skywang12345/p/3562146.html

          h文件:
          #ifndef _LIST_H#define _LIST_H
          #define offset_of(type, member) (unsigned long) &((type*)0)->member#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offset_of(type, member)))
          typedef struct list_structure{ struct list_structure* next; struct list_structure* prev;} ListObj;
          #define LIST_HEAD_INIT(name) {&(name), &(name)}#define LIST_HEAD(name) ListObj name = LIST_HEAD_INIT(name)
          void list_init(ListObj* list);void list_insert_after(ListObj* list, ListObj* node);void list_insert_before(ListObj* list, ListObj* node);void list_remove(ListObj* node);int list_isempty(const ListObj* list);unsigned int list_len(const ListObj* list);
          #define list_entry(node, type, member) \ container_of(node, type, member)
          #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
          #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next)
          #endif

          c文件:
          #include "list.h"
          void list_init(ListObj* list){ list->next = list->prev = list;}
          void list_insert_after(ListObj* list, ListObj* node){ list->next->prev = node; node->next = list->next;
          list->next = node; node->prev = list;}
          void list_insert_before(ListObj* list, ListObj* node){ list->prev->next = node; node->prev = list->prev;
          list->prev = node; node->next = list;}
          void list_remove(ListObj* node){ node->next->prev = node->prev; node->prev->next = node->next;
          node->next = node->prev = node;}
          int list_isempty(const ListObj* list){ return list->next == list;}
          unsigned int list_len(const ListObj* list){ unsigned int len = 0; const ListObj* p = list; while (p->next != list) { p = p->next; len++; }
          return len;}

          到此,一個(gè)全新的,完全解耦的,十分方便易用時(shí)間片輪詢框架完成。

          本文來(lái)源網(wǎng)絡(luò),版權(quán)歸原作者所有。如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系我進(jìn)行刪除。

          ????????????????  END  ????????????????

          關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

          歡迎關(guān)注我的視頻號(hào):


          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 76
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一道本二区 | 在线a√视频 | 91青青草视频在线 | 国产精品剧情亚洲二区 | 波多野结衣中文字幕久久 |