91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

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

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

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

非常實用,推薦一種面向?qū)ο笏季S的單片機程序框架

jf_pJlTbmA9 ? 來源:小麥大叔 ? 作者:小麥大叔 ? 2023-10-24 18:03 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

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

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

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

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

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

Demo

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

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

//創(chuàng)建5個任務(wù)對象
TimesilceTaskObjtask_1,task_2,task_3,task_4,task_5;

//具體的任務(wù)函數(shù)
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");
}

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

運行結(jié)果如下:

poYBAGGnJ7OAZ5XZAACMwYJDoAU530.png

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

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

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

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

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內(nèi)核中使用十分廣泛,也十分經(jīng)典,其原理具體可以參考文章:

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

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

來源:小麥大叔

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

審核編輯 黃宇

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

    關(guān)注

    6076

    文章

    45495

    瀏覽量

    670442
  • 框架
    +關(guān)注

    關(guān)注

    0

    文章

    404

    瀏覽量

    18425
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    文說透了如何實現(xiàn)單片機的多任務(wù)并發(fā)!

    資源,并且避免出現(xiàn)資源爭搶和堵塞的情況。 在單片機多任務(wù)并發(fā)中,常見的任務(wù)調(diào)度方式有兩: 1. 時間片輪轉(zhuǎn)法 時間片輪轉(zhuǎn)法是多任務(wù)并發(fā)中最基本的調(diào)度算法之,它的核心思想是輪流分配 CPU 時間片
    發(fā)表于 01-06 06:46

    面向單片機、事件驅(qū)動的嵌入式開發(fā)平臺介紹

    EventOS,是面向單片機、事件驅(qū)動的嵌入式開發(fā)平臺。它主要有兩大技術(shù)特色:是事件驅(qū)動,二是超輕量。EventOS以及其母項目EventOS,目標是開發(fā)
    發(fā)表于 12-05 06:26

    為什么單片機還在用C語言編程?

    最適合單片機開發(fā)的編程語言實在太過晦澀難懂,學習起來非常的不方便,并且每一種單片機的匯編指令有很大區(qū)別,所以想把
    發(fā)表于 11-28 07:37

    單片機開發(fā)中常用的三軟件架構(gòu)介紹

    // ... 找零邏輯 P2 = 0xFF;// 關(guān)閉機械臂} 6.面向對象架構(gòu)STM32的庫,就是一種面向對象的架構(gòu)。 不過在
    發(fā)表于 11-26 08:05

    C語言和單片機C語言有什么差異

    單片機c語言相對于普通C語言增加了些基本的指令,還有變量的賦值是16進制,當然單片機c語言只牽涉到普通c語言非常基礎(chǔ)部分。 主要的差異具體體現(xiàn)在: 1、
    發(fā)表于 11-14 07:55

    PYQT 應(yīng)用程序框架及開發(fā)工具

    大家好,本團隊此次分享的內(nèi)容為開發(fā)過程中使用到的PYQT 應(yīng)用程序框架及開發(fā)工具。 pYqt 是個多平臺的 python 圖形用戶界面應(yīng)用程序
    發(fā)表于 10-29 07:15

    單片機個承載科技與工程思維的核心平臺

    在現(xiàn)代社會中,科技的快速發(fā)展推動了各個行業(yè)和技術(shù)的革新。單片機(Single Chip Computer)作為一種集成化的電子系統(tǒng),正在逐漸成為連接數(shù)字世界與物理世界的橋梁。無論是智能家居、自動駕駛
    的頭像 發(fā)表于 09-29 01:07 ?577次閱讀

    單片機燒錄原理是怎樣的?輝芒微單片機燒錄程序詳細步驟講解

    燒錄(Programming)就是把 .hex/.bin 文件里的機器碼搬運進單片機片內(nèi) Flash 的過程。輝芒微(FMD)單片機內(nèi)部有塊 自舉 BootROM,上電時會先跑這段程序
    的頭像 發(fā)表于 09-17 16:14 ?2339次閱讀
    <b class='flag-5'>單片機</b>燒錄原理是怎樣的?輝芒微<b class='flag-5'>單片機</b>燒錄<b class='flag-5'>程序</b>詳細步驟講解

    一種適用于動態(tài)環(huán)境的自適應(yīng)先驗場景-對象SLAM框架

    由于傳統(tǒng)視覺SLAM在動態(tài)場景中容易會出現(xiàn)嚴重的定位漂移,本文提出了一種新穎的基于場景-對象的可靠性評估框架,該框架通過當前幀質(zhì)量指標以及相對于可靠參考幀的場景變化,全面評估SLAM的
    的頭像 發(fā)表于 08-19 14:17 ?877次閱讀
    <b class='flag-5'>一種</b>適用于動態(tài)環(huán)境的自適應(yīng)先驗場景-<b class='flag-5'>對象</b>SLAM<b class='flag-5'>框架</b>

    單片機原理及應(yīng)用詳解

    單片機(Microcontroller Unit, MCC) ?是一種集成計算機核心功能(CPU、存儲器、I/O接口等)的微型芯片,廣泛應(yīng)用于嵌入式系統(tǒng)中。以下是其原理及應(yīng)用的詳細介紹: 、
    的頭像 發(fā)表于 08-11 13:57 ?2305次閱讀

    怎么測單片機系統(tǒng)頻率

    單片機系統(tǒng)頻率是指單片機工作時的時鐘頻率,它直接影響單片機的運行速度和處理能力,準確測量系統(tǒng)頻率對單片機應(yīng)用開發(fā)、程序調(diào)試和性能優(yōu)化具有重要
    的頭像 發(fā)表于 07-25 11:39 ?794次閱讀

    單片機怎么燒程序

    單片機程序是將編寫好的程序代碼寫入單片機內(nèi)部存儲單元,讓單片機按照預(yù)設(shè)邏輯工作的過程,是單片機
    的頭像 發(fā)表于 07-23 11:47 ?1307次閱讀

    STC單片機范例程序

    電子發(fā)燒友網(wǎng)站提供《STC單片機范例程序.zip》資料免費下載
    發(fā)表于 06-04 16:27 ?10次下載

    單片機和伺服有什么區(qū)別

    : 1. 定義與功能 特性 單片機(Microcontroller) 伺服系統(tǒng)(Servo System) 定義 一種集成CPU、內(nèi)存、I/O接口的微型計算機芯片,用于控制設(shè)備。 一種由伺服電機、編碼器
    的頭像 發(fā)表于 05-26 09:18 ?860次閱讀

    一種新型直流電機控制器

    以前控制直流電機多由單片機完成。該方式缺點是接口繁瑣、速度慢,且不易在高溫、高壓等惡劣環(huán)境下工作[1]。采用一種新型直流電機控制器——DSP 控制器解決了單片機控制的缺點,其具備很多優(yōu)點,該控制器
    發(fā)表于 03-25 15:25