女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

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

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

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

一份單片機(jī)多任務(wù)事件驅(qū)動C源碼

STM32嵌入式開發(fā) ? 來源:CSDN技術(shù)社區(qū) ? 2023-08-24 09:22 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

單片機(jī)ROMRAM存貯空間有限,一般沒有多線程可用,給復(fù)雜的單片機(jī)項(xiàng)目帶來困擾。

經(jīng)過多年的單片機(jī)項(xiàng)目實(shí)踐,借鑒windows消息機(jī)制的思想,編寫了單片機(jī)多任務(wù)事件驅(qū)動C代碼,應(yīng)用于單片機(jī)項(xiàng)目,無論復(fù)雜的項(xiàng)目,還是簡單的項(xiàng)目,都可以達(dá)到優(yōu)化代碼架構(gòu)的目的。

經(jīng)過幾輪的精簡、優(yōu)化,現(xiàn)在分享給大家。

代碼分為3個(gè)模塊:任務(wù)列表、事件列表、定時(shí)器列表。

任務(wù)列表創(chuàng)建一個(gè)全局列表管理任務(wù),通過調(diào)用taskCreat()創(chuàng)建事件處理任務(wù),創(chuàng)建成功返回任務(wù)ID,任務(wù)列表、事件列表與定時(shí)器列表通過任務(wù)ID關(guān)聯(lián)。

事件列表創(chuàng)建一個(gè)全局循環(huán)列表管理事件,調(diào)用taskEventIssue()生成一個(gè)事件,放到事件循環(huán)列表,taskEventLoop()函數(shù)放到主線程循環(huán)調(diào)用,當(dāng)事件循環(huán)列表中有事件時(shí),根據(jù)任務(wù)ID分發(fā)到具體的事件處理任務(wù)。

定時(shí)器列表創(chuàng)建一個(gè)全局列表管理定時(shí)器,taskTimer()建立一個(gè)定時(shí)器,放到定時(shí)器列表執(zhí)行,當(dāng)定時(shí)時(shí)間到,會生成一個(gè)定時(shí)器事件,放到事件列表,分發(fā)到具體的事件處理任務(wù)。

//common.h
#ifndef __COMMON_H
#define __COMMON_H


#include "stdio.h"
#include 
#include 


typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef unsigned char bool;


#define false 0
#define true 1


#endif // __COMMON_H

//task.h
#ifndef _THREAD_H
#define _THREAD_H


#define TASK_MAX 20 // 最多任務(wù)數(shù)量
#define TASK_EVENT_MAX 100 // 任務(wù)隊(duì)列長度
#define TASK_TIMER_MAX 100 // 定時(shí)器最大數(shù)量


typedef void (*CBTaskEvent)(int taskID,uint32_t eventID);
typedef struct _TASK_EVENT
{
    int taskID;
    uint32_t eventID;


} TASK_EVENT;


int taskCreat(CBTaskEvent task);
void taskLoop();
void taskEventIssue(int taskID,uint32_t eventID);
void taskEventLoop();


//定時(shí)、休眠


typedef struct _TASK_TIMER
{
    bool isValid;
    int taskID;
    uint32_t eventID;
    uint32_t timeMs;
    uint32_t start;


} TASK_TIMER;


void taskTicksInc();
void taskTimer(int taskID,uint32_t eventID,uint32_t time_ms);
void taskTimerLoop();


#endif // _THREAD_H

//task.c
#include "common.h"
#include "task.h"


CBTaskEvent g_taskList[TASK_MAX]={0};


