LED(实现多个LED组合序列闪烁)

一、

.h

#include <stdint.h>
#include <stdbool.h>
#include <led.h>

/********************************
*led序列动作: 
*延时、停止、周期循环
*********************************/
#define LEDSEQ_WAITMS(X) (X)
#define LEDSEQ_STOP      -1
#define LEDSEQ_LOOP      -2

typedef struct 
{
    bool value;
    int action;
} ledseq_t;

extern const ledseq_t seq_calibrated[];
extern const ledseq_t seq_lowbat[];
extern const ledseq_t seq_alive[];
extern const ledseq_t seq_linkup[];
extern const ledseq_t seq_charged[];
extern const ledseq_t seq_charging[];


void ledseqInit(void);
bool ledseqTest(void);
void ledseqEnable(bool enable);
void ledseqRun(led_e led, const ledseq_t * sequence);
void ledseqStop(led_e led, const ledseq_t * sequence);
void ledseqSetTimes(ledseq_t *sequence, s32 onTime, s32 offTime);

二、

.c


/* LED序列优先级 */
static ledseq_t const * sequences[] = 
{
    seq_lowbat,
    seq_charged,
    seq_charging,
    seq_calibrated,
    seq_alive,
    seq_linkup,
};

/*Led 序列*/
ledseq_t const seq_lowbat[] =     /*电池低电压序列*/
{
    { true, LEDSEQ_WAITMS(1000)},
    {    0, LEDSEQ_LOOP},
};
const ledseq_t seq_calibrated[] = /*传感器校准完成序列*/
{
    { true, LEDSEQ_WAITMS(50)},
    {false, LEDSEQ_WAITMS(450)},
    {    0, LEDSEQ_LOOP},
};
const ledseq_t seq_alive[] =     /*开机序列*/
{
    { true, LEDSEQ_WAITMS(50)},
    {false, LEDSEQ_WAITMS(1950)},
    {    0, LEDSEQ_LOOP},
};
const ledseq_t seq_linkup[] =     /*通信连接序列*/
{
    { true, LEDSEQ_WAITMS(1)},
    {false, LEDSEQ_WAITMS(0)},
    {    0, LEDSEQ_STOP},
};
const ledseq_t seq_charged[] =     /*电池充电完成序列*/
{
    { true, LEDSEQ_WAITMS(1000)},
    {    0, LEDSEQ_LOOP},
};
ledseq_t const seq_charging[] = /*电池充电进行中序列*/
{
    { true, LEDSEQ_WAITMS(200)},
    {false, LEDSEQ_WAITMS(800)},
    {    0, LEDSEQ_LOOP},
};

#define SEQ_NUM (sizeof(sequences)/sizeof(sequences[0]))
    
static void updateActive(led_e led);        /*更新led的最高优先级序列*/
static int getPrio(const ledseq_t *seq);    /*获取led优先级*/
static void runLedseq(xTimerHandle xTimer);

static bool isInit = false;
static bool ledseqEnabled = true;
static int activeSeq[LED_NUM];        /*每个LED对应的活动优先级序列*/
static int state[LED_NUM][SEQ_NUM];    /*每个LED对应的序列的当前位置*/

static xTimerHandle timer[LED_NUM];    /*定时器句柄*/
static xSemaphoreHandle ledseqSem;    /*信号量*/


void ledseqInit()
{
    int i,j;
    if(isInit) return;

    ledInit();
    
    /*初始化各个序列状态*/
    for(i=0; i<LED_NUM; i++) 
    {
        activeSeq[i] = LEDSEQ_STOP;
        for(j=0; j<SEQ_NUM; j++)
            state[i][j] = LEDSEQ_STOP;
    }
    
    /*创建软件定时器*/
    for(i=0; i<LED_NUM; i++)
        timer[i] = xTimerCreate("ledseqTimer", 1000, pdFALSE, (void*)i, runLedseq);

    vSemaphoreCreateBinary(ledseqSem);    /*创建一个2值信号量*/

    isInit = true;
}

bool ledseqTest(void)
{
    bool status;

    status = isInit & ledTest();
    ledseqEnable(true);
    return status;
}

void ledseqEnable(bool enable)
{
    ledseqEnabled = enable;
}

void ledseqSetTimes(ledseq_t *sequence, int onTime, int offTime)
{
    sequence[0].action = onTime;
    sequence[1].action = offTime;
}

/*运行led的sequence序列*/
void ledseqRun(led_e led, const ledseq_t *sequence)
{
    int prio = getPrio(sequence);    /*获取led优先级序列*/

    if(prio<0) return;

    xSemaphoreTake(ledseqSem, portMAX_DELAY);
    state[led][prio] = 0; 
    updateActive(led);
    xSemaphoreGive(ledseqSem);

    if(activeSeq[led] == prio)    /*当前序列优先级等于活动序列优先级*/
        runLedseq(timer[led]);
}

/*停止led的sequence序列*/
void ledseqStop(led_e led, const ledseq_t *sequence)
{
    int prio = getPrio(sequence);

    if(prio<0) return;

    xSemaphoreTake(ledseqSem, portMAX_DELAY);
    state[led][prio] = LEDSEQ_STOP;  
    updateActive(led);
    xSemaphoreGive(ledseqSem);

    runLedseq(timer[led]);
}

/*FreeRTOS 定时器回调函数*/
static void runLedseq( xTimerHandle xTimer )
{
    bool leave = false;
    const ledseq_t *step;
    led_e led = (led_e)pvTimerGetTimerID(xTimer);

    if (!ledseqEnabled) return;

    while(!leave) 
    {
        int prio = activeSeq[led];

        if (prio == LEDSEQ_STOP)
            return;

        step = &sequences[prio][state[led][prio]];

        state[led][prio]++;

        xSemaphoreTake(ledseqSem, portMAX_DELAY);
        switch(step->action)
        {
            case LEDSEQ_LOOP:
                state[led][prio] = 0;
                break;
            case LEDSEQ_STOP:
                state[led][prio] = LEDSEQ_STOP;
                updateActive(led);
                break;
            default:  /*LED定时*/
                ledSet(led, step->value);    /*定时step->value*/
                if (step->action == 0)
                    break;
                xTimerChangePeriod(xTimer, step->action, 0);
                xTimerStart(xTimer, 0);
                leave=true;
                break;
        }
        xSemaphoreGive(ledseqSem);
    }
}

/*获取led序列优先级*/
static int getPrio(const ledseq_t *seq)
{
    int prio;

    for(prio=0; prio<SEQ_NUM; prio++)
        if(sequences[prio]==seq) return prio;

    return -1; /*无效序列*/
}

/*更新led的最高优先级序列*/
static void updateActive(led_e led)
{
    int prio;

    ledSet(led, false);
    activeSeq[led]=LEDSEQ_STOP;
    
    for(prio=0;prio<SEQ_NUM;prio++)
    {
        if (state[led][prio] != LEDSEQ_STOP)
        {
            activeSeq[led]=prio;
            break;
        }
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值