色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

非常實用,推薦一種面向對象思維的單片機程序框架

jf_pJlTbmA9 ? 來源:小麥大叔 ? 作者:小麥大叔 ? 2023-10-24 18:03 ? 次閱讀

程序架構重要性

很多人尤其是初學者在寫代碼的時候往往都是想一點寫一點,最開始沒有一個整體的規劃,導致后面代碼越寫越亂,bug不斷。

最終代碼跑起來看似沒有問題(有可能也真的沒有問題),但是系統的可擴展性很差,添加一個功能的時候會浪費大量的時間,甚至導致整個代碼的崩潰。

所以,在一個項目開始的時候多花一些時間在代碼的架構設計上是十分有必要的。代碼架構確定好了之后你會發現敲代碼的時候會特別快,并且在后期調試的時候也不會像無頭蒼蠅一樣胡亂找問題。當然,調試也是一門技術。

在學習實時操作系統的過程中,發現實時操作系統框架與個人的業務代碼之間的耦合性就非常低,都是只需要將業務代碼通過一定的接口函數注冊好后就交給操作系統托管了,十分方便。

但是操作系統的調度過于復雜,這里就使用操作系統的思維方式來重構這個時間片輪詢框架。實現該框架的完全解耦,用戶只需要包含頭文件,并且在使用過程中不需要改動已經寫好的庫文件。

Demo

首先來個demo,該demo是使用電腦開兩個線程:一個線程模擬單片機定時器中斷產生時間片輪詢個時鐘,另一個線程則模擬主函數中一直運行的時間片輪詢調度程序。

#include
#include
#include
#include"timeslice.h"

//創建5個任務對象
TimesilceTaskObjtask_1,task_2,task_3,task_4,task_5;

//具體的任務函數
voidtask1_hdl()
{
printf(">>task1isrunning...n");
}

voidtask2_hdl()
{
printf(">>task2isrunning...n");
}

voidtask3_hdl()
{
printf(">>task3isrunning...n");
}

voidtask4_hdl()
{
printf(">>task4isrunning...n");
}

voidtask5_hdl()
{
printf(">>task5isrunning...n");
}

//初始化任務對象,并且將任務添加到時間片輪詢調度中
voidtask_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);
}

//開兩個線程模擬在單片機上的運行過程
voidtimeslice_exec_thread()
{
while(true)
{
timeslice_exec();
}
}

voidtimeslice_tick_thread()
{
while(true)
{
timeslice_tick();
Sleep(10);
}
}

intmain()
{
task_init();

printf(">>tasknum:%dn",timeslice_get_task_num());
printf(">>tasklen:%dn",timeslice_get_task_timeslice_len( task_3));

timeslice_task_del( task_2);
printf(">>delettask2n");
printf(">>task2isexist:%dn",timeslice_task_isexist( task_2));

printf(">>tasknum:%dn",timeslice_get_task_num());
timeslice_task_del( task_5);printf(">>delettask5n");
printf(">>tasknum:%dn",timeslice_get_task_num());
printf(">>task3isexist:%dn",timeslice_task_isexist( task_3));

timeslice_task_add( task_2);printf(">>addtask2n");
printf(">>task2isexist:%dn",timeslice_task_isexist( task_2));

timeslice_task_add( task_5);printf(">>addtask5n");
printf(">>tasknum:%dn",timeslice_get_task_num());

printf("nn========timeslicerunning===========n");

std::threadthread_1(timeslice_exec_thread);
std::threadthread_2(timeslice_tick_thread);

thread_1.join();
thread_2.join();

return0;
}

運行結果如下:

poYBAGGnJ7OAZ5XZAACMwYJDoAU530.png

由以上例子可見,這個框架使用十分方便,甚至可以完全不知道其原理,僅僅通過幾個簡單的接口就可以迅速創建任務并加入到時間片輪詢的框架中,十分好用。

時間片輪詢架構

其實該部分主要使用了面向對象的思維,使用結構體作為對象,并使用結構體指針作為參數傳遞,這樣作可以節省資源,并且有著極高的運行效率。

其中最難的部分是侵入式鏈表的使用,這種鏈表在一些操作系統內核中使用十分廣泛,這里是參考RT-Thread實時操作系統中的侵入式鏈表實現。

h文件:

#ifndef_TIMESLICE_H
#define_TIMESLICE_H

#include"./list.h"

typedefenum
{
TASK_STOP,
TASK_RUN
}IsTaskRun;

typedefstructtimesilce
{
unsignedintid;
void(*task_hdl)(void);
IsTaskRunis_run;
unsignedinttimer;
unsignedinttimeslice_len;
ListObjtimeslice_task_list;
}TimesilceTaskObj;

voidtimeslice_exec(void);
voidtimeslice_tick(void);
voidtimeslice_task_init(TimesilceTaskObj*obj,void(*task_hdl)(void),unsignedintid,unsignedinttimeslice_len);
voidtimeslice_task_add(TimesilceTaskObj*obj);
voidtimeslice_task_del(TimesilceTaskObj*obj);
unsignedinttimeslice_get_task_timeslice_len(TimesilceTaskObj*obj);
unsignedinttimeslice_get_task_num(void);
unsignedchartimeslice_task_isexist(TimesilceTaskObj*obj);