int taskFindEmpty()
{
    static int index = -1;


    for(int i=0; i
",taskID);


    return taskID;
}


void taskDestroy(int taskID)
{
    printf("Destroy task<%d>
",taskID);


    g_taskList[taskID] = NULL;
}


void taskLoop()
{
    taskEventLoop();
    taskTimerLoop();
}


TASK_EVENT g_taskEventList[TASK_EVENT_MAX];
int g_TKEventWrite=0;
int g_TKEventRead=0;


int tkEventGetSize()
{
    return (g_TKEventWrite + TASK_EVENT_MAX - g_TKEventRead)% TASK_EVENT_MAX;
}


void taskEventIssue(int taskID,uint32_t eventID)
{
    int writePos;


    if(taskID >= TASK_EVENT_MAX || taskID < 0)
    {
        printf("taskEventIssue() error:taskID
");
        return;
    }


    writePos = (g_TKEventWrite + 1)% TASK_EVENT_MAX;


    if(writePos == g_TKEventRead)
    {
        printf("taskEventIssue() error:task<%d> event list is full!
",taskID);
        return;
    }


    g_taskEventList[g_TKEventWrite].taskID=taskID;
    g_taskEventList[g_TKEventWrite].eventID=eventID;
    g_TKEventWrite=writePos;


    //printf("add event:%x
",eventID);
}


void taskEventLoop()
{
    TASK_EVENT event;
    CBTaskEvent task;
    int size;


    size=tkEventGetSize();
    while(size-- >0)
    {
        event=g_taskEventList[g_TKEventRead];
        g_TKEventRead = (g_TKEventRead + 1)% TASK_EVENT_MAX;


        task = g_taskList[event.taskID];
        if(!task)
        {
            printf("taskEventLoop() error:task is NULL
");
            continue;
        }


        task(event.taskID,event.eventID);
    }
}


// 定時(shí)、休眠


uint32_t g_taskTicks=0;


uint32_t getTaskTicks()
{
    return g_taskTicks;
}


void taskTicksInc() // 1ms時(shí)間基準(zhǔn)
{
    g_taskTicks++;
}


uint32_t taskTickDiff(uint32_t now,uint32_t last)
{
    uint64_t diff;
    diff = now + 0x100000000 - last;


    return (diff & 0xffffffff);
}


TASK_TIMER g_taskTimerList[TASK_TIMER_MAX]={0};


int taskTimerFindEmpty()
{
    for(int i=0; i %ums
",taskID,eventID,time_ms);


}


void taskTimerLoop()
{
    static uint32_t start=0;
    if(taskTickDiff(getTaskTicks(),start)<3)
    {
        return;
    }


    start=getTaskTicks();


    for(int i=0; i=g_taskTimerList[i].timeMs)
            {
                taskEventIssue(g_taskTimerList[i].taskID,g_taskTimerList[i].eventID);
                g_taskTimerList[i].isValid=false;
            }
        }
    }
}

//test_task.h
#ifndef _TEST_THREAD_H
#define _TEST_THREAD_H


void testInit();
void testLoop();


#endif // 

//test_task.c
#include "common.h"
#include "task.h"


#define CTRL_EVENT1 0x01
#define CTRL_EVENT2 0x02
#define CTRL_EVENT3 0x04


void eventProcess(int taskID,uint32_t event)
{
    switch(event)
    {
        case CTRL_EVENT1:
            printf("task[%d] CTRL_EVENT1
",taskID);
            //taskEventIssue(taskID,CTRL_EVENT2);
            taskTimer(taskID,CTRL_EVENT2,1000);
            break;


        case CTRL_EVENT2:
            printf("task[%d] CTRL_EVENT2
",taskID);
            //taskEventIssue(taskID,CTRL_EVENT3);
            taskTimer(taskID,CTRL_EVENT3,2000);
            break;


        case CTRL_EVENT3:
            printf("task[%d] CTRL_EVENT3
",taskID);
            taskTimer(taskID,CTRL_EVENT1,4000);
            break;


        default:
            break;
    }
}


void testLoop()
{
    taskLoop();
}


void testInit()
{
    int taskID1,taskID2;


    printf("testInit()
");


    taskID1 = taskCreat((CBTaskEvent)&eventProcess);


    taskTimer(taskID1,CTRL_EVENT1,5000);


    taskID2 = taskCreat((CBTaskEvent)&eventProcess);
    taskEventIssue(taskID2,CTRL_EVENT2);
    taskDestroy(taskID1);
    taskDestroy(taskID2);
    //taskEventIssue(taskID1,CTRL_EVENT1);
    taskID1 = taskCreat((CBTaskEvent)&eventProcess);
    taskEventIssue(taskID1,CTRL_EVENT1);
}

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

    關(guān)注

    6067

    文章

    44983

    瀏覽量

    650272
  • ROM
    ROM
    +關(guān)注

    關(guān)注

    4

    文章

    578

    瀏覽量

    87332
  • WINDOWS
    +關(guān)注

    關(guān)注

    4

    文章

    3613

    瀏覽量

    91382
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3298

    瀏覽量

    118847
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    671

    瀏覽量

    30317

原文標(biāo)題:一份單片機(jī)多任務(wù)事件驅(qū)動C源碼

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

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

掃碼添加小助手

加入工程師交流群

    評論

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

    單片機(jī)分時(shí)多任務(wù)

    本帖最后由 eehome 于 2013-1-5 09:44 編輯 單片機(jī)分時(shí)多任務(wù)
    發(fā)表于 08-17 15:56

    單片機(jī)小型操作系統(tǒng)多任務(wù)并行的原理

    如果在單片機(jī)的中斷中修改了堆棧中的PC指針值,那么是不是中斷就返不回來原來的程序地址?如果還是這個(gè)地址是我故意設(shè)定的值那么他是不是執(zhí)行完這個(gè)中斷就跳到我的設(shè)定的這個(gè)地址上去了?如果這個(gè)地址又是另外個(gè)任務(wù)
    發(fā)表于 10-18 10:59

    51單片機(jī)多任務(wù)設(shè)計(jì)

    51單片機(jī)多任務(wù)設(shè)計(jì)
    發(fā)表于 05-14 20:16

    單片機(jī)多任務(wù)事件驅(qū)動C源碼分享

    單片機(jī)多任務(wù)事件驅(qū)動C源碼
    發(fā)表于 01-24 06:31

    51單片機(jī)多任務(wù)操作系統(tǒng)的原理是什么?

    51單片機(jī)多任務(wù)操作系統(tǒng)的原理
    發(fā)表于 11-06 08:10

    51單片機(jī)多任務(wù)機(jī)制的實(shí)現(xiàn)策略研究

    從操作系統(tǒng)實(shí)現(xiàn)多任務(wù)機(jī)制的原理入手,分析了51單片機(jī)實(shí)現(xiàn)多任務(wù)機(jī)制的基本條件,論述了5l單片機(jī)實(shí)現(xiàn)多任務(wù)控制的二種方案。
    發(fā)表于 09-19 17:26 ?159次下載
    51<b class='flag-5'>單片機(jī)</b><b class='flag-5'>多任務(wù)</b>機(jī)制的實(shí)現(xiàn)策略研究

    單片機(jī)系統(tǒng)多任務(wù)實(shí)現(xiàn)方法

    考慮到成本等因素,大多數(shù)單片機(jī)系統(tǒng)的開發(fā)還是基于處理器直接編寫,但開發(fā)者經(jīng)常面臨同時(shí)處理多個(gè)任務(wù)的要求,提出了單片機(jī)多任務(wù)程序設(shè)計(jì)的方法
    發(fā)表于 11-21 16:47 ?750次下載

    MSP430單片機(jī)實(shí)時(shí)多任務(wù)操作系統(tǒng)c源代碼

    : 資料-【C】嵌入系統(tǒng)-【C0】嵌入式綜合-【2】單片機(jī)編程-【參考程序】-MSP430單片機(jī)的實(shí)時(shí)多任務(wù)操作系統(tǒng)
    發(fā)表于 09-18 10:18 ?91次下載
    MSP430<b class='flag-5'>單片機(jī)</b>實(shí)時(shí)<b class='flag-5'>多任務(wù)</b>操作系統(tǒng)<b class='flag-5'>c</b>源代碼

    51單片機(jī)多任務(wù)操作系統(tǒng)的原理與實(shí)現(xiàn)

    51單片機(jī)多任務(wù)操作系統(tǒng)的原理與實(shí)現(xiàn),在51單片機(jī)上模擬操作系統(tǒng)
    發(fā)表于 02-28 15:09 ?16次下載

    基于實(shí)時(shí)操作系統(tǒng)的單片機(jī)多任務(wù)應(yīng)用程序設(shè)計(jì)

    基于實(shí)時(shí)操作系統(tǒng)的單片機(jī)多任務(wù)應(yīng)用程序設(shè)計(jì)
    發(fā)表于 10-27 15:21 ?49次下載
    基于實(shí)時(shí)操作系統(tǒng)的<b class='flag-5'>單片機(jī)</b><b class='flag-5'>多任務(wù)</b>應(yīng)用程序設(shè)計(jì)

    如何使用51單片機(jī)實(shí)現(xiàn)多任務(wù)機(jī)制的策略詳細(xì)資料說明

    51單片機(jī)在微型智能控制系統(tǒng)中應(yīng)用很廣,隨著人們對控制系統(tǒng)的要求不斷提高,51單片機(jī)的功能局限越發(fā)明顯。特別是51系列單片機(jī)不具有實(shí)時(shí)多任務(wù)支持功能,大大限制其在控制系統(tǒng)中的進(jìn)
    發(fā)表于 07-17 17:38 ?6次下載
    如何使用51<b class='flag-5'>單片機(jī)</b>實(shí)現(xiàn)<b class='flag-5'>多任務(wù)</b>機(jī)制的策略詳細(xì)資料說明

    單片機(jī)多任務(wù)處理方案

    單片機(jī)要執(zhí)行多任務(wù),可以使用中斷的方式,也可以使用操作系統(tǒng),目前有些適用于單片機(jī)的小型操作系統(tǒng)。
    的頭像 發(fā)表于 09-13 15:45 ?1w次閱讀

    使用單片機(jī)實(shí)現(xiàn)道路交通燈多任務(wù)控制系統(tǒng)的課件說明

     RTX-51是運(yùn)行于8051單片機(jī)環(huán)境中的實(shí)時(shí)多任務(wù)操作系統(tǒng)(RTOS),其常用于處理復(fù)雜的多任務(wù)控制系統(tǒng)。8051單片機(jī)支持典型的RTX-51 Tiny和RTX-51 Full實(shí)時(shí)
    發(fā)表于 04-16 17:31 ?7次下載
    使用<b class='flag-5'>單片機(jī)</b>實(shí)現(xiàn)道路交通燈<b class='flag-5'>多任務(wù)</b>控制系統(tǒng)的課件說明

    基于M16C62單片機(jī)構(gòu)成的實(shí)時(shí)多任務(wù)系統(tǒng)

    多任務(wù)系統(tǒng)的設(shè)計(jì)合應(yīng)用成為單片機(jī)應(yīng)用的新的發(fā)展趨勢。 μC/OS-Ⅱ是個(gè)源碼公開的實(shí)時(shí)嵌入式操作系統(tǒng),它的特點(diǎn)在于公開的源代碼,很強(qiáng)的移
    的頭像 發(fā)表于 10-30 11:48 ?625次閱讀

    單片機(jī)多任務(wù)事件驅(qū)動C源碼

    單片機(jī)多任務(wù)事件驅(qū)動C源碼
    發(fā)表于 11-29 10:06 ?26次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>多任務(wù)</b>事件<b class='flag-5'>驅(qū)動</b><b class='flag-5'>C</b><b class='flag-5'>源碼</b>