chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

單片機(jī)常用的九大軟件架構(gòu)盤(pán)點(diǎn)

無(wú)際單片機(jī)編程 ? 來(lái)源:無(wú)際單片機(jī)編程 ? 2024-04-29 16:40 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

可能很多工程師,工作了很多年,都不會(huì)有軟件架構(gòu)的概念。 因?yàn)槲以谧鲅邪l(fā)工程師的第6年,才開(kāi)始意識(shí)到這個(gè)東西,在此之前,都是做一些比較簡(jiǎn)單的項(xiàng)目,一個(gè)main函數(shù)干到底,架構(gòu)復(fù)雜了反而是累贅。 后面有幸,接觸了稍微復(fù)雜點(diǎn)的項(xiàng)目,感覺(jué)以前水平Hold不住,然后借著項(xiàng)目需求,學(xué)習(xí)了很多優(yōu)秀的代碼架構(gòu),比如以前同事的,一些模組廠的SDK,還有市面上成熟的系統(tǒng)。 說(shuō)出來(lái)可能有點(diǎn)夸張,一個(gè)好項(xiàng)目帶來(lái)的成長(zhǎng),頂你做幾年小項(xiàng)目。 在一個(gè)工程師從入門(mén)到成為高級(jí)工程師,都會(huì)經(jīng)歷哪些軟件架構(gòu)?

下面給大家盤(pán)點(diǎn)一下,每個(gè)都提供了簡(jiǎn)易的架構(gòu)模型代碼,難度循環(huán)漸進(jìn)。

1.線(xiàn)性架構(gòu)

這是最簡(jiǎn)單的一種程序設(shè)計(jì)方法,也就是我們?cè)谌腴T(mén)時(shí)寫(xiě)的,下面是一個(gè)使用C語(yǔ)言編寫(xiě)的線(xiàn)性架構(gòu)示例:

#include   // 包含51系列單片機(jī)寄存器定義


// 延時(shí)函數(shù),用于產(chǎn)生一定的延遲
void delay(unsigned int count) {
    unsigned int i;
    while(count--) {
        for(i = 0; i < 120; i++) {}  // 空循環(huán),用于產(chǎn)生延遲
    }
}


void main() {
    // 初始設(shè)置P1端口為輸出模式,用于控制LED
    P1 = 0xFF;  // 將P1端口設(shè)置為高電平,關(guān)閉所有LED


    while(1) {  // 無(wú)限循環(huán)
        P1 = 0x00;  // 將P1端口設(shè)置為低電平,點(diǎn)亮所有LED
        delay(500000);  // 調(diào)用延時(shí)函數(shù),延遲一段時(shí)間


        P1 = 0xFF;  // 將P1端口設(shè)置為高電平,關(guān)閉所有LED
        delay(500000);  // 再次調(diào)用延時(shí)函數(shù),延遲相同的時(shí)間
    }
}
? 2.模塊化架構(gòu) 模塊化架構(gòu)是一種將程序分解為獨(dú)立模塊的設(shè)計(jì)方法,每個(gè)模塊執(zhí)行特定的任務(wù)。 這種架構(gòu)有助于代碼的重用、維護(hù)和測(cè)試。 下面是一個(gè)使用C語(yǔ)言編寫(xiě)的模塊化架構(gòu)示例,該程序模擬了一個(gè)簡(jiǎn)單的交通信號(hào)燈控制系統(tǒng)。
#include   // 包含51系列單片機(jī)的寄存器定義


// 定義信號(hào)燈的狀態(tài)
typedef enum {
    RED_LIGHT,
    YELLOW_LIGHT,
    GREEN_LIGHT
} TrafficLightState;


// 函數(shù)聲明
void initializeTrafficLight(void);
void setTrafficLight(TrafficLightState state);
void delay(unsigned int milliseconds);


// 信號(hào)燈控制主函數(shù)
void main(void) {
    initializeTrafficLight();  // 初始化交通信號(hào)燈


    while(1) {
        setTrafficLight(RED_LIGHT);
        delay(5000);  // 紅燈亮5秒


        setTrafficLight(YELLOW_LIGHT);
        delay(2000);  // 黃燈亮2秒


        setTrafficLight(GREEN_LIGHT);
        delay(5000);  // 綠燈亮5秒
    }
}


// 初始化交通信號(hào)燈的函數(shù)
void initializeTrafficLight(void) {
    // 這里可以添加初始化代碼,比如設(shè)置端口方向、默認(rèn)狀態(tài)等
    // 假設(shè)P1端口連接了信號(hào)燈,初始狀態(tài)為熄滅(高電平)
    P1 = 0xFF;
}


// 設(shè)置交通信號(hào)燈狀態(tài)的函數(shù)
void setTrafficLight(TrafficLightState state) {
    switch(state) {
        case RED_LIGHT:
            // 設(shè)置紅燈亮,其他燈滅
            P1 = 0b11100000;  // 假設(shè)低電平有效,這里設(shè)置P1.0為低電平,其余為高電平
            break;
        case YELLOW_LIGHT:
            // 設(shè)置黃燈亮,其他燈滅
            P1 = 0b11011000;  // 設(shè)置P1.1為低電平,其余為高電平
            break;
        case GREEN_LIGHT:
            // 設(shè)置綠燈亮,其他燈滅
            P1 = 0b11000111;  // 設(shè)置P1.2為低電平,其余為高電平
            break;
        default:
            // 默認(rèn)為熄滅所有燈
            P1 = 0xFF;
            break;
    }
}


// 延時(shí)函數(shù),參數(shù)是毫秒數(shù)
void delay(unsigned int milliseconds) {
    unsigned int delayCount = 0;
    while(milliseconds--) {
        for(delayCount = 0; delayCount < 120; delayCount++) {
            // 空循環(huán),用于產(chǎn)生延時(shí)
        }
    }
}

3.層次化架構(gòu) 層次化架構(gòu)是一種將系統(tǒng)分解為多個(gè)層次的設(shè)計(jì)方法,每個(gè)層次負(fù)責(zé)不同的功能。

著以下是一個(gè)使用C語(yǔ)言編寫(xiě)的層次化架構(gòu)示例,模擬了一個(gè)具有不同權(quán)限級(jí)別的嵌入式系統(tǒng)。

#include   // 包含51系列單片機(jī)的寄存器定義


// 定義不同的操作級(jí)別
typedef enum {
    LEVEL_USER,
    LEVEL_ADMIN,
    LEVEL_SUPERUSER
} OperationLevel;


// 函數(shù)聲明
void systemInit(void);
void performOperation(OperationLevel level);
void displayMessage(char* message);


// 系統(tǒng)初始化后的主循環(huán)
void main(void) {
    systemInit();  // 系統(tǒng)初始化


    // 模擬用戶(hù)操作
    performOperation(LEVEL_USER);
    // 模擬管理員操作
    performOperation(LEVEL_ADMIN);
    // 模擬超級(jí)用戶(hù)操作
    performOperation(LEVEL_SUPERUSER);


    while(1) {
        // 主循環(huán)可以是空閑循環(huán)或者處理其他低優(yōu)先級(jí)任務(wù)
    }
}


// 系統(tǒng)初始化函數(shù)
void systemInit(void) {
    // 初始化系統(tǒng)資源,如設(shè)置端口、中斷等
    // 這里省略具體的初始化代碼
}


// 執(zhí)行不同級(jí)別操作的函數(shù)
void performOperation(OperationLevel level) {
    switch(level) {
        case LEVEL_USER:
          //用戶(hù)操作具體代碼
            break;
        case LEVEL_ADMIN:
          //管理員操作具體代碼
            break;
        case LEVEL_SUPERUSER:
           //超級(jí)用戶(hù)操作具體代碼
            break;
    }
}


// 顯示消息的函數(shù)
void displayMessage(char* message) {
    // 這里省略了實(shí)際的顯示代碼,因?yàn)閱纹瑱C(jī)通常沒(méi)有直接的屏幕輸出
    // 消息可以通過(guò)LED閃爍、串口輸出或其他方式展示
    // 假設(shè)通過(guò)P1端口的LED展示,每個(gè)字符對(duì)應(yīng)一個(gè)LED閃爍模式
    // 實(shí)際應(yīng)用中,需要根據(jù)硬件設(shè)計(jì)來(lái)實(shí)現(xiàn)消息的顯示
}



4.事件驅(qū)動(dòng)架構(gòu)

事件驅(qū)動(dòng)架構(gòu)是一種編程范式,其中程序的執(zhí)行流程由事件(如用戶(hù)輸入、傳感器變化、定時(shí)器到期等)觸發(fā)。 在單片機(jī)開(kāi)發(fā)中,事件驅(qū)動(dòng)架構(gòu)通常用于響應(yīng)外部硬件中斷或軟件中斷。 以下是一個(gè)使用C語(yǔ)言編寫(xiě)的事件驅(qū)動(dòng)架構(gòu)示例,模擬了一個(gè)基于按鍵輸入的LED控制。

#include   // 包含51系列單片機(jī)的寄存器定義


// 定義按鍵和LED的狀態(tài)
#define KEY_PORT P3  // 假設(shè)按鍵連接在P3端口
#define LED_PORT P2  // 假設(shè)LED連接在P2端口


// 函數(shù)聲明
void delay(unsigned int milliseconds);
bit checkKeyPress(void);  // 返回按鍵是否被按下的狀態(tài)(1表示按下,0表示未按下)


// 定時(shí)器初始化函數(shù)
void timer0Init(void) 
{
    TMOD = 0x01;  // 設(shè)置定時(shí)器模式寄存器,使用模式1(16位定時(shí)器)
    TH0 = 0xFC;   // 設(shè)置定時(shí)器初值,用于產(chǎn)生定時(shí)中斷
    TL0 = 0x18;
    ET0 = 1;      // 開(kāi)啟定時(shí)器0中斷
    EA = 1;       // 開(kāi)啟總中斷
    TR0 = 1;      // 啟動(dòng)定時(shí)器
}


// 定時(shí)器中斷服務(wù)程序
void timer0_ISR() interrupt 1 
{
    // 定時(shí)器溢出后自動(dòng)重新加載初值,無(wú)需手動(dòng)重置
    // 這里可以放置定時(shí)器溢出后需要執(zhí)行的代碼
}


// 按鍵中斷服務(wù)程序
bit keyPress_ISR(void) interrupt 2 using 1 
{
    if(KEY_PORT != 0xFF) // 檢測(cè)是否有按鍵按下
        {  
        LED_PORT = ~LED_PORT;  // 如果有按鍵按下,切換LED狀態(tài)
        delay(20);  // 去抖動(dòng)延時(shí)
        while(KEY_PORT != 0xFF);  // 等待按鍵釋放
        return 1;  // 返回按鍵已按下
    }
    return 0;  // 如果沒(méi)有按鍵按下,返回0
}


// 延時(shí)函數(shù),參數(shù)是毫秒數(shù)
void delay(unsigned int milliseconds) {
    unsigned int i, j;
    for(i = 0; i < milliseconds; i++)
        for(j = 0; j < 1200; j++);  // 空循環(huán),用于產(chǎn)生延時(shí)
}


// 主函數(shù)
void main(void) 
{
    timer0Init();  // 初始化定時(shí)器
    LED_PORT = 0xFF;  // 初始LED熄滅(假設(shè)低電平點(diǎn)亮LED)


    while(1) 
    {
        if(checkKeyPress())
        {  // 檢查是否有按鍵按下事件
            // 如果有按鍵按下,這里可以添加額外的處理代碼
        }
    }
}


// 檢查按鍵是否被按下的函數(shù)
bit checkKeyPress(void) 
{
    bit keyState = 0;
    // 模擬按鍵中斷觸發(fā),實(shí)際應(yīng)用中需要連接硬件中斷
    if(1) // 假設(shè)按鍵中斷觸發(fā)
    {  
      keyState = keyPress_ISR();  // 調(diào)用按鍵中斷服務(wù)程序
    }
    return keyState;  // 返回按鍵狀態(tài)
}
事實(shí)上,真正的事件型驅(qū)動(dòng)架構(gòu),是非常復(fù)雜的,我職業(yè)生涯的巔峰之作,就是用的事件型驅(qū)動(dòng)架構(gòu)。

c5f76e4a-0601-11ef-a297-92fbcf53809c.png

5.狀態(tài)機(jī)架構(gòu) 在單片機(jī)開(kāi)發(fā)中,狀態(tài)機(jī)常用于處理復(fù)雜的邏輯和事件序列,如用戶(hù)界面管理、協(xié)議解析等。 以下是一個(gè)使用C語(yǔ)言編寫(xiě)的有限狀態(tài)機(jī)(FSM)的示例,模擬了一個(gè)簡(jiǎn)單的自動(dòng)售貨機(jī)的狀態(tài)轉(zhuǎn)換。

#include   // 包含51系列單片機(jī)的寄存器定義


// 定義自動(dòng)售貨機(jī)的狀態(tài)
typedef enum {
    IDLE,
    COIN_INSERTED,
    PRODUCT_SELECTED,
    DISPENSE,
    CHANGE_RETURNED
} VendingMachineState;


// 定義事件
typedef enum {
    COIN_EVENT,
    PRODUCT_EVENT,
    DISPENSE_EVENT,
    REFUND_EVENT
} VendingMachineEvent;


// 函數(shù)聲明
void processEvent(VendingMachineEvent event);
void dispenseProduct(void);
void returnChange(void);


// 當(dāng)前狀態(tài)
VendingMachineState currentState = IDLE;


// 主函數(shù)
void main(void)
{
    // 初始化代碼(如果有)
    // ...


    while(1)
    {
        // 假設(shè)事件由外部觸發(fā),這里使用一個(gè)模擬事件
        VendingMachineEvent currentEvent = COIN_EVENT; // 模擬投入硬幣事件


        processEvent(currentEvent);  // 處理當(dāng)前事件
    }
}


// 處理事件的函數(shù)
void processEvent(VendingMachineEvent event)
{
    switch(currentState)
    {
        case IDLE:
            if(event == COIN_EVENT)
            {
                // 如果在空閑狀態(tài)且檢測(cè)到硬幣投入事件,則轉(zhuǎn)換到硬幣投入狀態(tài)
                currentState = COIN_INSERTED;
            }
            break;
        case COIN_INSERTED:
            if(event == PRODUCT_EVENT)
            {
                // 如果在硬幣投入狀態(tài)且用戶(hù)選擇商品,則請(qǐng)求出貨
                currentState = PRODUCT_SELECTED;
            }
            break;
        case PRODUCT_SELECTED:
            if(event == DISPENSE_EVENT)
            {
                dispenseProduct();  // 出貨商品
                currentState = DISPENSE;
            }
            break;
        case DISPENSE:
            if(event == REFUND_EVENT)
            {
                returnChange();  // 返回找零
                currentState = CHANGE_RETURNED;
            }
            break;
        case CHANGE_RETURNED:
            // 等待下一個(gè)循環(huán),返回到IDLE狀態(tài)
            currentState = IDLE;
            break;
        default:
            // 如果狀態(tài)非法,重置為IDLE狀態(tài)
            currentState = IDLE;
            break;
    }
}


// 出貨商品的函數(shù)
void dispenseProduct(void)
{
    // 這里添加出貨邏輯,例如激活電機(jī)推出商品
    // 假設(shè)P1端口連接了出貨電機(jī)
    P1 = 0x00;  // 激活電機(jī)
    // ... 出貨邏輯
    P1 = 0xFF;  // 關(guān)閉電機(jī)
}


// 返回找零的函數(shù)
void returnChange(void)
{
    // 這里添加找零邏輯,例如激活機(jī)械臂放置零錢(qián)
    // 假設(shè)P2端口連接了找零機(jī)械臂
    P2 = 0x00;  // 激活機(jī)械臂
    // ... 找零邏輯
    P2 = 0xFF;  // 關(guān)閉機(jī)械臂
}

6.面向?qū)ο蠹軜?gòu) STM32的庫(kù),就是一種面向?qū)ο蟮募軜?gòu)。 不過(guò)在單片機(jī)由于資源限制,OOP并不像在高級(jí)語(yǔ)言中那樣常見(jiàn),但是一些基本概念如封裝和抽象仍然可以被應(yīng)用。

雖然C語(yǔ)言本身并不直接支持面向?qū)ο缶幊?,但可以通過(guò)結(jié)構(gòu)體和函數(shù)指針模擬一些面向?qū)ο蟮奶匦浴? 下面是一個(gè)簡(jiǎn)化的示例,展示如何在C語(yǔ)言中模擬面向?qū)ο蟮木幊田L(fēng)格,以51單片機(jī)為背景,創(chuàng)建一個(gè)簡(jiǎn)單的LED類(lèi)。

#include 


// 定義一個(gè)LED類(lèi)
typedef struct {
    unsigned char state;  // LED的狀態(tài)
    unsigned char pin;    // LED連接的引腳
    void (*turnOn)(struct LED*);  // 點(diǎn)亮LED的方法
    void (*turnOff)(struct LED*); // 熄滅LED的方法
} LED;


// LED類(lèi)的構(gòu)造函數(shù)
void LED_Init(LED* led, unsigned char pin) {
    led->state = 0;  // 默認(rèn)狀態(tài)為熄滅
    led->pin = pin;   // 設(shè)置LED連接的引腳
}


// 點(diǎn)亮LED的方法
void LED_TurnOn(LED* led) {
    // 根據(jù)引腳狀態(tài)點(diǎn)亮LED
    if(led->pin < 8) {
        P0 |= (1 << led->pin);  // 假設(shè)P0.0到P0.7連接了8個(gè)LED
    } else {
        P1 &= ~(1 << (led->pin - 8));  // 假設(shè)P1.0到P1.7連接了另外8個(gè)LED
    }
    led->state = 1;  // 更新?tīng)顟B(tài)為點(diǎn)亮
}


// 熄滅LED的方法
void LED_TurnOff(LED* led) {
    // 根據(jù)引腳狀態(tài)熄滅LED
    if(led->pin < 8) {
        P0 &= ~(1 << led->pin);  // 熄滅P0上的LED
    } else {
        P1 |= (1 << (led->pin - 8));  // 熄滅P1上的LED
    }
    led->state = 0;  // 更新?tīng)顟B(tài)為熄滅
}


// 主函數(shù)
void main(void) {
    LED myLed;  // 創(chuàng)建一個(gè)LED對(duì)象
    LED_Init(&myLed, 3);  // 初始化LED對(duì)象,連接在P0.3


    // 給LED對(duì)象綁定方法
    myLed.turnOn = LED_TurnOn;
    myLed.turnOff = LED_TurnOff;


    // 使用面向?qū)ο蟮娘L(fēng)格控制LED
    while(1) {
        myLed.turnOn(&myLed);  // 點(diǎn)亮LED
        // 延時(shí)
        myLed.turnOff(&myLed); // 熄滅LED
        // 延時(shí)
    }
}
這段代碼定義了一個(gè)結(jié)構(gòu)體LED,模擬面向?qū)ο笾械摹邦?lèi)。 這個(gè)示例僅用于展示如何在C語(yǔ)言中模擬面向?qū)ο蟮娘L(fēng)格,并沒(méi)有使用真正的面向?qū)ο缶幊陶Z(yǔ)言的特性,如繼承和多態(tài),不過(guò)對(duì)于單片機(jī)的應(yīng)用,足以。 7.基于任務(wù)的架構(gòu) 這種我最喜歡用,結(jié)構(gòu),邏輯清晰,每個(gè)任務(wù)都能靈活調(diào)度。

基于任務(wù)的架構(gòu)是將程序分解為獨(dú)立的任務(wù),每個(gè)任務(wù)執(zhí)行特定的工作。

在單片機(jī)開(kāi)發(fā)中,如果沒(méi)有使用實(shí)時(shí)操作系統(tǒng),我們可以通過(guò)編寫(xiě)一個(gè)簡(jiǎn)單的輪詢(xún)調(diào)度器來(lái)模擬基于任務(wù)的架構(gòu)。

以下是一個(gè)使用C語(yǔ)言編寫(xiě)的基于任務(wù)的架構(gòu)的示例,該程序在51單片機(jī)上實(shí)現(xiàn)。

為了簡(jiǎn)化,我們將使用一個(gè)簡(jiǎn)單的輪詢(xún)調(diào)度器來(lái)在兩個(gè)任務(wù)之間切換:一個(gè)是按鍵掃描任務(wù),另一個(gè)是LED閃爍任務(wù)。

#include 


// 假設(shè)P1.0是LED輸出
sbit LED = P1^0;


// 全局變量,用于記錄系統(tǒng)Tick
unsigned int systemTick = 0;


// 任務(wù)函數(shù)聲明
void taskLEDBlink(void);
void taskKeyScan(void);


// 定時(shí)器0中斷服務(wù)程序,用于產(chǎn)生Tick
void timer0_ISR() interrupt 1 using 1 
{
    // 定時(shí)器溢出后自動(dòng)重新加載初值,無(wú)需手動(dòng)重置
    systemTick++;  // 更新系統(tǒng)Tick計(jì)數(shù)器
}


// 任務(wù)調(diào)度器,主函數(shù)中調(diào)用,負(fù)責(zé)任務(wù)輪詢(xún)
void taskScheduler(void) 
{
    // 檢查系統(tǒng)Tick,決定是否執(zhí)行任務(wù)
    // 例如,如果我們需要每1000個(gè)Tick執(zhí)行一次LED閃爍任務(wù)
    if (systemTick % 1000 == 0) 
    {
       taskLEDBlink();
    }
    // 如果有按鍵任務(wù),可以類(lèi)似地檢查T(mén)ick并執(zhí)行
    if (systemTick % 10 == 0) 
    {
       taskKeyScan();
    }
}


// LED閃爍任務(wù)
void taskLEDBlink(void) 
{
    static bit ledState = 0;  // 用于記錄LED的當(dāng)前狀態(tài)
    ledState = !ledState;  // 切換LED狀態(tài)
    LED = ledState;         // 更新LED硬件狀態(tài)
}


// 按鍵掃描任務(wù)(示例中省略具體實(shí)現(xiàn))
void taskKeyScan(void) 
{
    // 按鍵掃描邏輯
}


// 主函數(shù)
void main(void) 
{
    // 初始化LED狀態(tài)
    LED = 0;


    // 定時(shí)器0初始化設(shè)置
    TMOD &= 0xF0;  // 設(shè)置定時(shí)器模式寄存器,使用模式1(16位定時(shí)器/計(jì)數(shù)器)
    TH0 = 0x4C;     // 設(shè)置定時(shí)器初值,產(chǎn)生定時(shí)中斷(定時(shí)周期取決于系統(tǒng)時(shí)鐘頻率)
    TL0 = 0x00;
    ET0 = 1;        // 允許定時(shí)器0中斷
    EA = 1;         // 允許中斷
    TR0 = 1;        // 啟動(dòng)定時(shí)器0


    while(1) 
    {
        taskScheduler();  // 調(diào)用任務(wù)調(diào)度器
    }
}
這里只是舉個(gè)簡(jiǎn)單的例子,這個(gè)代碼示例,比較適合51和stm8這種資源非常少的單片機(jī)。

8.代理架構(gòu) 這個(gè)大家或許比較少聽(tīng)到過(guò),但在稍微復(fù)雜的項(xiàng)目中,是非常常用的。

在代理架構(gòu)中,每個(gè)代理(Agent)都是一個(gè)獨(dú)立的實(shí)體,它封裝了特定的決策邏輯和數(shù)據(jù),并與其他代理進(jìn)行交互。

在實(shí)際項(xiàng)目中,需要?jiǎng)?chuàng)建多個(gè)獨(dú)立的任務(wù)或模塊,每個(gè)模塊負(fù)責(zé)特定的功能,并通過(guò)某種機(jī)制(如消息隊(duì)列、事件觸發(fā)等)進(jìn)行通信。

這種方式可以大大提高程序可擴(kuò)展性和可移植性。

以下是一個(gè)LED和按鍵代理的簡(jiǎn)化模型。

#include   // 包含51系列單片機(jī)的寄存器定義


// 假設(shè)P3.5是按鍵輸入,P1.0是LED輸出
sbit KEY = P3^5;
sbit LED = P1^0;


typedef struct 
{
    unsigned char pin;    // 代理關(guān)聯(lián)的引腳
    void (*action)(void); // 代理的行為函數(shù)
} Agent;


// 按鍵代理的行為函數(shù)聲明
void keyAction(void);
// LED代理的行為函數(shù)聲明
void ledAction(void);


// 代理數(shù)組,存儲(chǔ)所有代理的行為和關(guān)聯(lián)的引腳
Agent agents[] = 
{
    {5, keyAction},  // 按鍵代理,關(guān)聯(lián)P3.5
    {0, ledAction}   // LED代理,關(guān)聯(lián)P1.0
};


// 按鍵代理的行為函數(shù)
void keyAction(void) 
{
    if(KEY == 0) // 檢測(cè)按鍵是否被按下
        {  
        LED = !LED;   // 如果按鍵被按下,切換LED狀態(tài)
        while(KEY == 0);  // 等待按鍵釋放
    }
}


// LED代理的行為函數(shù)
void ledAction(void) 
{
    static unsigned int toggleCounter = 0;
    toggleCounter++;
    if(toggleCounter == 500)  // 假設(shè)每500個(gè)時(shí)鐘周期切換一次LED
        { 
        LED = !LED;               // 切換LED狀態(tài)
        toggleCounter = 0;        // 重置計(jì)數(shù)器
    }
}


// 主函數(shù)
void main(void) 
{
    unsigned char agentIndex;
    // 主循環(huán)
    while(1) 
    {
        for(agentIndex = 0; agentIndex < sizeof(agents) / sizeof(agents[0]); agentIndex++) 
        {
            // 調(diào)用每個(gè)代理的行為函數(shù)
            (*agents[agentIndex].action)(); // 注意函數(shù)指針的調(diào)用方式
        }
    }
}

9.組件化架構(gòu) 組件化架構(gòu)是一種將軟件系統(tǒng)分解為獨(dú)立、可重用組件的方法。

將程序分割成負(fù)責(zé)特定任務(wù)的模塊,如LED控制、按鍵處理、傳感器讀數(shù)等。

每個(gè)組件可以獨(dú)立開(kāi)發(fā)和測(cè)試,然后被組合在一起形成完整的系統(tǒng)。

以下是一個(gè)簡(jiǎn)化的組件化架構(gòu)示例,模擬了一個(gè)單片機(jī)系統(tǒng)中的LED控制和按鍵輸入處理兩個(gè)組件。

為了簡(jiǎn)化,組件間的通信將通過(guò)直接函數(shù)調(diào)用來(lái)模擬。

#include   // 包含51系列單片機(jī)的寄存器定義


// 定義組件結(jié)構(gòu)體
typedef struct 
{
    void (*init)(void);      // 組件初始化函數(shù)
    void (*task)(void);       // 組件任務(wù)函數(shù)
} Component;


// 假設(shè)P3.5是按鍵輸入,P1.0是LED輸出
sbit KEY = P3^5;
sbit LED = P1^0;


// LED組件
void LED_Init(void) 
{
    LED = 0;  // 初始化LED狀態(tài)為關(guān)閉
}


void LED_Task(void) 
{
    static unsigned int toggleCounter = 0;
    toggleCounter++;
    if (toggleCounter >= 1000) // 假設(shè)每1000個(gè)時(shí)鐘周期切換一次LED
    {  
        LED = !LED;                // 切換LED狀態(tài)
        toggleCounter = 0;         // 重置計(jì)數(shù)器
    }
}


// 按鍵組件
void KEY_Init(void) 
{
    // 按鍵初始化代碼
}


void KEY_Task(void) 
{
    if (KEY == 0) // 檢測(cè)按鍵是否被按下
    {  
       LED = !LED;  // 如果按鍵被按下,切換LED狀態(tài)
       while(KEY == 0);  // 等待按鍵釋放
    }
}


// 組件數(shù)組,存儲(chǔ)系統(tǒng)中所有組件的初始化和任務(wù)函數(shù)
Component components[] = 
{
    {LED_Init, LED_Task},
    {KEY_Init, KEY_Task}
};


// 系統(tǒng)初始化函數(shù),調(diào)用所有組件的初始化函數(shù)
void System_Init(void) 
{
    unsigned char componentIndex;
    for (componentIndex = 0; componentIndex < sizeof(components) / sizeof(components[0]); componentIndex++) 
    {
        components[componentIndex].init();
    }
}


// 主循環(huán),調(diào)用所有組件的任務(wù)函數(shù)
void main(void) 
{
    System_Init();  // 系統(tǒng)初始化
    while(1) 
    {
        unsigned char componentIndex;
        for (componentIndex = 0; componentIndex < sizeof(components) / sizeof(components[0]); componentIndex++)
        {
            components[componentIndex].task();  // 調(diào)用組件任務(wù)
        }
    }
}
審核編輯:黃飛

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

    關(guān)注

    6067

    文章

    44992

    瀏覽量

    650597
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5434

    瀏覽量

    124545
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    41

    文章

    3683

    瀏覽量

    131408
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7632

    瀏覽量

    141800

原文標(biāo)題:長(zhǎng)文干貨預(yù)警 | 單片機(jī)常用的9種軟件架構(gòu)!

