Base Timer 包含三个定时器 Timer0/1/2。Timer0/1/2 功能完全相同。Timer0/1/2 是同步定时/计数器,可以作为 16 位自动重装载功能的定时/计数器,也可以作为 32 位无重载功能的定时/计数器。Timer0/1/2 可以对外部脉冲进行计数或者实现系统定时。
Timer0/1/2 每个定时/计数器都有独立的控制启动信号,以及外部输入时钟,门控信号。
TIM0/1/2 的定时/计数器支持两种工作模式,模式 1为 32 位自由计数模式。模式 2 是 16 位重载模式。
通过定时器的翻转输出功能可以实现驱动 Buzzer 的功能。还给出了在计数时钟为 4M 情况下 Buzzer 输出不同频率的Timer 重载模式配置值。
bt_cnt例程
本样例Base Timer对内部4M时钟进行计数,直到计数到溢出值时产生中断,并停止计数,LED1点亮,大约上电4.2s左右。
使用内部4MHz,定时器进行256分频,周期为15625Hz,定时器初始值0xFFFF0000,需要16位溢出,计数值65536。
溢出时间为65536/15625=4.19s
- en_result_t BtCntTest(void)
- {
- stc_bt_config_t stcConfig;
- en_result_t enResult = Error;
- uint32_t u32InitCntData = 0xFFFFFFFA; // 设置初始值,实际使用16位
-
- // INT ENABLE
- EnableNvic(TIM0_IRQn, 3, TRUE);
- Bt_EnableIrq(TIM0);
-
- //对外部ext0计数,GPIO配置
- Gpio_SetFunc_TIM0_EXT_P34();
-
- stcConfig.enGateP = BtPositive;
- stcConfig.enGate = BtGateDisable;
- stcConfig.enPRS = BtPCLKDiv256;
- stcConfig.enTog = BtTogDisable;
- stcConfig.enCT = BtCounter;
- stcConfig.enMD = BtMode1;
-
- stcConfig.pfnTim0Cb = Bt0Int;
- // Bt配置初始化
- if (Ok != Bt_Init(TIM0, &stcConfig)) {
- enResult = Error;
- }
- //设置计数值,启动计数
- Bt_Cnt32Set(TIM0, u32InitCntData);
- Bt_Run(TIM0);
-
- Gpio_InitIO(1, 5, GpioDirOut);
- Gpio_SetIO(1, 5, 0);
- //等待计数完成后进入中断……
- while (1) {
- if (0x01 == u32BtTestFlag) {
- //进入中断后,停止计数
- u32BtTestFlag = (u32BtTestFlag & (~0x01));
- Bt_Stop(TIM0);
- enResult = Ok;
- break;
- }
- }
- Gpio_SetIO(1, 5, 1);
- return enResult;
- }
设置tim0计数器,在开始计数时点亮LED3,当计数到时熄灭LED3.
- void Bt0Int(void)
- {
- if (TRUE == Bt_GetIntFlag(TIM0)) {
- Bt_ClearIntFlag(TIM0);
- u32BtTestFlag = 0x01;
- }
- }
在中断中置位,主程序此时会退出while循环向下执行,熄灭LED3。
bt_timer例程
本样例使用门控控制定时器定时,定时溢出后产生中断,翻转LED1,并重新载入初值进行定时,并再次溢出进入中断,翻转LED1。
使用内部4MHz,定时器进行256分频,周期为15625Hz,定时器初始值0x2000,溢出需要57344计数。
溢出时间为57344/15625=3.67s
- en_result_t BtTimerTest(void)
- {
- stc_bt_config_t stcConfig;
- en_result_t enResult = Error;
- uint16_t u16ArrData = 0xF000; // 重载值
- uint16_t u16InitCntData = 0xF000; // 计数值
-
- EnableNvic(TIM0_IRQn, 3, TRUE);
- Bt_EnableIrq(TIM0);
-
- // P35设置为门控使能IO
- Gpio_SetFunc_TIM0_GATE_P35();
-
- stcConfig.pfnTim0Cb = Bt0Int;
- stcConfig.enGateP = BtPositive;
- stcConfig.enGate = BtGateEnable;
- stcConfig.enPRS = BtPCLKDiv256;
- stcConfig.enTog = BtTogDisable;
- stcConfig.enCT = BtTimer;
- stcConfig.enMD = BtMode2;
-
- // Bt初始化
- if (Ok != Bt_Init(TIM0, &stcConfig)) {
- enResult = Error;
- }
-
- //设置重载值和计数值,启动计数
- Bt_ARRSet(TIM0, u16ArrData);
- Bt_Cnt16Set(TIM0, u16InitCntData);
- Bt_Run(TIM0);
-
- //此处进入中断……
- while (1) {
- //判断是否第二次进入中断
- if (0x02 == u32BtTestFlag) {
- u32BtTestFlag = u32BtTestFlag & (~0x02);
- if (10 == u32Cnt) {
- Bt_Stop(TIM0);
- enResult = Ok;
- break;
- }
- u32Cnt++;
- }
- }
-
- return enResult;
- }
这里是对定时器的设置,已经门控引脚的设置。
- void Bt0Int(void)
- {
- if (TRUE == Bt_GetIntFlag(TIM0)) {
- Bt_ClearIntFlag(TIM0);
- u32BtTestFlag = 0x02;
- Data = ~Data;
- Gpio_SetIO(2, 3, Data);
- }
- }
在中断中翻转LED1。
bt_tog例程
本样例展示翻转输出功能,可输出两路相位相反的波形,该功能可用于驱动Buzzer。
使用内部4MHz,定时器进行64分频,周期为62500Hz,定时器初始值0x0BDC,溢出需要62500计数。
溢出时间为1s,间隔1s翻转一次,翻转10次后停止。
- en_result_t BtTogTest(void)
- {
- stc_bt_config_t stcConfig;
- en_result_t enResult = Ok;
- ///<(4Mhz->1000Hz)
- uint16_t u16ArrData = 0x0BDC;
- uint16_t u16InitCntData = 0x0BDC;
-
- // config P14/P15 as toggleB/toggle
- Gpio_SetFunc_TIM2_TOGN_P14();
- Gpio_SetFunc_TIM2_TOG_P15();
-
- EnableNvic(TIM2_IRQn, 3, TRUE);
- Bt_EnableIrq(TIM2);
-
- stcConfig.pfnTim2Cb = Bt2Int;
- stcConfig.enGateP = BtPositive;
- stcConfig.enGate = BtGateDisable;
- stcConfig.enPRS = BtPCLKDiv64;
- stcConfig.enTog = BtTogEnable;
- stcConfig.enCT = BtTimer;
- stcConfig.enMD = BtMode2;
-
- if (Ok != Bt_Init(TIM2, &stcConfig)) {
- enResult = Error;
- }
-
- //设置重载值,计数值,启动计数
- Bt_ARRSet(TIM2, u16ArrData);
- Bt_Cnt16Set(TIM2, u16InitCntData);
- Bt_Run(TIM2);
-
- //等待波形输出……
- u32Cnt = 10;
- while (u32Cnt)
- ;
- Bt_Stop(TIM2);
-
- return enResult;
- }
在中断中进行自减计数。
- void Bt2Int(void)
- {
- if (TRUE == Bt_GetIntFlag(TIM2)) {
- Bt_ClearIntFlag(TIM2);
- u32BtTestFlag = 0x04;
- u32Cnt--;
- }
- }
定时器在软件设计中非常常用,2380提供的库还是很好用。
这里简单说一下,下一节要将的lpt,低功耗定时器,因为例程中需要用到的引脚模块并没有引出,所以这一节的例程就没有改,也没做,需要用到的时候读一下例程应该就会用了,都差不多。