STM32定时器3配置时钟的坑

STMf1的配置TIM3

我用的是原子的F1精英版,配置定时器3的时候出了点问题

问题描述

这里是主函数,在TIM3_Int_Init函数中,4999是重装载值,3599是预分频系数
计算:
如果APB1给TIM的时钟是36M的话,我使用3599预分频之后,那分频之后的频率就是 36M/3600=10K
(因为是从零开始计数,所以计算使用3600,但是代码里面要用3599)也就是说每计一个数用的时间就是1/10K = 0.0001s = 0.1ms.
我现在计数个数是5000个(0~4999),那时间就是 5000*0.1ms = 500 ms ,我让PE5每中断一次就取反一次,所以PE5的高电平时间应该是500,方波周期就是1s,频率为1Hz,
下图就是假设TIM3的时钟是36M的时候,产生的方波
STM32定时器3配置时钟的坑
这很明显就不对,所以虽然TIM是挂在时钟频率为36MHz的APB1总线上,但是最终到定时器的时钟并不是36M

int main(void)
 {		
 
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	TIM3_Int_Init(4999,3599);//10Khz的计数频率,计数到5000为500ms  
   	while(1)
	{
		LED0=0;
		//delay_ms(200);		   
	}	 
}	 

定时器初始化及中断函数

//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


	TIM_Cmd(TIM2, ENABLE);  //使能TIMx					 
}
//定时器3中断服务程序
void TIM2_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
		{
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx更新中断标志 
		LED1=!LED1;
		}
}

如果假设是72M,那么计算的话可以按照上面的来,最终的结果就是2Hz。那上面的那个波形图就是对的。

总的来说就是,定时器3的时钟不等于APB1的时钟

问题解决

我去看了一下那个时钟树,大概就明白了是怎么个回事,放图
STM32定时器3配置时钟的坑

在系统时钟72M进入APB1之后进行了2分频,得到了36M,所以挂在APB1总线上的外设时钟频率是36M,因为分频系数不等于1,所以APB1的36需要进行乘2才进入定时器的时钟。
这是挂在APB1上面的所有外设

#define RCC_APB1Periph_TIM2              ((uint32_t)0x00000001)
#define RCC_APB1Periph_TIM3              ((uint32_t)0x00000002)
#define RCC_APB1Periph_TIM4              ((uint32_t)0x00000004)
#define RCC_APB1Periph_TIM5              ((uint32_t)0x00000008)
#define RCC_APB1Periph_TIM6              ((uint32_t)0x00000010)
#define RCC_APB1Periph_TIM7              ((uint32_t)0x00000020)
#define RCC_APB1Periph_TIM12             ((uint32_t)0x00000040)
#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)
#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)
#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)
#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)
#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)
#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)
#define RCC_APB1Periph_USART3            ((uint32_t)0x00040000)
#define RCC_APB1Periph_UART4             ((uint32_t)0x00080000)
#define RCC_APB1Periph_UART5             ((uint32_t)0x00100000)
#define RCC_APB1Periph_I2C1              ((uint32_t)0x00200000)
#define RCC_APB1Periph_I2C2              ((uint32_t)0x00400000)
#define RCC_APB1Periph_USB               ((uint32_t)0x00800000)
#define RCC_APB1Periph_CAN1              ((uint32_t)0x02000000)
#define RCC_APB1Periph_CAN2              ((uint32_t)0x04000000)
#define RCC_APB1Periph_BKP               ((uint32_t)0x08000000)
#define RCC_APB1Periph_PWR               ((uint32_t)0x10000000)
#define RCC_APB1Periph_DAC               ((uint32_t)0x20000000)
#define RCC_APB1Periph_CEC               ((uint32_t)0x40000000)

总结

虽然不知道系统在那里设置了乘2的操作,但是现在我就是只知道这样子去用,以后配置的时候都按照72M的时钟去配置定时器。

上一篇:tim不能改变消息记录文件夹解决,提示你没有权限在此写入数据


下一篇:BZOJ3004: 吊灯(结论 毒瘤)