控制灯的基本函数:
#include "stdbool.h"
void aplRunLedOn(bool on)
{
HAL_GPIO_WritePin(GPO_RUN_LED_GPIO_Port,GPO_RUN_LED_Pin,on ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
LED灯的闪烁序列如下:
typedef struct
{
uint16_t bON;
uint16_t delay;
}LEDFlashState;
// LED灯的亮灭顺序
LEDFlashState ledFlashStates[] =
{
{1,300}, // 亮灯300ms
{0,700}, // 灭灯700ms
{1,100}, // 亮灯100ms
{0,100}, // 灭灯100ms
{1,100}, // 亮灯100ms
{0,700}, // 灭灯700ms
};
那么有至少2种有效的闪灯控制实现。
- 方案一,基于任务
__NO_RETURN void threadBoardLed (void *argument)
{
uint8_t step = 0;
uint32_t ticks ;
uint32_t baseTicks = osKernelGetTickCount();
while(1) {
aplRunLedOn(ledFlashStates[step].bON); // 板载LED
ticks = osKernelGetTickCount();
osDelayUntil(ticks + ledFlashStates[step].delay);
step ++;
if(step >= sizeof(ledFlashStates)/sizeof(ledFlashStates[0])) {
step = 0;
}
}
}
- 方案二,基于定时器
osTimerId_t timerIdLedFlash;
void timerLedFlash_Callback (void *arg)
{
static uint8_t step = 0;
osTimerStop (timerIdLedFlash);
aplRunLedOn(ledFlashStates[step].bON);
osTimerStart (timerIdLedFlash,ledFlashStates[step].delay);
step ++;
if(step >= sizeof(ledFlashStates)/sizeof(ledFlashStates[0])) {
step = 0;
}
}
__NO_RETURN void threadBoardLed (void *argument)
{
timerIdLedFlash = osTimerNew (timerLedFlash_Callback, osTimerPeriodic, NULL, NULL);
osTimerStart (timerIdLedFlash,9);
while(1) {
osDelay(1000);
}
}
下面还有一种短期没问题,但是不能长期运行的方案
__NO_RETURN void threadBoardLed (void *argument)
{
uint8_t step = 0;
uint32_t ticks ;
uint32_t baseTicks = osKernelGetTickCount();
while(1)
{
osDelay(10);
ticks = osKernelGetTickCount();
if(ticks < (baseTicks + ledFlashStates[step].delay)) {
aplRunLedOn(ledFlashStates[step].bON); // 板载LED
} else {
baseTicks = osKernelGetTickCount();
step ++;
if(step >= sizeof(ledFlashStates)/sizeof(ledFlashStates[0])) {
step = 0;
}
}
}
}
上面的代码潜在的问题是通过osKernelGetTickCount获取的系统计数器可能会溢出后环回。如果系统心跳设置为1毫秒一次,会在运行大约49天后出现计数器溢出。