Cortex-m0之DualTimers定时器
Posted annabelle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cortex-m0之DualTimers定时器相关的知识,希望对你有一定的参考价值。
1. DualTimers简介
cortex m0是ARM公司推出的一款小型低功耗处理器,集成了dualtimers双定时器。
dualtimers是挂在APB总线上的从外设,有如下特性:
- 可配置16位或32位计数器,采用向下计数的方式
- 支持1/16/256分频
- 每个定时器有独立的使能信号
- 三种定时模式:单次计时one-shot,周期计时periodic,自由运行模式free-running
- 周期装载寄存器period load register和后台装载寄存器background load register
2. DualTimers特性
2.1 三种定时模式
dualtimers有三种计时模式,分别是
1. 自由运行模式:从最大值向下计数,每计到0就产生一次中断,不断循环。
2.周期计时模式:从重装载值向下计数,每计到0就产生一次中断,不断循环。重装载值可在定时器初始化时进行配置。如果在counter正常计数时配置重装载值,那么counter会立即从重装载值重新向下计数。
3.单次计时模式:计数器只产生一次中断,计数器向下计到0时就会停止。
2.2 16bit或32bit宽度counter计数器
计数器counter可选16bit宽度或32bit宽度
2.3 定时器分频
配置寄存器:control register [3:2] TimerPre
定时器支持1分频,16分频和256分频。
一般微秒、毫秒、秒级的延时,完全可以使用1分频作为分频因子,且更加准确。
由于这里使用的系统时钟是50MHz,希望产生1秒中的时间间隔,只需要将分频模式设为1分频,装载值设为50M即可。
2.4 装载值和当前值
定时器采用的是向下计数的方式,因此配置装载值后,计时器从装载值向下计数直至计至0并产生中断。
在周期定时模式下,计至0后会重新从装载值向下计数并循环往复。
对装载寄存器Load Register写值,能够直接将向下计数的counter重设到新装载值(也就是说如果上次计数还没有计到0,这一修改就使得上次计数还没有进入中断就重新计数)。
如果对后台装载寄存器Background Load Register写值,则不会立即修改counter,而是counter向下计数至0后开始下一次计数时,从后台装载寄存器的值开始计时。
3. 配置寄存器
DualTimers控制较为简单,寄存器较少。
TIMER1LOAD 装载寄存器。向这一寄存器写入装载值。
TIMER1VALUE 当前值寄存器,可从这一寄存器将counter当前的值读出来。
TIMER1CONTROL 控制寄存器。用于初始化过程中的定时器配置
TIMER1INTCLR 中断清除寄存器。向这一寄存器写入任何值将清除中断
TIMER1RIS 原始中断寄存器。未经过屏蔽的原始中断
TIMER1MIS 中断状态寄存器。判断中断是否产生
TIMER1BGLOAD 后台装载寄存器。区别于装载寄存器,向这一寄存器写装载值,在counter下次向下计数时进行装载,而不会立即打断本次计数。
3.1 控制寄存器
配置三种定时模式的寄存器为控制寄存器control register
Bits | 名称 | 描述 |
[31:8] | - | 保留 |
[7] |
Timer Enable 定时器使能 |
0 失能(缺省) 1 使能 |
[6] |
Timer Mode 定时器模式 |
0 free-running自由运行模式(缺省) 1 periodic周期定时模式 |
[5] |
Interrupt Enable 中断使能 |
0 中断失能 1 中断使能(缺省) |
[4] |
- |
保留 |
[3:2] |
TimerPre 定时器预分频 |
00 1分频(缺省) 01 16分频 10 256分频 |
[1] |
Timer Size
|
0 16-bit宽度计数器(缺省) 1 32-bit宽度计数器 |
[0] |
One-shot Count 单次计数模式 |
0 循环模式(缺省) 1 单次计数模式 |
3.2 中断相关寄存器
M0的DualTimers在count向下计至0时出发中断。
其中需要在初始化时在控制寄存器中使能中断,产生中断后在中断服务程序中将中断清除,并执行相应操作。
Interrup Clear Register 对其进行写入操作将清除中断。
Raw Interrupt Status Register 原始中断状态寄存器。
Interrupt Status Register 中断状态寄存器。
4. DualTimers使用示例
使用过程中,和M3定时器配置大体一致。
在程序运行时首先对其进行初始化配置。
如:将TIM1配置成循环计数,这样每当counter向下计数至0时,就会产生一次中断,并从重装载值继续向下计数,循环往复。
void TIM1_Config( void ) TIM_InitTypeDef Time_InitStruct; Time_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//1分频 Time_InitStruct.TIM_CounterMode = TIM_Mode_Periodic;//周期计数 Time_InitStruct.TIM_CounterbitWide = TIM_Wide32Bit;//32位宽counter Time_InitStruct.TIM_Period = 1000;//重装载值 TIM_Init(CMSDK_TIMER1,&Time_InitStruct); TIM_CmdEnable(CMSDK_TIMER1,ENABLE);//使能定时器 TIM_ITCmdEnable(CMSDK_TIMER1,ENABLE);//TIM中断使能 NVIC_ClearPendingIRQ(DUALTIMER_IRQn); NVIC_EnableIRQ(DUALTIMER_IRQn);
将TIM0配置成单次计数,可以用于延时函数,如delay_ms()
void TIM0_Config( void ) TIM_InitTypeDef Time_InitStruct; Time_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//1分频 Time_InitStruct.TIM_CounterMode = TIM_Mode_OneShort;//单次计数 Time_InitStruct.TIM_CounterMode = TIM_Mode_Periodic; Time_InitStruct.TIM_CounterbitWide = TIM_Wide32Bit; Time_InitStruct.TIM_Period = 1000;//重装载值 TIM_Init(CMSDK_TIMER0,&Time_InitStruct); TIM_CmdEnable(CMSDK_TIMER0,ENABLE);//使能定时器 TIM_ITCmdEnable(CMSDK_TIMER0,ENABLE);//TIM中断使能 NVIC_ClearPendingIRQ(DUALTIMER_IRQn); NVIC_EnableIRQ(DUALTIMER_IRQn);
这样接下来就可以在延时函数中使用TIM0,其中TIM0_delayFlag作为完成一次计时的标志。
系统使用了50MHz时钟,当我们需要1ms的延时时,可以通过一分频,配置重装载值为50_000_000/1000-1
void delay_ms(uint32_t nms) TIM0_delayFlag = 0; TIM_SetLoadValue(CMSDK_TIMER0,nms*50*1000-1); while(TIM0_delayFlag != 1);//等待延时结束
中断服务函数:
void DUALTIMER_HANDLER(void) if((CMSDK_TIMER0->TimerMIS&0x01) == 1)//TIM0中断 TIM0_delayFlag = 1;//用于延时 TIM_ClearITFlag(CMSDK_TIMER0); if((CMSDK_TIMER1->TimerMIS&0x01) == 1)//TIM1中断 TIM_ClearITFlag(CMSDK_TIMER1);
再通过中断使能等操作,定时器就可以正常使用了。
以上是关于Cortex-m0之DualTimers定时器的主要内容,如果未能解决你的问题,请参考以下文章