基于CMSIS-RTOS2的闪灯序列控制

控制灯的基本函数:

#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天后出现计数器溢出。

你可能感兴趣的:(rl-rtx,电子,电路,MCU及外设驱动,嵌入式软件)