我在上一篇帖子简单展示了如何使用状态机来替代阻塞延时,这一篇我将向大家展示如何使用结构体和函数指针来构建对象。假设有个需求是需要三个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的分别控制。
|