“LED 闪烁控制软件模块”的版本间的差异
(led闪烁模块说明初版结束) |
|||
(未显示同一用户的2个中间版本) | |||
第1行: | 第1行: | ||
LED闪烁功能,作为常用需求。将其归纳为软件模块,与其他项目或工程共享原代码。 | LED闪烁功能,作为常用需求。将其归纳为软件模块,与其他项目或工程共享原代码。 | ||
+ | |||
+ | === 文件组成 === | ||
+ | 功能模块由六个文件组成,分别承载不同作用。 | ||
+ | {| class="wikitable" | ||
+ | |+ | ||
+ | !文件名称 | ||
+ | !作用 | ||
+ | |- | ||
+ | |bsp_status_led.c | ||
+ | |对应用层函数进行定义 | ||
+ | |- | ||
+ | |bsp_status_led.h | ||
+ | |对应用层函数进行声明 | ||
+ | |- | ||
+ | |ledConfig.c | ||
+ | |对硬件操作接口进行抽象 | ||
+ | |- | ||
+ | |ledConfig.h | ||
+ | |对硬件操作接口进行声明 | ||
+ | |- | ||
+ | |hal_led.c | ||
+ | |对硬件接口进行定义 | ||
+ | |- | ||
+ | |hal_led.h | ||
+ | |对硬件接口进行声明 | ||
+ | |} | ||
+ | 在LED闪烁功能模块中,用到硬件包括一个GPIO引脚,一个定时器。开发者需要根据自身硬件情况,自行选择相应的硬件。并将这些硬件按要求实现相应的函数。这些函数在hal_led.h与hal_led.c文件中进行声明与定义。 | ||
+ | |||
+ | ==== hal_led.h与hal_led.c ====<!-- hal_led.h中与硬件相关函数声明 --> | ||
+ | <syntaxhighlight lang="c" line="1"> | ||
+ | /*定时器超时回调函数指针*/ | ||
+ | typedef void (*fnTimerTimeoutCb_t)(bool); | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // function declare | ||
+ | /*Create a timer*/ | ||
+ | void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb); | ||
+ | |||
+ | /*Start timer*/ | ||
+ | void HalLed_TimerStart(uint32_t ms, void *pContext); | ||
+ | /*Stop timer*/ | ||
+ | void HalLed_TimerStop(void); | ||
+ | /*Pin init*/ | ||
+ | void HalLed_PinInit(void); | ||
+ | /*Pin set */ | ||
+ | void HalLed_PinSet(bool level); | ||
+ | </syntaxhighlight>各函数功能及形参解释说明,如下表所示。 | ||
+ | {| class="wikitable" | ||
+ | |+ | ||
+ | !函数名 | ||
+ | !解释 | ||
+ | |- | ||
+ | |HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb) | ||
+ | |创建一个定时器,且定时器能达到秒级的周期。 | ||
+ | pFnTimeoutCb:是定时器超时回调函数指针 | ||
+ | |- | ||
+ | |HalLed_Timerstart(uint32_t ms, void *pContext) | ||
+ | |启动定时器。 | ||
+ | ms:是定时周期 | ||
+ | |||
+ | pContext:传入的参数指针,会在超时回调函数中使用 | ||
+ | |- | ||
+ | |HalLed_Timerstop(void) | ||
+ | |停止定时器 | ||
+ | |- | ||
+ | |HalLed_PinInit(void) | ||
+ | |初始化与LED相连的GPIO引脚,并保持LED灭状态 | ||
+ | |- | ||
+ | |HalLed_PinSet(void) | ||
+ | |设置GPIO的高低电平,即控制LED亮灭。 | ||
+ | level:true ->LED亮 | ||
+ | |||
+ | false -> LED灭 | ||
+ | |}<!-- hal_led.c就是对上述函数进行定义。而各个函数体是与开发者的硬件相关联 --> | ||
+ | <syntaxhighlight lang="c" line="1"> | ||
+ | //****************************************************************************** | ||
+ | // fn : HalLed_TimerInit | ||
+ | // | ||
+ | // brief: Create a time object for blink led | ||
+ | // | ||
+ | // param : pFnTimeoutCb -> the timeout cb | ||
+ | // | ||
+ | // return : none | ||
+ | void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : HalLed_TimerStart | ||
+ | // | ||
+ | // brief: Start timer | ||
+ | // | ||
+ | // param : ms -> the timeout ,unit = ms | ||
+ | // | ||
+ | // return : none | ||
+ | void HalLed_TimerStart(uint32_t ms,void *pContext) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : HalLed_TimerStop | ||
+ | // | ||
+ | // brief: Stop timer | ||
+ | // | ||
+ | // param : ms -> the timeout ,unit = ms | ||
+ | // | ||
+ | // return : none | ||
+ | void HalLed_TimerStop(void) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : HalLed_PinInit | ||
+ | // | ||
+ | // brief: Pin init | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | void HalLed_PinInit(void) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : HalLed_PinInit | ||
+ | // | ||
+ | // brief: Pin set | ||
+ | // | ||
+ | // param : level -> true -> open,false -> off | ||
+ | // | ||
+ | // return : none | ||
+ | void HalLed_PinSet(bool level) | ||
+ | { | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== ledConfig.h与ledConfig.c ==== | ||
+ | ledConfig.h与ledConfig.c是对LED闪烁模块的硬件进行抽象,即hal_led.h与hal_led.c中定义的功能函数。<!-- ledConfig.h抽象接口声明 --> | ||
+ | |||
+ | <syntaxhighlight lang="c" line="1"> | ||
+ | /*定时器初始化函数指针*/ | ||
+ | typedef void (*fnTimerInit_t)(fnTimerTimeoutCb_t); | ||
+ | /*定时器启动函数指针*/ | ||
+ | typedef void (*fnTimerStart_t)(uint32_t ms,void*pContext); | ||
+ | |||
+ | /*定时器停止函数指针*/ | ||
+ | typedef void (*fnTimerStop_t)(void); | ||
+ | |||
+ | /*Led 引脚初始化函数指针*/ | ||
+ | typedef void (*fnPinInit_t)(void); | ||
+ | /*Led 引脚高低电平设置函数指针*/ | ||
+ | typedef void (*fnPinLevelSet_t)(bool level); | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // Name : ledBlinkCfg_t | ||
+ | // | ||
+ | // Brief : 描述LED闪烁控制接口函数 | ||
+ | typedef struct | ||
+ | { | ||
+ | fnTimerInit_t fnTimerInit; | ||
+ | fnTimerStart_t fnTimerStart; | ||
+ | fnTimerStop_t fnTimerStop; | ||
+ | fnPinInit_t fnPinInit; | ||
+ | fnPinLevelSet_t fnPinLevelSet; | ||
+ | |||
+ | }ledModuleCfg_t; | ||
+ | |||
+ | extern ledModuleCfg_t ledModule; | ||
+ | </syntaxhighlight>hal_led.h就是根据ledConfig.h声明函数接口进行定义的。 | ||
+ | |||
+ | 其中结构体ledModuleCfg_t就是对硬件层进行抽象。其中包括定时器定义,定时器启动,定时器停止,引脚gpio初始化,引脚高低电平设置。<!-- ledConfig.c是ledModuleCfg_t进行初始化 --> | ||
+ | |||
+ | <syntaxhighlight lang="c" line="1"> | ||
+ | /*led operate interface*/ | ||
+ | ledModuleCfg_t ledModule = { | ||
+ | .fnTimerInit = HalLed_TimerInit, | ||
+ | .fnTimerStart = HalLed_TimerStart, | ||
+ | .fnTimerStop = HalLed_TimerStop, | ||
+ | .fnPinInit = HalLed_PinInit, | ||
+ | .fnPinLevelSet = HalLed_PinSet | ||
+ | }; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== bsp_status_led.h 与bsp_status_led.c ==== | ||
+ | 这两个文件是开发者可以调用函数的声明与定义。开发者可以调用相应函数对LED闪烁状态进行设置。led支持如下6种状态。<syntaxhighlight lang="c" line="1"> | ||
+ | |||
+ | typedef enum | ||
+ | { | ||
+ | LED_STATUS_OFF, //关闭 | ||
+ | LED_STATUS_ON, //常亮 | ||
+ | LED_STATUS_BLINK1, //闪烁1,周期200ms,占空比50:亮100,灭100 | ||
+ | LED_STATUS_BLINK2, //闪烁2,周期1000,占空比10:亮100,灭900 | ||
+ | LED_STATUS_BLINK3, //闪烁3,周期1000,占空比50:亮500,灭500 | ||
+ | LED_STATUS_BLINK4, //闪烁4,周期2000,占空比5: 亮100,灭1900 | ||
+ | LED_STATUS_END | ||
+ | }eLEDStatus; | ||
+ | </syntaxhighlight>当然开发者也可以,根据自己的需求,对led闪烁状态进行修改。包括周期,占空比。具体修改的地方在bsp_status_led.c文件头部。各个闪烁状态由宏定义定义,如下。<syntaxhighlight lang="c" line="1"> | ||
+ | #define LED_BLINK1_PERIOD 200 | ||
+ | #define LED_BLINK1_DUTY 50 | ||
+ | #define LED_BLINK1_ON_MS 100 | ||
+ | #define LED_BLINK1_OFF_MS (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS) | ||
+ | |||
+ | #define LED_BLINK2_PERIOD 1000 | ||
+ | #define LED_BLINK2_DUTY 10 | ||
+ | #define LED_BLINK2_ON_MS 100 | ||
+ | #define LED_BLINK2_OFF_MS (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS) | ||
+ | |||
+ | #define LED_BLINK3_PERIOD 1000 | ||
+ | #define LED_BLINK3_DUTY 50 | ||
+ | #define LED_BLINK3_ON_MS 500 | ||
+ | #define LED_BLINK3_OFF_MS (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS) | ||
+ | |||
+ | #define LED_BLINK4_PERIOD 2000 | ||
+ | #define LED_BLINK4_DUTY 5 | ||
+ | #define LED_BLINK4_ON_MS 100 | ||
+ | #define LED_BLINK4_OFF_MS (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===== 闪烁次数定义 ===== | ||
+ | 在代码中,各个闪烁状态都有相应的次数限制。其中0表示此状态闪烁结束,将进行下一个状态,0xFF表示永久闪烁,直到当前状态被人为改变,即闪烁次数被置零,或改为其他数值;或被弹出。<syntaxhighlight lang="c" line="1"> | ||
+ | #define LED_BLINK_STOP 0 | ||
+ | #define LED_BLINK_FOREVER 0xFF | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===== 应用函数声明 ===== | ||
+ | 在用户层提供了两种方式。一种是普通模式,一种是栈模式。 | ||
+ | |||
+ | 普通模式中,开发者只需调用LED_Set函数,即可对当前led状态进行设置。状态结束后,led处在灭状态,等待用户进行下个状态设置。而在栈模式中,开发者调用LED_StackPush函数时,会将led状态压入栈中,并设置led状态。当led闪烁状态结束后,继续之前led状态,直到栈空为至。当然在这个过程中开发者也可以调用LED_Set函数,对当前led闪烁状态进行设置。只是led闪烁状态结束后会继续栈的上个led状态,而不会继续LED_Set函数调用前的状态。<syntaxhighlight lang="c" line="1"> | ||
+ | /*initial led module*/ | ||
+ | void LED_Init(void); | ||
+ | /*set the led status*/ | ||
+ | void LED_Set(eLEDStatus,uint8_t times); | ||
+ | |||
+ | #ifdef LED_PRORITY_EN | ||
+ | /*push the led status to ledstack.it will be placed at the top*/ | ||
+ | bool LED_StackPush(eLEDStatus,uint8_t times); | ||
+ | |||
+ | /*pop the top node from ledstack*/ | ||
+ | void LED_StackPop(void); | ||
+ | |||
+ | /*clear stack*/ | ||
+ | void LED_StackClear(void); | ||
+ | #endif | ||
+ | |||
+ | </syntaxhighlight>其中与栈有关的函数是通过宏LED_PRORITY_EN来控制。 | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |+ | ||
+ | !函数名 | ||
+ | !解释 | ||
+ | ! | ||
+ | |- | ||
+ | |void LED_Init(void) | ||
+ | |对LED闪烁模块进行初始化。在任何函数调用之前进行调用 | ||
+ | | | ||
+ | |- | ||
+ | |void LED_Set( eLEDStatus status,uint8_t times) | ||
+ | |设置led闪烁状态 | ||
+ | status:设置的led状态 | ||
+ | |||
+ | times:闪烁次数 | ||
+ | | | ||
+ | |- | ||
+ | |bool LED_StackPush(eLEDStatus status, uint8_t times) | ||
+ | |设置led闪烁状态,并压入栈中 | ||
+ | status:设置的led状态 | ||
+ | |||
+ | times:闪烁次数 | ||
+ | | | ||
+ | |- | ||
+ | |void LED_StackPop(void) | ||
+ | |弹出栈顶状态 | ||
+ | | | ||
+ | |- | ||
+ | |void LED_StackClear(void) | ||
+ | |清空栈里所有led状态,并将led设置灭状态 | ||
+ | | | ||
+ | |}<!-- bsp_status_led.c函数定义 --> | ||
+ | <syntaxhighlight lang="c" line="1"> | ||
+ | /*blink status*/ | ||
+ | /* | ||
+ | { | ||
+ | 1.period -> 闪烁周期 | ||
+ | 2.duty -> 引脚高电平占整个周期的百分比 | ||
+ | 3.times -> 闪烁次数 | ||
+ | } | ||
+ | */ | ||
+ | #define LED_BLINK1_PERIOD 200 | ||
+ | #define LED_BLINK1_DUTY 50 | ||
+ | #define LED_BLINK1_ON_MS 100 | ||
+ | #define LED_BLINK1_OFF_MS (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS) | ||
+ | |||
+ | #define LED_BLINK2_PERIOD 1000 | ||
+ | #define LED_BLINK2_DUTY 10 | ||
+ | #define LED_BLINK2_ON_MS 100 | ||
+ | #define LED_BLINK2_OFF_MS (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS) | ||
+ | |||
+ | #define LED_BLINK3_PERIOD 1000 | ||
+ | #define LED_BLINK3_DUTY 50 | ||
+ | #define LED_BLINK3_ON_MS 500 | ||
+ | #define LED_BLINK3_OFF_MS (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS) | ||
+ | |||
+ | #define LED_BLINK4_PERIOD 2000 | ||
+ | #define LED_BLINK4_DUTY 5 | ||
+ | #define LED_BLINK4_ON_MS 100 | ||
+ | #define LED_BLINK4_OFF_MS (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS) | ||
+ | |||
+ | |||
+ | #define LED_BLINK_STOP 0 | ||
+ | #define LED_BLINK_FOREVER 0xFF | ||
+ | |||
+ | #define LED_ON true | ||
+ | #define LED_OFF false | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // typedef area | ||
+ | // | ||
+ | /*定义当前led工作状态信息*/ | ||
+ | typedef struct | ||
+ | { | ||
+ | bool ledLevelFlag; //true -> high,false -> low | ||
+ | uint8_t ledPointer; | ||
+ | }ledBlinkInfo_t; | ||
+ | |||
+ | #ifdef LED_PRORITY_EN | ||
+ | //定义LED状态的栈空间 | ||
+ | typedef struct | ||
+ | { | ||
+ | uint8_t stack[LED_STATUS_END]; //栈的最大空间 | ||
+ | uint8_t num; //栈当前含有元素个数 | ||
+ | |||
+ | }ledStack_t; | ||
+ | #endif | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // variable define | ||
+ | // | ||
+ | |||
+ | static uint8_t ledBlinkTimesTable[LED_STATUS_END] = {0x00}; | ||
+ | |||
+ | static ledBlinkInfo_t ledInfo = {LED_OFF,0x00}; | ||
+ | #ifdef LED_PRORITY_EN | ||
+ | static ledStack_t ledStack = {{0x00},0x00}; | ||
+ | |||
+ | #endif | ||
+ | //****************************************************************************** | ||
+ | // function define | ||
+ | // | ||
+ | /*定时次的超时回调函数*/ | ||
+ | static void ledTimeoutCb(bool level); | ||
+ | |||
+ | /*获取led定时时间*/ | ||
+ | static uint16_t ledGetBlinkTime(bool level); | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : LED_Init | ||
+ | // | ||
+ | // brief : initial led module | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | void LED_Init(void) | ||
+ | { | ||
+ | ledModule.fnTimerInit(ledTimeoutCb); | ||
+ | ledModule.fnPinInit(); | ||
+ | ledInfo.ledLevelFlag = LED_OFF; | ||
+ | ledInfo.ledPointer = NULL; | ||
+ | memset(ledBlinkTimesTable,0,LED_STATUS_END); | ||
+ | |||
+ | #ifdef LED_PRORITY_EN | ||
+ | memset(&ledStack,0,sizeof(ledStack_t)); | ||
+ | LED_StackPush(LED_STATUS_ON,0xFF); | ||
+ | LED_StackPush(LED_STATUS_BLINK3,0xFF); | ||
+ | #else | ||
+ | LED_Set(LED_STATUS_BLINK3,0xFF); | ||
+ | #endif | ||
+ | } | ||
+ | //****************************************************************************** | ||
+ | // fn : LED_Init | ||
+ | // | ||
+ | // brief : set the led status | ||
+ | // | ||
+ | // param : ledStatus -> 设置led状态 | ||
+ | // times -> Led闪烁次数,0xFF 表示一直执行,直到下一次状态改变 | ||
+ | // | ||
+ | // return : none | ||
+ | void LED_Set(eLEDStatus ledStatus, uint8_t times) | ||
+ | { | ||
+ | if(LED_STATUS_END <= ledStatus) | ||
+ | { | ||
+ | return ; | ||
+ | } | ||
+ | // if(times == LED_BLINK_STOP) | ||
+ | // { | ||
+ | // return; | ||
+ | // } | ||
+ | |||
+ | ledInfo.ledPointer = ledStatus; | ||
+ | ledInfo.ledLevelFlag = LED_OFF; | ||
+ | ledBlinkTimesTable[ledStatus] = times; | ||
+ | ledModule.fnTimerStop(); | ||
+ | |||
+ | if(LED_BLINK_STOP == times) | ||
+ | { | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | switch(ledStatus) | ||
+ | { | ||
+ | case LED_STATUS_OFF: | ||
+ | { | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | case LED_STATUS_ON: | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | case LED_STATUS_BLINK1: | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnTimerStart(LED_BLINK1_ON_MS,&ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | case LED_STATUS_BLINK2: | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnTimerStart(LED_BLINK2_ON_MS,&ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | case LED_STATUS_BLINK3: | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnTimerStart(LED_BLINK3_ON_MS,&ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | case LED_STATUS_BLINK4: | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnTimerStart(LED_BLINK4_ON_MS,&ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | break; | ||
+ | default : | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | #ifdef LED_PRORITY_EN | ||
+ | //****************************************************************************** | ||
+ | // fn : LED_StackPush | ||
+ | // | ||
+ | // brief : push the led status to ledstack.it will be placed at the top | ||
+ | // | ||
+ | // param : ledStatus -> 设置led状态 | ||
+ | // times -> Led闪烁次数,0x00 表示一直执行,直到下一次状态改变 | ||
+ | // | ||
+ | // return : none | ||
+ | bool LED_StackPush(eLEDStatus ledStatus,uint8_t times) | ||
+ | { | ||
+ | if(LED_STATUS_END <= ledStatus) | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | if(times == LED_BLINK_STOP) | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | if(ledStack.num > LED_STATUS_END) | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | ledStack.stack[ledStack.num] = ledStatus; | ||
+ | ledStack.num++; | ||
+ | LED_Set(ledStatus,times); | ||
+ | |||
+ | return true; | ||
+ | } | ||
+ | //****************************************************************************** | ||
+ | // fn : LED_StackPop | ||
+ | // | ||
+ | // brief : pop the top node from ledstack | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | void LED_StackPop(void) | ||
+ | { | ||
+ | if(ledStack.num == 0) | ||
+ | { | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | ledStack.num -= 1; | ||
+ | //停止当前LED状态 | ||
+ | ledInfo.ledLevelFlag = LED_OFF; | ||
+ | ledModule.fnTimerStop(); | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | |||
+ | if(ledStack.num) | ||
+ | { | ||
+ | eLEDStatus led_id = (eLEDStatus)ledStack.stack[ledStack.num - 1]; | ||
+ | uint8_t times = ledBlinkTimesTable[led_id]; | ||
+ | if(times == LED_BLINK_STOP) | ||
+ | { | ||
+ | LED_StackPop(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | LED_Set(led_id,times); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //****************************************************************************** | ||
+ | // fn : LED_StackClear | ||
+ | // | ||
+ | // brief : clear the stack of led | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | void LED_StackClear(void) | ||
+ | { | ||
+ | ledStack.num = 0; | ||
+ | //停止当前LED状态 | ||
+ | ledInfo.ledLevelFlag = LED_OFF; | ||
+ | ledModule.fnTimerStop(); | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | |||
+ | #endif | ||
+ | //****************************************************************************** | ||
+ | // static functions define area | ||
+ | // | ||
+ | //****************************************************************************** | ||
+ | // fn : ledTimeoutCb | ||
+ | // | ||
+ | // brief : the timeout callback to the led | ||
+ | // | ||
+ | // param : level -> true:pin high;false:pin low | ||
+ | // | ||
+ | // return : none | ||
+ | static void ledTimeoutCb(bool level) | ||
+ | { | ||
+ | uint16_t ms = 0; | ||
+ | if(level == LED_ON) | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_OFF; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | ledInfo.ledLevelFlag = LED_ON; | ||
+ | if(LED_BLINK_FOREVER != ledBlinkTimesTable[ledInfo.ledPointer]) | ||
+ | { | ||
+ | ledBlinkTimesTable[ledInfo.ledPointer] -= 1; | ||
+ | if(ledBlinkTimesTable[ledInfo.ledPointer] == LED_BLINK_STOP) | ||
+ | { | ||
+ | #ifdef LED_PRORITY_EN | ||
+ | LED_StackPop(); //弹出当前led状态 | ||
+ | return; | ||
+ | #else | ||
+ | return; | ||
+ | #endif | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | ms = ledGetBlinkTime(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnPinLevelSet(ledInfo.ledLevelFlag); | ||
+ | ledModule.fnTimerStart(ms,&ledInfo.ledLevelFlag); | ||
+ | } | ||
+ | //****************************************************************************** | ||
+ | // fn : ledGetBlinkTime | ||
+ | // | ||
+ | // brief : Get the time with led status | ||
+ | // | ||
+ | // param : level -> true:pin high;false:pin low | ||
+ | // | ||
+ | // return : time | ||
+ | static uint16_t ledGetBlinkTime(bool level) | ||
+ | { | ||
+ | uint16_t ms = 0; | ||
+ | switch(ledInfo.ledPointer) | ||
+ | { | ||
+ | case LED_STATUS_BLINK1: | ||
+ | ms = level ? LED_BLINK1_ON_MS : LED_BLINK1_OFF_MS; | ||
+ | break; | ||
+ | case LED_STATUS_BLINK2: | ||
+ | ms = level ? LED_BLINK2_ON_MS : LED_BLINK2_OFF_MS; | ||
+ | break; | ||
+ | case LED_STATUS_BLINK3: | ||
+ | ms = level ? LED_BLINK3_ON_MS : LED_BLINK3_OFF_MS; | ||
+ | break; | ||
+ | case LED_STATUS_BLINK4: | ||
+ | ms = level ? LED_BLINK4_ON_MS : LED_BLINK4_OFF_MS; | ||
+ | break; | ||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | return ms; | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> |
2019年12月9日 (一) 16:25的最新版本
LED闪烁功能,作为常用需求。将其归纳为软件模块,与其他项目或工程共享原代码。
目录
1 文件组成
功能模块由六个文件组成,分别承载不同作用。
文件名称 | 作用 |
---|---|
bsp_status_led.c | 对应用层函数进行定义 |
bsp_status_led.h | 对应用层函数进行声明 |
ledConfig.c | 对硬件操作接口进行抽象 |
ledConfig.h | 对硬件操作接口进行声明 |
hal_led.c | 对硬件接口进行定义 |
hal_led.h | 对硬件接口进行声明 |
在LED闪烁功能模块中,用到硬件包括一个GPIO引脚,一个定时器。开发者需要根据自身硬件情况,自行选择相应的硬件。并将这些硬件按要求实现相应的函数。这些函数在hal_led.h与hal_led.c文件中进行声明与定义。
1.1 hal_led.h与hal_led.c
1 /*定时器超时回调函数指针*/
2 typedef void (*fnTimerTimeoutCb_t)(bool);
3
4 //******************************************************************************
5 // function declare
6 /*Create a timer*/
7 void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb);
8
9 /*Start timer*/
10 void HalLed_TimerStart(uint32_t ms, void *pContext);
11 /*Stop timer*/
12 void HalLed_TimerStop(void);
13 /*Pin init*/
14 void HalLed_PinInit(void);
15 /*Pin set */
16 void HalLed_PinSet(bool level);
各函数功能及形参解释说明,如下表所示。
函数名 | 解释 |
---|---|
HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb) | 创建一个定时器,且定时器能达到秒级的周期。
pFnTimeoutCb:是定时器超时回调函数指针 |
HalLed_Timerstart(uint32_t ms, void *pContext) | 启动定时器。
ms:是定时周期 pContext:传入的参数指针,会在超时回调函数中使用 |
HalLed_Timerstop(void) | 停止定时器 |
HalLed_PinInit(void) | 初始化与LED相连的GPIO引脚,并保持LED灭状态 |
HalLed_PinSet(void) | 设置GPIO的高低电平,即控制LED亮灭。
level:true ->LED亮 false -> LED灭 |
1 //******************************************************************************
2 // fn : HalLed_TimerInit
3 //
4 // brief: Create a time object for blink led
5 //
6 // param : pFnTimeoutCb -> the timeout cb
7 //
8 // return : none
9 void HalLed_TimerInit(fnTimerTimeoutCb_t pFnTimeoutCb)
10 {
11
12 }
13
14 //******************************************************************************
15 // fn : HalLed_TimerStart
16 //
17 // brief: Start timer
18 //
19 // param : ms -> the timeout ,unit = ms
20 //
21 // return : none
22 void HalLed_TimerStart(uint32_t ms,void *pContext)
23 {
24
25 }
26
27 //******************************************************************************
28 // fn : HalLed_TimerStop
29 //
30 // brief: Stop timer
31 //
32 // param : ms -> the timeout ,unit = ms
33 //
34 // return : none
35 void HalLed_TimerStop(void)
36 {
37
38 }
39
40 //******************************************************************************
41 // fn : HalLed_PinInit
42 //
43 // brief: Pin init
44 //
45 // param : none
46 //
47 // return : none
48 void HalLed_PinInit(void)
49 {
50
51 }
52
53 //******************************************************************************
54 // fn : HalLed_PinInit
55 //
56 // brief: Pin set
57 //
58 // param : level -> true -> open,false -> off
59 //
60 // return : none
61 void HalLed_PinSet(bool level)
62 {
63
64 }
1.2 ledConfig.h与ledConfig.c
ledConfig.h与ledConfig.c是对LED闪烁模块的硬件进行抽象,即hal_led.h与hal_led.c中定义的功能函数。
1 /*定时器初始化函数指针*/
2 typedef void (*fnTimerInit_t)(fnTimerTimeoutCb_t);
3 /*定时器启动函数指针*/
4 typedef void (*fnTimerStart_t)(uint32_t ms,void*pContext);
5
6 /*定时器停止函数指针*/
7 typedef void (*fnTimerStop_t)(void);
8
9 /*Led 引脚初始化函数指针*/
10 typedef void (*fnPinInit_t)(void);
11 /*Led 引脚高低电平设置函数指针*/
12 typedef void (*fnPinLevelSet_t)(bool level);
13
14 //******************************************************************************
15 // Name : ledBlinkCfg_t
16 //
17 // Brief : 描述LED闪烁控制接口函数
18 typedef struct
19 {
20 fnTimerInit_t fnTimerInit;
21 fnTimerStart_t fnTimerStart;
22 fnTimerStop_t fnTimerStop;
23 fnPinInit_t fnPinInit;
24 fnPinLevelSet_t fnPinLevelSet;
25
26 }ledModuleCfg_t;
27
28 extern ledModuleCfg_t ledModule;
hal_led.h就是根据ledConfig.h声明函数接口进行定义的。
其中结构体ledModuleCfg_t就是对硬件层进行抽象。其中包括定时器定义,定时器启动,定时器停止,引脚gpio初始化,引脚高低电平设置。
1 /*led operate interface*/
2 ledModuleCfg_t ledModule = {
3 .fnTimerInit = HalLed_TimerInit,
4 .fnTimerStart = HalLed_TimerStart,
5 .fnTimerStop = HalLed_TimerStop,
6 .fnPinInit = HalLed_PinInit,
7 .fnPinLevelSet = HalLed_PinSet
8 };
1.3 bsp_status_led.h 与bsp_status_led.c
这两个文件是开发者可以调用函数的声明与定义。开发者可以调用相应函数对LED闪烁状态进行设置。led支持如下6种状态。
1 typedef enum
2 {
3 LED_STATUS_OFF, //关闭
4 LED_STATUS_ON, //常亮
5 LED_STATUS_BLINK1, //闪烁1,周期200ms,占空比50:亮100,灭100
6 LED_STATUS_BLINK2, //闪烁2,周期1000,占空比10:亮100,灭900
7 LED_STATUS_BLINK3, //闪烁3,周期1000,占空比50:亮500,灭500
8 LED_STATUS_BLINK4, //闪烁4,周期2000,占空比5: 亮100,灭1900
9 LED_STATUS_END
10 }eLEDStatus;
当然开发者也可以,根据自己的需求,对led闪烁状态进行修改。包括周期,占空比。具体修改的地方在bsp_status_led.c文件头部。各个闪烁状态由宏定义定义,如下。
1 #define LED_BLINK1_PERIOD 200
2 #define LED_BLINK1_DUTY 50
3 #define LED_BLINK1_ON_MS 100
4 #define LED_BLINK1_OFF_MS (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS)
5
6 #define LED_BLINK2_PERIOD 1000
7 #define LED_BLINK2_DUTY 10
8 #define LED_BLINK2_ON_MS 100
9 #define LED_BLINK2_OFF_MS (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS)
10
11 #define LED_BLINK3_PERIOD 1000
12 #define LED_BLINK3_DUTY 50
13 #define LED_BLINK3_ON_MS 500
14 #define LED_BLINK3_OFF_MS (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS)
15
16 #define LED_BLINK4_PERIOD 2000
17 #define LED_BLINK4_DUTY 5
18 #define LED_BLINK4_ON_MS 100
19 #define LED_BLINK4_OFF_MS (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS)
1.3.1 闪烁次数定义
在代码中,各个闪烁状态都有相应的次数限制。其中0表示此状态闪烁结束,将进行下一个状态,0xFF表示永久闪烁,直到当前状态被人为改变,即闪烁次数被置零,或改为其他数值;或被弹出。
1 #define LED_BLINK_STOP 0
2 #define LED_BLINK_FOREVER 0xFF
1.3.2 应用函数声明
在用户层提供了两种方式。一种是普通模式,一种是栈模式。
普通模式中,开发者只需调用LED_Set函数,即可对当前led状态进行设置。状态结束后,led处在灭状态,等待用户进行下个状态设置。而在栈模式中,开发者调用LED_StackPush函数时,会将led状态压入栈中,并设置led状态。当led闪烁状态结束后,继续之前led状态,直到栈空为至。当然在这个过程中开发者也可以调用LED_Set函数,对当前led闪烁状态进行设置。只是led闪烁状态结束后会继续栈的上个led状态,而不会继续LED_Set函数调用前的状态。
1 /*initial led module*/
2 void LED_Init(void);
3 /*set the led status*/
4 void LED_Set(eLEDStatus,uint8_t times);
5
6 #ifdef LED_PRORITY_EN
7 /*push the led status to ledstack.it will be placed at the top*/
8 bool LED_StackPush(eLEDStatus,uint8_t times);
9
10 /*pop the top node from ledstack*/
11 void LED_StackPop(void);
12
13 /*clear stack*/
14 void LED_StackClear(void);
15 #endif
其中与栈有关的函数是通过宏LED_PRORITY_EN来控制。
函数名 | 解释 | |
---|---|---|
void LED_Init(void) | 对LED闪烁模块进行初始化。在任何函数调用之前进行调用 | |
void LED_Set( eLEDStatus status,uint8_t times) | 设置led闪烁状态
status:设置的led状态 times:闪烁次数 |
|
bool LED_StackPush(eLEDStatus status, uint8_t times) | 设置led闪烁状态,并压入栈中
status:设置的led状态 times:闪烁次数 |
|
void LED_StackPop(void) | 弹出栈顶状态 | |
void LED_StackClear(void) | 清空栈里所有led状态,并将led设置灭状态 |
1 /*blink status*/
2 /*
3 {
4 1.period -> 闪烁周期
5 2.duty -> 引脚高电平占整个周期的百分比
6 3.times -> 闪烁次数
7 }
8 */
9 #define LED_BLINK1_PERIOD 200
10 #define LED_BLINK1_DUTY 50
11 #define LED_BLINK1_ON_MS 100
12 #define LED_BLINK1_OFF_MS (LED_BLINK1_PERIOD - LED_BLINK1_ON_MS)
13
14 #define LED_BLINK2_PERIOD 1000
15 #define LED_BLINK2_DUTY 10
16 #define LED_BLINK2_ON_MS 100
17 #define LED_BLINK2_OFF_MS (LED_BLINK2_PERIOD - LED_BLINK2_ON_MS)
18
19 #define LED_BLINK3_PERIOD 1000
20 #define LED_BLINK3_DUTY 50
21 #define LED_BLINK3_ON_MS 500
22 #define LED_BLINK3_OFF_MS (LED_BLINK3_PERIOD - LED_BLINK3_ON_MS)
23
24 #define LED_BLINK4_PERIOD 2000
25 #define LED_BLINK4_DUTY 5
26 #define LED_BLINK4_ON_MS 100
27 #define LED_BLINK4_OFF_MS (LED_BLINK4_PERIOD - LED_BLINK4_ON_MS)
28
29
30 #define LED_BLINK_STOP 0
31 #define LED_BLINK_FOREVER 0xFF
32
33 #define LED_ON true
34 #define LED_OFF false
35
36 //******************************************************************************
37 // typedef area
38 //
39 /*定义当前led工作状态信息*/
40 typedef struct
41 {
42 bool ledLevelFlag; //true -> high,false -> low
43 uint8_t ledPointer;
44 }ledBlinkInfo_t;
45
46 #ifdef LED_PRORITY_EN
47 //定义LED状态的栈空间
48 typedef struct
49 {
50 uint8_t stack[LED_STATUS_END]; //栈的最大空间
51 uint8_t num; //栈当前含有元素个数
52
53 }ledStack_t;
54 #endif
55
56 //******************************************************************************
57 // variable define
58 //
59
60 static uint8_t ledBlinkTimesTable[LED_STATUS_END] = {0x00};
61
62 static ledBlinkInfo_t ledInfo = {LED_OFF,0x00};
63 #ifdef LED_PRORITY_EN
64 static ledStack_t ledStack = {{0x00},0x00};
65
66 #endif
67 //******************************************************************************
68 // function define
69 //
70 /*定时次的超时回调函数*/
71 static void ledTimeoutCb(bool level);
72
73 /*获取led定时时间*/
74 static uint16_t ledGetBlinkTime(bool level);
75
76 //******************************************************************************
77 // fn : LED_Init
78 //
79 // brief : initial led module
80 //
81 // param : none
82 //
83 // return : none
84 void LED_Init(void)
85 {
86 ledModule.fnTimerInit(ledTimeoutCb);
87 ledModule.fnPinInit();
88 ledInfo.ledLevelFlag = LED_OFF;
89 ledInfo.ledPointer = NULL;
90 memset(ledBlinkTimesTable,0,LED_STATUS_END);
91
92 #ifdef LED_PRORITY_EN
93 memset(&ledStack,0,sizeof(ledStack_t));
94 LED_StackPush(LED_STATUS_ON,0xFF);
95 LED_StackPush(LED_STATUS_BLINK3,0xFF);
96 #else
97 LED_Set(LED_STATUS_BLINK3,0xFF);
98 #endif
99 }
100 //******************************************************************************
101 // fn : LED_Init
102 //
103 // brief : set the led status
104 //
105 // param : ledStatus -> 设置led状态
106 // times -> Led闪烁次数,0xFF 表示一直执行,直到下一次状态改变
107 //
108 // return : none
109 void LED_Set(eLEDStatus ledStatus, uint8_t times)
110 {
111 if(LED_STATUS_END <= ledStatus)
112 {
113 return ;
114 }
115 // if(times == LED_BLINK_STOP)
116 // {
117 // return;
118 // }
119
120 ledInfo.ledPointer = ledStatus;
121 ledInfo.ledLevelFlag = LED_OFF;
122 ledBlinkTimesTable[ledStatus] = times;
123 ledModule.fnTimerStop();
124
125 if(LED_BLINK_STOP == times)
126 {
127 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
128 return;
129 }
130
131 switch(ledStatus)
132 {
133 case LED_STATUS_OFF:
134 {
135 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
136 }
137 break;
138 case LED_STATUS_ON:
139 {
140 ledInfo.ledLevelFlag = LED_ON;
141 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
142 }
143 break;
144 case LED_STATUS_BLINK1:
145 {
146 ledInfo.ledLevelFlag = LED_ON;
147 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
148 ledModule.fnTimerStart(LED_BLINK1_ON_MS,&ledInfo.ledLevelFlag);
149 }
150 break;
151 case LED_STATUS_BLINK2:
152 {
153 ledInfo.ledLevelFlag = LED_ON;
154 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
155 ledModule.fnTimerStart(LED_BLINK2_ON_MS,&ledInfo.ledLevelFlag);
156 }
157 break;
158 case LED_STATUS_BLINK3:
159 {
160 ledInfo.ledLevelFlag = LED_ON;
161 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
162 ledModule.fnTimerStart(LED_BLINK3_ON_MS,&ledInfo.ledLevelFlag);
163 }
164 break;
165 case LED_STATUS_BLINK4:
166 {
167 ledInfo.ledLevelFlag = LED_ON;
168 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
169 ledModule.fnTimerStart(LED_BLINK4_ON_MS,&ledInfo.ledLevelFlag);
170 }
171 break;
172 default :
173 return;
174 }
175
176 }
177 #ifdef LED_PRORITY_EN
178 //******************************************************************************
179 // fn : LED_StackPush
180 //
181 // brief : push the led status to ledstack.it will be placed at the top
182 //
183 // param : ledStatus -> 设置led状态
184 // times -> Led闪烁次数,0x00 表示一直执行,直到下一次状态改变
185 //
186 // return : none
187 bool LED_StackPush(eLEDStatus ledStatus,uint8_t times)
188 {
189 if(LED_STATUS_END <= ledStatus)
190 {
191 return false;
192 }
193
194 if(times == LED_BLINK_STOP)
195 {
196 return false;
197 }
198
199 if(ledStack.num > LED_STATUS_END)
200 {
201 return false;
202 }
203
204 ledStack.stack[ledStack.num] = ledStatus;
205 ledStack.num++;
206 LED_Set(ledStatus,times);
207
208 return true;
209 }
210 //******************************************************************************
211 // fn : LED_StackPop
212 //
213 // brief : pop the top node from ledstack
214 //
215 // param : none
216 //
217 // return : none
218 void LED_StackPop(void)
219 {
220 if(ledStack.num == 0)
221 {
222 return;
223 }
224
225 ledStack.num -= 1;
226 //停止当前LED状态
227 ledInfo.ledLevelFlag = LED_OFF;
228 ledModule.fnTimerStop();
229 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
230
231 if(ledStack.num)
232 {
233 eLEDStatus led_id = (eLEDStatus)ledStack.stack[ledStack.num - 1];
234 uint8_t times = ledBlinkTimesTable[led_id];
235 if(times == LED_BLINK_STOP)
236 {
237 LED_StackPop();
238 }
239 else
240 {
241 LED_Set(led_id,times);
242 }
243 }
244 }
245
246 //******************************************************************************
247 // fn : LED_StackClear
248 //
249 // brief : clear the stack of led
250 //
251 // param : none
252 //
253 // return : none
254 void LED_StackClear(void)
255 {
256 ledStack.num = 0;
257 //停止当前LED状态
258 ledInfo.ledLevelFlag = LED_OFF;
259 ledModule.fnTimerStop();
260 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
261 }
262
263 #endif
264 //******************************************************************************
265 // static functions define area
266 //
267 //******************************************************************************
268 // fn : ledTimeoutCb
269 //
270 // brief : the timeout callback to the led
271 //
272 // param : level -> true:pin high;false:pin low
273 //
274 // return : none
275 static void ledTimeoutCb(bool level)
276 {
277 uint16_t ms = 0;
278 if(level == LED_ON)
279 {
280 ledInfo.ledLevelFlag = LED_OFF;
281 }
282 else
283 {
284 ledInfo.ledLevelFlag = LED_ON;
285 if(LED_BLINK_FOREVER != ledBlinkTimesTable[ledInfo.ledPointer])
286 {
287 ledBlinkTimesTable[ledInfo.ledPointer] -= 1;
288 if(ledBlinkTimesTable[ledInfo.ledPointer] == LED_BLINK_STOP)
289 {
290 #ifdef LED_PRORITY_EN
291 LED_StackPop(); //弹出当前led状态
292 return;
293 #else
294 return;
295 #endif
296 }
297 }
298 }
299 ms = ledGetBlinkTime(ledInfo.ledLevelFlag);
300 ledModule.fnPinLevelSet(ledInfo.ledLevelFlag);
301 ledModule.fnTimerStart(ms,&ledInfo.ledLevelFlag);
302 }
303 //******************************************************************************
304 // fn : ledGetBlinkTime
305 //
306 // brief : Get the time with led status
307 //
308 // param : level -> true:pin high;false:pin low
309 //
310 // return : time
311 static uint16_t ledGetBlinkTime(bool level)
312 {
313 uint16_t ms = 0;
314 switch(ledInfo.ledPointer)
315 {
316 case LED_STATUS_BLINK1:
317 ms = level ? LED_BLINK1_ON_MS : LED_BLINK1_OFF_MS;
318 break;
319 case LED_STATUS_BLINK2:
320 ms = level ? LED_BLINK2_ON_MS : LED_BLINK2_OFF_MS;
321 break;
322 case LED_STATUS_BLINK3:
323 ms = level ? LED_BLINK3_ON_MS : LED_BLINK3_OFF_MS;
324 break;
325 case LED_STATUS_BLINK4:
326 ms = level ? LED_BLINK4_ON_MS : LED_BLINK4_OFF_MS;
327 break;
328 default:
329 break;
330 }
331 return ms;
332
333 }