关键字:延时器;非阻塞自由延时
在一些按键或其它形式的命令响应中,要求严格的话通常会需要队列缓存命令,以防丢失。
但是我通常还会遇到一些要求非常不严格的场景,这些场景甚至要限制响应的次数或频率(这里指不能响应太快)。
比如(只是个例子),我的产品是一个根据接收到的串口命令来工作的。串口命令发送的速度是不确定的,有时候1秒
会发送10帧命令过来,有的时候1秒确能发送100帧,但是这个产品每秒只打算处理20帧命令。而且由于命令有多个,
对于有些命令码可能每秒响应40帧或30帧等,这种场景用多个延时器就很合适了。
延时器模块的接口函数一共3个,如下:
- /* Exported functions ------------------------------------------------------- */
- bool zl_poll_delay_set(uint8_t chUserId, uint16_t hwTime);
- bool zl_poll_delay_timeout(uint8_t chUserId);
- void zl_poll_delay_tick(void);
看下接口函数的实现,很简单的
- /* Z L _ P O L L _ D E L A Y _ S E T */
- /*-------------------------------------------------------------------------
- 功能描述 : 设定延时时间,同时启动延时。
- 输入参数 : uint8_t chUserId 延时器ID
- uint16_t hwTime 延时时间
- 输出参数 : 无
- 返 回 值 :
- 修改历史
- 1.日 期 : 2017年2月6日
- 作 者 : zys
- 修改内容 : 新生成函数,OK。
- -------------------------------------------------------------------------*/
- bool zl_poll_delay_set(uint8_t chUserId, uint16_t hwTime)
- {
- if (chUserId >= ZL_POLL_DELAY_NUM) {
- return false;
- }
- if (0 == hwTime) {
- return false;
- }
- s_tPollBuf[chUserId].Time = hwTime;
- return true;
- }
- /* Z L _ P O L L _ D E L A Y _ T I M E O U T */
- /*-------------------------------------------------------------------------
- 功能描述 : 查询给定ID的延时器是否超时。
- 输入参数 : uint8_t chUserId
- 输出参数 : 无
- 返 回 值 : true 超时;false 未超时。
- 修改历史
- 1.日 期 : 2017年5月22日
- 作 者 : zys
- 修改内容 : 新生成函数。
- -------------------------------------------------------------------------*/
- bool zl_poll_delay_timeout(uint8_t chUserId)
- {
- if (chUserId >= ZL_POLL_DELAY_NUM) {
- return false;
- }
- if ( !s_tPollBuf[chUserId].Time) {
- return true;
- }
- return false;
- }
- /* Z L _ P O L L _ D E L A Y _ T I C K */
- /*-------------------------------------------------------------------------
- 功能描述 : 延时模块的驱动任务,在心跳中断里运行。
- 输入参数 : void
- 输出参数 : 无
- 返 回 值 :
- 修改历史
- 1.日 期 : 2017年5月22日
- 作 者 : zys
- 修改内容 : 新生成函数。
- -------------------------------------------------------------------------*/
- void zl_poll_delay_tick(void)
- {
- uint8_t i;
- for ( i = 0 ; i < ZL_POLL_DELAY_NUM; i++ ) {
- if (s_tPollBuf[i].Time) {
- s_tPollBuf[i].Time--;
- }
- }
- }
模块的使用
使用很简单,首先把模块源文件添加到工程中,然后把
- void zl_poll_delay_tick(void)
放到心跳中断里,我一般用1ms的心跳中断。
现在就能使用
- bool zl_poll_delay_set(uint8_t chUserId, uint16_t hwTime)
来设置延时器了,入参分别是延时器的ID和延时时间,延时时间单位和心跳中断有关,看自己需求了。。。
然后用
- bool zl_poll_delay_timeout(uint8_t chUserId)
来查询延时器是否超时,入参是要查询的延时器ID号。
延时器的可用最大数量通过宏定义配置
- /* 定义可用的延时数量 */
- #define ZL_POLL_DELAY_NUM 5
模拟一个应用场景演示代码
- /* 定义延时器信息,便于阅读修改 */
- #define DELAY_ID0 0
- #define DELAY_TIME0 50
- #define DELAY_ID1 1
- #define DELAY_TIME1 900
- /* 模拟一个应用场景 */
- void xxx_cmd_process(uint8_t chCmd)
- {
- switch (chCmd) {
- case CMD_LEFT:
- /* 该命令执行间隔不能小于50ms */
- if (zl_poll_delay_timeout(DELAY_ID0)) {
- zl_poll_delay_set(DELAY_ID0, DELAY_TIME0);
- cmd_do_left();
- }
- break;
- case CMD_RIGHT:
- /* 该命令执行间隔不能小于900ms */
- if (zl_poll_delay_timeout(DELAY_ID1)) {
- zl_poll_delay_set(DELAY_ID1, DELAY_TIME1);
- cmd_do_left();
- }
- break;
- case CMD_UP:
- /* 该命令无限制,来就执行 */
- cmd_do_up();
- break;
- case CMD_DOWN:
- break;
- default:
- break;
- }
- }
- /* 在1ms心跳(时基)中断里运行 */
- void st_systick_1ms_irq(void)
- {
- zl_poll_delay_tick()
- }
延时器的用处还有很多,可以灵活。。。
最新回复 [0]