#endifc文件:
#include"./timeslice.h"

staticLIST_HEAD(timeslice_task_list);

voidtimeslice_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;
}
}
}

voidtimeslice_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;
}
}
}
}

unsignedinttimeslice_get_task_num()
{
returnlist_len( timeslice_task_list);
}

voidtimeslice_task_init(TimesilceTaskObj*obj,void(*task_hdl)(void),unsignedintid,unsignedinttimeslice_len)
{
obj->id=id;
obj->is_run=TASK_STOP;
obj->task_hdl=task_hdl;
obj->timer=timeslice_len;
obj->timeslice_len=timeslice_len;
}

voidtimeslice_task_add(TimesilceTaskObj*obj)
{
list_insert_before( timeslice_task_list, obj->timeslice_task_list);
}

voidtimeslice_task_del(TimesilceTaskObj*obj)
{
if(timeslice_task_isexist(obj))
list_remove( obj->timeslice_task_list);
else
return;
}

unsignedchartimeslice_task_isexist(TimesilceTaskObj*obj)
{
unsignedcharisexist=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;
}

returnisexist;
}

unsignedinttimeslice_get_task_timeslice_len(TimesilceTaskObj*obj)
{
returnobj->timeslice_len;
}

底層侵入式雙向鏈表

該鏈表是linux內核中使用十分廣泛,也十分經典,其原理具體可以參考文章:

https://www.cnblogs.com/skywang12345/p/3562146.html

h文件:

#ifndef_LIST_H
#define_LIST_H
#defineoffset_of(type,member)(unsignedlong) ((type*)0)->member
#definecontainer_of(ptr,type,member)((type*)((char*)(ptr)-offset_of(type,member)))

typedefstructlist_structure
{
structlist_structure*next;
structlist_structure*prev;
}ListObj;

#defineLIST_HEAD_INIT(name){ (name), (name)}
#defineLIST_HEAD(name)ListObjname=LIST_HEAD_INIT(name)

voidlist_init(ListObj*list);
voidlist_insert_after(ListObj*list,ListObj*node);
voidlist_insert_before(ListObj*list,ListObj*node);
voidlist_remove(ListObj*node);
intlist_isempty(constListObj*list);
unsignedintlist_len(constListObj*list);

#definelist_entry(node,type,member)
container_of(node,type,member)

#definelist_for_each(pos,head)
for(pos=(head)->next;pos!=(head);pos=pos->next)

#definelist_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"

voidlist_init(ListObj*list)
{
list->next=list->prev=list;
}

voidlist_insert_after(ListObj*list,ListObj*node)
{
list->next->prev=node;
node->next=list->next;

list->next=node;
node->prev=list;
}

voidlist_insert_before(ListObj*list,ListObj*node)
{
list->prev->next=node;
node->prev=list->prev;

list->prev=node;
node->next=list;
}

voidlist_remove(ListObj*node)
{
node->next->prev=node->prev;
node->prev->next=node->next;

node->next=node->prev=node;
}

intlist_isempty(constListObj*list)
{
returnlist->next==list;
}

unsignedintlist_len(constListObj*list)
{
unsignedintlen=0;
constListObj*p=list;
while(p->next!=list)
{
p=p->next;
len++;
}

returnlen;
}

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

來源:小麥大叔

免責聲明:本文為轉載文章,轉載此文目的在于傳遞更多信息,版權歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權問題,請聯系小編進行處理

審核編輯 黃宇

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

    關注

    6039

    文章

    44585

    瀏覽量

    636483
  • 框架
    +關注

    關注

    0

    文章

    403

    瀏覽量

    17511
