文章目录
- 简要
- 注意事项
- API说明
- 1、1毫秒计时驱动
- 2、1秒计时驱动
- 2、设置一个单位时间为1毫秒的周期性事件
- 3、设置一个单位时间为1秒的周期性事件
- 4、单次触发事件
- 5、清除停止事件
- 5、缓存事件触发标志
- 6、获取事件状态
- 示例
- 源码
简要
最大支持32个事件标志管理,倒计时精度为1毫秒的最大倒计时时间为4294967295
毫秒,倒计时精度为1秒的最大倒计时时间为4294967295
秒,可产生以下事件:
- 立即触发事件
- 单次超时事件
- 循环周期性事件
注意事项
- 内存访问一致性:主循环中获取事件标志或者调用事件触发和事件设置API都有可能导致读取的数据不一致,由于事件标志是4个字节长度,在事件标志读取和设置途中有可能在定时器中断中也会同时操作,这就导致在主循环中读取到的变量出现误差。所以会在相关函数入口和退出处控制控制所有中断开关。
__set_PRIMASK(1);
关闭所有中断__set_PRIMASK(0);
打开所有中断
API说明
1、1毫秒计时驱动
void eventDriver(void);
调用setEvent(...)
延时自动触发事件的倒计时就是在该API中执行,所以该函数需要放在一个周期为1毫秒的定时器中执行。
2、1秒计时驱动
void eventDriver1s(void);
调用setEvent1s(...)
延时自动触发事件的倒计时就是在该API中执行,所以该函数需要放在一个周期为1秒的定时器中执行。
比如一些低功耗运行的场景,该定时器可以选择低功耗定时器
2、设置一个单位时间为1毫秒的周期性事件
void setEvent(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_ms);
序号 | 传参 | 变量类型 | 说明 |
---|---|---|---|
1 | mask | uint32_t | 需要设置的事件标志,一个事件占用一个bit内存 |
2 | first | bool | true 表示调用setEvent(...) 后立即触发一次事件,false 表示等待周期时间到了再触发产生事件 |
3 | reload | bool | true 表示周期性触发mask 事件,false 表示执行完第一次超时触发事件后,该事件就停止运行 |
4 | setCover | bool | true 表示重新计时,false 表示不重新计时 |
5 | timeOut_ms | uint32_t | 0 表示立即触发,无周期性事件,非0 表示以时间做超时事件 |
3、设置一个单位时间为1秒的周期性事件
void setEvent1s(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_s);
序号 | 传参 | 变量类型 | 说明 |
---|---|---|---|
1 | mask | uint32_t | 需要设置的事件标志,一个事件占用一个bit内存 |
2 | first | bool | true 表示调用setEvent(...) 后立即触发一次事件,false 表示等待周期时间到了再触发产生事件 |
3 | reload | bool | true 表示周期性触发mask 事件,false 表示执行完第一次超时触发事件后,该事件就停止运行 |
4 | setCover | bool | true 表示重新计时,false 表示不重新计时 |
5 | timeOut_s | uint32_t | 0 表示立即触发,无周期性事件,非0 表示以时间做超时事件 |
4、单次触发事件
void event_post(uint32_t mask);
执行后会立即触发该事件。
5、清除停止事件
void event_clear(uint32_t mask);
执行后会立即停止该事件的执行。
5、缓存事件触发标志
uint32_t event_pend(void);
该函数放在主循环中执行,会先把所有的事件标志缓存起来,供后续事件判断处理。
6、获取事件状态
uint32_t getEvent(uint32_t mask);
获取事件状态,返回值0
表示该事件未触发,非0
表示该事件已触发。
示例
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "eventUnit.h"#define EVENT_TIME_CYCLE_10ms 0
#define EVENT_TIME_CYCLE_500ms 1void MAIN_TIM_CALLBACK(uint8_t status, uint32_t param)
{static uint16_t timeCnt_1ms = 0;if(++ timeCnt_1ms == 5){timeCnt_1ms = 0;eventDriver();}
}
void MAIN_TIM_1S_CALLBACK(uint8_t status, uint32_t param)
{eventDriver1s();
}
int main(void)
{myTim3_init(200, 0);myIrqCallback_mainTimCallback.thisCb = MAIN_TIM_CALLBACK;TIM3_callbackRegiste(&myIrqCallback_mainTimCallback);setEvent(EVENT_TIME_CYCLE_10ms, true, true, true, 10);setEvent(EVENT_TIME_CYCLE_500ms, true, true, true, 500);while(1){event_pend();if (getEvent(EVENT_TIME_CYCLE_10ms)){}if (getEvent(EVENT_TIME_CYCLE_500ms)){}}
}
源码
eventUnit.h
#ifndef __EVENTUNIT_H
#define __EVENTUNIT_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
// #include "at32f423_clock.h"
#include "cmsis_armcc.h"#define EVENT_INDEX_MAX 32
typedef struct
{bool reload; //bool flag_1s; //uint32_t count; //uint32_t countSet; //
}eventParams_ts;void eventDriver(void);
void eventDriver1s(void);
void setEvent(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_ms);
void setEvent1s(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_s);
void event_post(uint32_t mask);
void event_clear(uint32_t mask);
uint32_t event_pend(void);
uint32_t getEvent(uint32_t mask);
#endif
eventUnit.c
#include "eventUnit.h"volatile eventParams_ts eventParams[EVENT_INDEX_MAX];
volatile uint32_t timerEventMask;
uint32_t getEventMask;
bool eventDriverSta;void eventDriver(void)
{int i;for ( i = 0; i < EVENT_INDEX_MAX; i++){if (eventParams[i].flag_1s == false && eventParams[i].countSet){if (++ eventParams[i].count >= eventParams[i].countSet - 1){eventParams[i].count = 0;if (eventParams[i].reload == false){eventParams[i].countSet = 0;}timerEventMask |= (1 << i);}}}
}
void eventDriver1s(void)
{int i;for ( i = 0; i < EVENT_INDEX_MAX; i++){if (eventParams[i].flag_1s && eventParams[i].countSet){if (++ eventParams[i].count >= eventParams[i].countSet - 1){eventParams[i].count = 0;if (eventParams[i].reload == false){eventParams[i].countSet = 0;}timerEventMask |= (1 << i);}}}
}
void setEvent(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_ms)
{__set_PRIMASK(1);if (setCover){eventParams[mask].count = 0;}eventParams[mask].countSet = timeOut_ms;eventParams[mask].flag_1s = false;eventParams[mask].reload = reload;if ((timeOut_ms == 0) || first){timerEventMask |= (1 << mask);}__set_PRIMASK(0);//开总中断
}
void setEvent1s(uint32_t mask, bool first, bool reload, bool setCover, uint32_t timeOut_s)
{__set_PRIMASK(1);if (setCover){eventParams[mask].count = 0;}eventParams[mask].countSet = timeOut_s;eventParams[mask].flag_1s = true;eventParams[mask].reload = reload;if ((timeOut_ms == 0) || first){timerEventMask |= (1 << mask);}__set_PRIMASK(0);//开总中断
}
void event_post(uint32_t mask)
{__set_PRIMASK(1);eventParams[mask].countSet = 0;eventParams[mask].count = 0;eventParams[mask].reload = false;timerEventMask |= (1 << mask);__set_PRIMASK(0);//开总中断
}
void event_clear(uint32_t mask)
{__set_PRIMASK(1);eventParams[mask].countSet = 0;eventParams[mask].count = 0;eventParams[mask].reload = false;timerEventMask &= (~(1 << mask));__set_PRIMASK(0);//开总中断
}
uint32_t event_pend(void)
{uint32_t ret = 0;__set_PRIMASK(1);ret = timerEventMask;getEventMask = ret;timerEventMask = 0;__set_PRIMASK(0);//开总中断return ret;
}
uint32_t getEvent(uint32_t mask)
{return getEventMask & (1 << mask);
}