RP2040(树莓派Pico) 普通定时器&RTC

定时器功能也很基础,而且只有一个,主要功能如下:

  • 64位计数器 (频率固定1MHz,所以要好几千年才能溢出!)
  • 4个闹钟 (闹钟是只匹配低32B,最大间隔4295秒.)
  • 寄存器自带映射,所以多个处理器同时访问也不用考虑竞争问题. (无需考虑竞争问题.)

其中ALARM功能只会发起一次中断,中断发生后就会清除ARMED位,所有函数都有他的毫秒版本和微秒版本.

struct repeating_timer timer;

int main() {
    // 设置两秒之后发起一次中断.
    add_alarm_in_ms(2000, alarm_callback, NULL, false);

    // 参数1:定时时间 参数2:回调函数 参数3:携带数据 参数4:定时器结构体
    // 参数1 > 0 则在回调函数执行结束后再开启下一次定时,这样每次间隔可能不一样.
    // 参数1 < 0 则在回调函数进入时就开启下一次定时器,这样可能任务还没完成下一次定时又来了.
    // 通过参数3可以多个定时器共享一个回调.
    add_repeating_timer_ms(500, repeating_timer_callback, NULL, &timer);

    // 取消周期定时器
    bool cancelled = cancel_repeating_timer(&timer);
}

另外的两个定时器例子,其中periodic_sampler演示了队列的使用,启动了一个间隔定时器,timer_lowlevel演示了从底层访问寄存器的方法来控制定时器,另外,默认的ALARM函数也不能指定用哪个ALARM,而是内部Pool自动轮询.但是由于底层的一些延迟函数等等也用到了定时器,所以不推荐使用这个方法,根据源码来看,以后可能还会出多定时器版本的芯片.

RTC和定时器有相似的功能,都可以发起ALARM,只不过是被专用设计用来储存时间,因此可以处理闰年啊之类的问题,没有专用的RTC引脚,在低功耗模式下工作需要外部输入时钟(听起来就有点扯,但这是真!),没有专门的RTC引脚,也没有专用的RTC电源,因此… (就不用多说了!)

调用rtc_init就可以使用RTC,至于复位后会怎样?我不知道,因为我没找到复位的方法?是RUN引脚还是什么?rtc_set_datetime设置时间,而rtc_get_datetime获取时间,RTC寄存器没特殊保护.从hello_rtc能获取到不少内容,特别注意的是,他的时钟引用于XOSC,这个时钟足足1000ppm,每天就可能误差86.4秒.

比较关键是rtc_set_alarm函数,只有1个ALARM,设定方法和Linux的cron很类似.

datetime_t alarm = {
    .year  = -1,
    .month = -1,
    .day   = -1,
    .dotw  = -1,
    .hour  = -1,
    .min   = -1,
    .sec   = 30
};

rtc_set_alarm(&alarm, &alarm_callback);

就像上面的代码,-1即任意匹配,上面的代码会在每年每月每天不管星期几每小时每分30秒发起中断,而且是周期性的,如果全部数值都是确定值,则发生一次后再也不会被匹配到,就是一次性.

发表评论

邮箱地址不会被公开。 必填项已用*标注