收藏 人收藏

    評論

    相關推薦

    一種面向飛行試驗的數據融合框架

    天地氣動數據致性,針對某外形飛行試驗數據開展了典型對象的天地氣動數據融合方法研究。結合數據挖掘的隨機森林方法,本文提出了一種面向飛行試驗的數據融合
    的頭像 發表于 11-27 11:34 ?261次閱讀
    <b class='flag-5'>一種</b><b class='flag-5'>面向</b>飛行試驗的數據融合<b class='flag-5'>框架</b>

    單片機編程語言有哪些選擇

    些常用的單片機編程語言,以及它們的特點和應用場景: 1. C語言 特點 :C語言是一種通用的編程語言,以其高效性和靈活性而聞名。它提供了豐富的庫函數和直接的硬件訪問能力,非常適合用于單片機
    的頭像 發表于 11-01 14:13 ?699次閱讀

    單片機怎么寫入程序

    單片機(Microcontroller Unit,MCU)是一種集成電路芯片,它將計算機的CPU、存儲器、輸入/輸出接口等功能集成在個芯片上。單片機廣泛應用于嵌入式系統和物聯網設備中
    的頭像 發表于 10-21 11:21 ?545次閱讀

    單片機有哪些中斷類型

    單片機中斷是指在單片機執行程序的過程中,當外部設備或內部條件發生某個特定事件時,能夠暫停當前正在執行的程序,轉而去執行個特定的服務
    的頭像 發表于 10-17 18:12 ?830次閱讀

    單片機的中斷機制

    單片機的中斷機制是一種重要的處理方式,它允許單片機在執行主程序的過程中,能夠暫停當前任務,轉而處理外部或內部緊急事件。這種機制極大地提高了系統的響應速度和處理能力,使得
    的頭像 發表于 10-17 18:03 ?822次閱讀

    單片機io口的四工作狀態

    單片機的I/O口工作狀態是單片機編程和硬件操作中非常重要的部分,它決定了單片機如何與外部設備進行通信。 1.
    的頭像 發表于 09-14 14:24 ?1751次閱讀

    keil可以讀出單片機程序

    Keil是款廣泛應用于單片機程序開發的軟件,它提供了包括C編譯器、宏匯編、連接器、庫管理和個功能強大的仿真調試器等在內的完整開發方案。然而,關于Keil是否能直接“讀出”
    的頭像 發表于 09-02 10:32 ?1075次閱讀

    單片機燒錄程序用什么軟件

    單片機燒錄程序單片機開發過程中的個重要環節,涉及到將編寫好的程序代碼通過燒錄器寫入單片機的R
    的頭像 發表于 09-02 10:05 ?1394次閱讀

    單片機燒錄程序可以重新燒嗎

    單片機(Microcontroller Unit, MCU)是一種集成電路芯片,它將計算機的CPU、存儲器、輸入/輸出接口等集成在塊芯片上,用于控制各種電子設備。單片機燒錄
    的頭像 發表于 09-02 10:04 ?1349次閱讀

    單片機燒錄程序的線比單片機上的少還能燒錄嗎

    單片機燒錄原理 單片機燒錄是指將編寫好的程序代碼通過定的方式傳輸到單片機的存儲器中,使其能夠按照程序
    的頭像 發表于 09-02 09:54 ?535次閱讀

    單片機燒錄程序的基本步驟是什么

    單片機燒錄程序單片機開發過程中非常重要的步,它涉及到將編寫好的程序代碼通過
    的頭像 發表于 09-02 09:47 ?1164次閱讀

    文讀懂什么單片機:組成結構與應用

    歡迎來到單片機的世界,這是一種微小(但功能強大)的設備,改變了嵌入式系統的面貌。在本文中,您將了解單片機些基本知識、單片機的結構以及微處
    的頭像 發表于 08-09 11:49 ?1743次閱讀
    <b class='flag-5'>一</b>文讀懂什么<b class='flag-5'>單片機</b>:組成結構與應用

    數字電路仿真軟件單片機怎么用

    數字電路仿真軟件是一種用于模擬和測試數字電路設計的工具。其中,單片機仿真軟件是一種專門針對單片機進行仿真的工具。這種軟件能夠提供個類似真實
    的頭像 發表于 04-21 10:28 ?1095次閱讀

    單片機中斷功能及其應用

    單片機中斷功能及其應用? 單片機中斷是指在程序執行過程中,根據特定的條件或事件自動暫時中斷當前程序的執行,轉而執行特定的中斷服務程序。中斷是
    的頭像 發表于 01-30 14:45 ?5628次閱讀

    單片機原理及應用是什么

    單片機(Microcontroller)是一種集成電路(IC)芯片,其中包括了中央處理器(CPU)、存儲器和輸入/輸出(I/O)設備等功能模塊。它是一種小型計算機系統,具有獨立的工作能力和完整的計算
    的頭像 發表于 01-12 15:28 ?2185次閱讀
    主站蜘蛛池模板: 精品无码日本蜜桃麻豆| 在线免费观看国产| 约艺术院校96年清纯白嫩| YELLOW在线观看高清视频免费| 国产在线观看码高清视频| 欧美内射深插日本少妇| 亚洲精品福利在线| YY8848高清私人影院| 极品 女神校花 露脸91| 乳交高H糙汉宠文| 116美女写真成人午夜视频| 国产精品永久在线| 欧美特级另类xxx| 在线亚洲黄色| 国产三级在线精品男人的天堂| 琪琪热热色原日韩在线| 一区二区三区内射美女毛片| 国产精品观看视频免费完整版| 女性BBWBBWBBWBBW| 在线观看免费av网站| 国产睡熟迷奷系列精品| 全黄h全肉细节文在线观看| 中国欧美日韩一区二区三区| 国产亚洲精品线观看不卡| 日日干夜夜爽| 99久久精品费精品国产一区二| 久久国产高清字幕中文| 亚洲 自拍 偷拍 另类综合图区| 穿白丝袜边走边尿白丝袜| 摸老师丝袜小内内摸出水| 一区二区三区四区国产| 国内精品久久影视免费| 手机在线免费观看毛片| 办公室里做好紧好爽H| 男人一生要读的书| 中文字幕在线视频网站| 精品国产乱码久久久久久乱码| 特级毛片AAAAAA| 东日韩二三区| 日本乱子伦一区二区三区| caoporn 超碰在线视频|