easyblink

easyblink

1.初始化
    led1 = easyblink_init_led(GET_PIN(B, 7), PIN_LOW);

功能:对控制led灯的引脚初始化,传入的参数为 初始化哪个引脚,高有效还是低有效

实现方法1.遍历eb_leds数组(该数组保存了所有led灯的信息,初始的时候led结构体中相关的标志位没有激活),在数组中找到第一个没有激活的位置,该位置即会保存当前所要初始化的那个led灯的所有信息。

eb_leds数组中每个元素是easyblink_data类型的变量

struct easyblink_data
{
    rt_base_t led_pin;
    rt_base_t active_level;
    rt_uint16_t flag;
    rt_int16_t nums;
    rt_int16_t nums_bak;
    rt_uint16_t pulse;
    rt_uint16_t pulse_bak;
    rt_uint16_t npulse;
    rt_uint16_t npulse_bak;
    rt_int32_t ticks;
};

2.找到保存led信息的位置后,首先将标志位置为1,((led)->flag |= (0X01)), 防止这个位置被后面初始化的led占了。然后将初始化的关键信息保存下来(哪个引脚,什么电平有效)。同时配置该引脚为输出模式。

__EASYBLINK_SET_FLAG(led, PKG_EASYBLINK_INIT);

led->led_pin = led_pin;
led->active_level = active_level;

eb_led_off(led);
rt_pin_mode(led_pin, PIN_MODE_OUTPUT);

3.如果是第一个配置的led,在配置完之后还需要开一个线程,这个线程的任务就是实现具体的led闪烁的业务。(第一个打开线程后,第二个就不需要打开了,因为这个线程会遍历存放所有led信息的数组)。【只用一个线程就能解决所有led的业务能够节约内存】。

2.调用
easyblink(led1, 5, 500, 1000);

功能:led1 闪烁5次 每次1000ms ,其中点亮的时间为500ms。 note:无限次的参数为-1。

实现方法:判断当前的灯属于什么状态(上一个指令有没有执行完?,上一个指令是什么?)。

上一个指令是无限次循环:保存当前无线循环的信息(周期和占空比)—>关灯—>执行当前的指令

上一个指令是有限循环且未执行完毕:等上一个指令执行完毕–>再执行当前的指令

上一个指令执行完毕了,led当前属于空闲状态:直接执行当前的指令

 if(led -> nums == -1)//无限循环?
    {...........}
    else if (__EASYBLINK_IS_FLAG(led,PKG_EASYBLINK_ACTIVE))//上一个指令没有执行完毕?
    {..........}
    else
    {.......... }

easyblink只操作了led结构体(*easyblink_data)的信息,在这个函数中没有控制MCU相关引脚的电平,具体引脚电平的控制是在初始化时开的线程中实现的

3.线程实现的逻辑

线程入口函数eb_daemon_thread_entry,负责将实现数组eb_leds中每个led结构体包含的闪烁信息

遍历数组中的每个led灯

if(如果当前led应该亮) //如果这次应该亮
{
	if(当前还有剩余的闪烁次数 或 闪烁的次数为无限次)
	{
            操作硬件点灯          
            清除应该亮的标志位 //下一次就是应该灭了
            记录下应该亮多久 //方便到点了过来给关闭
    }
    else //如果当前没有闪烁的次数
    {
        if(如果还有下一个任务)
        {
			把led的下一个任务(bak里存着的)拿出来
            tick赋值0 // 0是最小 下次线程一定先处理跟新这个灯的信息
            如果任务是永久的(-1)情况,单独处理    
        }
        else //没有下一个任务 (当前任务结束+没有下一个任务==》led任务结束)
        {
            关闭led灯激活的标志位 // 没有剩余的闪烁次数 也 下面也没有要做的事  这一轮就算结束了
        }
    }
}
else//如果应该灭
{
    操作硬件灭灯
    置位点亮的标志位//下一个时间点应该开灯
    记录关灯的时间
    闪烁的次数-1//成功完成了一次闪烁    
}
4.单线程实现多个led灯的闪烁

这个包的一个特点是,使用一个线程解决了多个灯的闪烁问题,好处是节约内存。

实现方法:每次找到最先需要闪烁的灯,并算出需要等待的时间----->等待相应的时间(交出CPU的控制权)----->led灯动作----->再次算出最先需要闪烁的灯的时间…

1.计算需要等待的时间 correct_or_get_min_ticks(0, RT_FALSE)

功能:校正其余led的ticks, 并返回最小的ticks, 当corr为fasle时, 只单纯取最小的ticks

实现: 遍历所有的led灯,选出最小的led->ticks

if(led->ticks < tick_min)
    tick_min = led->ticks;

2.等待时间(交出CPU控制权)

  • 在等待的时候没有新的led任务(有新调用easyblink

rt_sem_take等待信号量,如果等待的时间超过wait_tick则返回RT_ETIMEOUT。没有新的led任务时,不会等待信号量,超过时间则break跳出这个循环。

  • 在等待的时候添加了新的led任务(没有新调用easyblink

调用新的led时会释放一个信号量(在led_blink_delayrt_sem_release)----->收到RT_EOK----->correct_or_get_min_ticks(tick, RT_TRUE)重新计算tick,并取最小的ticks

        while(wait_tick)
        {
            tick = rt_tick_get();
            /*在线等待 wait_tick个 os tick*/
            if (rt_sem_take(eb_sem, wait_tick) != RT_EOK)
                break;
            /*接收到信号量,校正其他led的tick数,并取最小的ticks*/
            wait_tick = correct_or_get_min_ticks(tick, RT_TRUE);
        }

3.重新计算tick

重新计算tick,并取最小时间的方法 correct_or_get_min_ticks(tick, RT_TRUE)

1.已经等了多长时间了tick = rt_tick_get() - tick 现在的tick - 上一次记录的tick

rt_tick_get() // 返回从开机开始的时间戳

2.更新所有led的最新等待时间 最新时间 = 所有led的时间戳 - 已经等待的时间

 led->ticks -= tick;
/*校正其余led的ticks, 并返回最小的ticks, 当corr为fasle时, 只单纯取最小的ticks*/
rt_tick_t correct_or_get_min_ticks(rt_tick_t tick, rt_bool_t corr)
{
    int i;
    ebled_t led = RT_NULL;
    rt_int32_t tick_min = PKG_EASYBLINK_WAIT_MAX_TICK;

    if(corr)
        tick = rt_tick_get() - tick;

    for(i = 0; i < PKG_EASYBLINK_MAX_LED_NUMS; i++)
    {
        led = &eb_leds[i];
        if(__EASYBLINK_IS_FLAG(led, PKG_EASYBLINK_ACTIVE))
        {
            if(corr)
            {
                if(__EASYBLINK_IS_FLAG(led, PKG_EASYBLINK_CORRECT))
                    __EASYBLINK_CLEAR_FLAG(led, PKG_EASYBLINK_CORRECT);
                else
                    led->ticks -= tick;
            }

            if(led->ticks < tick_min)
                tick_min = led->ticks;
        }
    }

    return (rt_tick_t)((tick_min < 0) ? 0 : tick_min);//如果比0小就返回0
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值