把STM32F10X的主频调为72MHz后,为了测试时钟是否配置正确,用定时器生成PWM波,测量PWM波的周期是否与配置的一致。
配置定时器的一般步骤
void TIMER_cfg()配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
1.重新将Timer设置为缺省值
TIM_DeInit(TIM2); -
2.采用内部时钟给TIM2提供时钟源
TIM_InternalClockConfig(TIM2); -
3.预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1; -
4设置时钟分割
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; -
5.设置计数器模式为向上计数模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; -
6.设置计数溢出大小,每计2000个数就产生一个更新事件
TIM_TimeBaseStructure.TIM_Period = 2000 - 1; -
7.将配置应用到TIM2中
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); -
8.清除溢出中断标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update); -
9.禁止ARR预装载缓冲器
TIM_ARRPreloadConfig(TIM2, DISABLE); -
10.开启TIM2的中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
void NVIC_cfg()配置
NVIC_InitTypeDef NVIC_InitStructure;
-
1.选择中断分组1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); -
2.选择TIM2的中断通道
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; -
3.抢占式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; -
4.响应式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; -
5.使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
实际使用的定时器配置
在我使用的框架中实际代码如下:
VOID HwTim_100msEnable()
{
TIM_TimeBaseInitTypeDef INIT = {0};
RCC_ClocksTypeDef Clock;
USHORT Frequency = 0; //hz
TRACESTACK(HwTim_100msEnable);
RCC_GetClocksFreq(&Clock);
TIM_DeInit(TIM7);
//100ms
Frequency = 10;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
INIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1; //APB1时钟分频>1,定时器输入频率*2
INIT.TIM_Prescaler = 1000 - 1;//设置预分频系数,计数器时钟为72MHz/1000 = 72kHz
INIT.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
INIT.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM7, &INIT);
TIM_ClearFlag(TIM7,TIM_FLAG_Update);
TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM7, ENABLE);
HwIrq_Enable(TIM7_IRQn,2,0x03,ENABLE);
return;
}
其中Clock.PCLK1_Frequency为系统时钟的2分频,这种配置方法可移植性非常高,代码简洁明了。
Frequency = 10;
INIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1;
INIT.TIM_Prescaler = 1000 - 1;
如上三行代码配置了100ms的计数值和计数时间。
计数频率 = 系统时钟频率/分频系数 = SYSCLK/INIT.TIM_Prescaler
计数次数 = NIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1;
定时器计时时间 = 单位计数时间 × 计数次数
如果系统时钟为24MHz:
计数次数 = 12M*2/1000/Frequency - 1 = 2.4K
计数频率 = 24M/INIT.TIM_Prescaler = 24k
定时时间 = 计数次数/计数频率 = 0.1S.
如果系统时钟为72MHz
计数次数 = 36M*2/1000/Frequency - 1 = 7.2K
计数频率 = 72M/INIT.TIM_Prescaler = 72k
定时时间 = 计数次数/计数频率 = 0.1S.
这种配置方法及时更改了系统时钟,也不会影响到定时器的配置。
若要配置其他时钟更改计数次数和计数频率即可。
生成的波形如下图所示: