我在上一篇帖子簡單展示了如何使用狀態機來替代阻塞延時,這一篇我將向大家展示如何使用結構體和函數指針來構建對象。假設有個需求是需要三個LED分別按照5HZ、1HZ和0.5HZ的頻率來閃爍,我們應該怎么實現它呢?如果按照上篇的解決方案需要三個LED_Twinkle函數,只是函數內部關于開關LED的部分不一樣。這樣存在一個問題,假如LED_Twinkle是一個非常復雜函數,那么寫三遍非常費時費力容易出bug并且編譯出的可執行文件體積還大。于是乎面向對象和代碼分層呼之欲出,廢話不多說先上代碼。
這段代碼涉及到結構體和函數指針的語法知識,關于語法這里不再贅述,我來介紹一下這段代碼是如何面向對象和分層的。
結構體:
struct LED_Obj
{
uint8_t Status;
uint16_t DelayTime_LED;
void (*LED_OnOff)(uint8_t Com);
};
該結構體成員包括運行狀態變量(Status)、LED開關延時變量(DelayTime_LED)以及作為上下層接口用來控制LED開關的函數指針(*LED_OnOff)(uint8_t Com)
硬件層部分:
void LED1_OnOff(uint8_t Com);
void LED2_OnOff(uint8_t Com);
void LED3_OnOff(uint8_t Com);
這三個函數就是控制IO來實現LED開關
結構體實例化(對象):
struct LED_Obj LED1 =
{
.LED_OnOff = LED1_OnOff
};
struct LED_Obj LED2 =
{
.LED_OnOff = LED2_OnOff
};
struct LED_Obj LED3 =
{
.LED_OnOff = LED3_OnOff
};
因為我們有3個LED需要控制,所以需要創建3個LED_Obj對象并實現硬件層和應用層的連接(函數指針初始化,指向一個函數)
應用層:
void LED_Twinkle(struct LED_Obj *LED,uint16_t HarfPeriod)
{
switch(LED->Status)
{
case 0:
{
LED->LED_OnOff(ON);
Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
LED->Status++;
}break;
case 1:
{
if(CheckDelay(&LED->DelayTime_LED) == 0)
{
LED->Status++;
}
}break;
case 2:
{
LED->LED_OnOff(OFF);
Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
LED->Status++;
}break;
case 3:
{
if(CheckDelay(&LED->DelayTime_LED) == 0)
{
LED->Status = 0;
}
}break;
}
}
void LED_Run(void)
{
LED_Twinkle(&LED1,100);
LED_Twinkle(&LED2,500);
LED_Twinkle(&LED3,1000);
}
void Task_1mS(void)
{
DelayTimeCount_ms(&LED1.DelayTime_LED);
DelayTimeCount_ms(&LED2.DelayTime_LED);
DelayTimeCount_ms(&LED3.DelayTime_LED);
}
至此,我們就實現了三個LED的分別控制。
|