文章出處:【微信號(hào):nanshuqg,微信公眾號(hào):無(wú)際單片機(jī)編程】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    單片機(jī)開(kāi)發(fā)中常用的三種軟件架構(gòu)

    嵌入式系統(tǒng)的軟件架構(gòu)是構(gòu)建可靠嵌入式應(yīng)用程序的關(guān)鍵。本文將探討單片機(jī)開(kāi)發(fā)中常用的三種軟件架構(gòu):分
    發(fā)表于 09-13 09:25 ?4408次閱讀

    單片機(jī)9種常用軟件架構(gòu)-C語(yǔ)言

    單片機(jī)9種常用軟件架構(gòu)-C語(yǔ)言
    發(fā)表于 06-10 20:35

    單片機(jī)常用軟件

    單片機(jī)常用軟件
    發(fā)表于 12-25 18:52

    51單片機(jī)常用軟件

    51單片機(jī)常用軟件
    發(fā)表于 12-25 18:54

    單片機(jī)常用軟件下載分享

    單片機(jī)常用軟件在附件內(nèi)
    發(fā)表于 07-08 13:11

    單片機(jī)常用輔助軟件自?。?/a>

    51單片機(jī)常用輔助開(kāi)發(fā)工具軟件免費(fèi)下載!51Hex_Bin、51波特率初值設(shè)定、51定時(shí)器計(jì)算、lcd漢字取模軟件單片機(jī)小精靈
    發(fā)表于 03-24 22:44

    概述常用單片機(jī)軟件架構(gòu)

    一、概述常用單片機(jī)軟件架構(gòu)大體分三種:1. 前后臺(tái)順序執(zhí)行程序2. 時(shí)間片輪詢(xún)法3. 操作系統(tǒng)二、前后臺(tái)順序執(zhí)行程序所謂的前臺(tái),就是主動(dòng)去判斷處理某個(gè)事務(wù),這個(gè)是主循環(huán)里要做的事,也就
    發(fā)表于 11-22 06:57

    單片機(jī)系統(tǒng)常用軟件抗干擾措施

    單片機(jī)系統(tǒng)常用軟件抗干擾措施:可靠性設(shè)計(jì)是一項(xiàng)系統(tǒng)工程,單片機(jī)系統(tǒng)的可靠性必須從軟件、硬件以及結(jié)構(gòu)設(shè)計(jì)等方面全面考慮。硬件系統(tǒng)的可靠性設(shè)計(jì)是單片機(jī)
    發(fā)表于 04-28 11:39 ?18次下載

    常用單片機(jī)介紹

    常用單片機(jī)介紹 單片機(jī)種類(lèi)繁多,但是一般常用的有以下幾種:    ATMEL公司的AVR單片機(jī),是增強(qiáng)型RISC內(nèi)
    發(fā)表于 03-18 15:30 ?2226次閱讀

    單片機(jī)教程:單片機(jī)數(shù)據(jù)傳遞類(lèi)指令

    單片機(jī)教程:單片機(jī)數(shù)據(jù)傳遞類(lèi)指令 單片機(jī)數(shù)據(jù)傳遞類(lèi)指令 (3)以直接地址為目的操作數(shù)的指令 MOV direct,A 例: MOV 20H,A
    發(fā)表于 05-15 23:03 ?957次閱讀
    <b class='flag-5'>單片機(jī)</b>教程<b class='flag-5'>九</b>:<b class='flag-5'>單片機(jī)</b>數(shù)據(jù)傳遞類(lèi)指令

    單片機(jī)常用算法設(shè)計(jì)

    單片機(jī)常用算法歸納
    發(fā)表于 04-05 14:01 ?5次下載

    單片機(jī)學(xué)習(xí)和開(kāi)發(fā)常用軟件合集免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是單片機(jī)學(xué)習(xí)和開(kāi)發(fā)常用軟件合集免費(fèi)下載包括了:串口調(diào)試助手,圖片取模軟件,文字取模軟件,51波特率初值設(shè)定,ST
    發(fā)表于 03-27 08:00 ?6次下載
    <b class='flag-5'>單片機(jī)</b>學(xué)習(xí)和開(kāi)發(fā)<b class='flag-5'>常用</b>的<b class='flag-5'>軟件</b>合集免費(fèi)下載

    單片機(jī)開(kāi)發(fā)會(huì)用到的常用軟件合集

    本文檔的主要內(nèi)容詳細(xì)介紹的是單片機(jī)開(kāi)發(fā)會(huì)用到的常用軟件合集 串口調(diào)試助手、網(wǎng)絡(luò)調(diào)試助手、字庫(kù)制作軟件、文字取模軟件等,都在里面。
    發(fā)表于 01-08 08:00 ?7次下載
    <b class='flag-5'>單片機(jī)</b>開(kāi)發(fā)會(huì)用到的<b class='flag-5'>常用軟件</b>合集

    分享:單片機(jī)常用術(shù)語(yǔ)

    分享:單片機(jī)常用術(shù)語(yǔ)
    發(fā)表于 02-10 11:11 ?6次下載
    分享:<b class='flag-5'>單片機(jī)</b><b class='flag-5'>常用</b>術(shù)語(yǔ)

    arm架構(gòu)單片機(jī)有哪些 arm單片機(jī)選型

    一些常見(jiàn)的ARM架構(gòu)單片機(jī)包括:   1. STM32系列:主要包括Cortex-M0, Cortex-M3, Cortex-M4等內(nèi)核的單片機(jī),是比較常用的高性?xún)r(jià)比的ARM
    發(fā)表于 03-23 15:47 ?7825次閱讀