热度 16
2014-8-14 10:29
2459 次阅读|
1 个评论
1.1 TIM1_CH1N 与 TIM1_CH1 的区别 在刚准备使用定时器的时候,我看了下原理图,发现对于定时器1,它的每一个输出通道都是成对的,即TIM1_CH1N与TIM1_CH1两个一组,通过网络查询后,明白了芯片这样设计的原因。 TIM1是一个完整的电机控制用定时器外设,TIM1_CH1和TIM1_CH1N,用于驱动上下两个功率管。如果Deadtime为0,则 TIM1_CH1N是TIM1_CH1的反相,如果Deadtime不为0,则在TIM1_CH1N上插入了Deadtime,防止上下功率管同时导通。 另外的两类管脚定义: TIM1_ETR是外部触发输入管脚; TIM1_BKIN是故障信号,用来关闭TIM1的输出。 1.2 定时器的配置及 PWM 的设置 1.2.1 定时器相关结构体 从固件库里的教程CHM获取到的定时器相关的结构体。 TIM_BDTRInitTypeDef BDTR structure definition TIM_ICInitTypeDef TIM Input Capture Init structure definition TIM_OCInitTypeDef TIM Output Compare Init structure definition TIM_TimeBaseInitTypeDef TIM Time Base Init structure definition TIM_TypeDef TIM 其中与PWM输出有关的结构体主要为: TIM_TimeBaseInitTypeDef:定时器初始化配置结构体 TIM_OCInitTypeDef:定时器输出比较结构体 1.2.2 定时器的三个速度 在刚开始学习定时器的时候,我对定时器的速度、技术速度都很迷糊,通过前面对STM32时钟系统的学习,以及RCC库里面几个函数的学习,总算明白了,定时器的这三个速度。 TIMxCLK(定时器的工作频率):这个频率是我们在RCC里面配置APB1或APB2总线时的频率。 TIMx Counter Clock(定时器的计数频率):这个频率是定时器对ARR寄存器内的值进行加数或是减数的速度。 以前在做51单片机编程的时候,这两个频率往往是一致的。所以,刚开始对这两个频率的理解上还是有点疑惑的。 TIMx Running @(定时器的作用频率):这个频率表示定时器在这一次ARR寄存器开始累加或递减到下一次ARR寄存器重装所用的时间,这个频率可以理解为在以前的51单片机内我们定时器的定时周期。 对以上三个频率理解清楚后,再对定时器进行初始化的配置就很清晰了。 1.2.3 定时器的配置 定时器的配置代码 // Compute the prescaler value / //TIM3CLK is 72 MHz //TIM3 Counter Clock is 24 MHz //TIM3 is running at 1 KHz PrescalerValue = (unsigned int) (72000000 / 36000000) - 1; PeriodValue = (unsigned int)( 36000000 / 1000 ) - 1; 三个频率的设置:定时器工作频率为72MHz,定时器计数频率36MHz,定时周期1KHz,通过这三个值,计算PrescalerValue 及PeriodValue的值。为后面的结构体配置做准备。 关于定时器的工作频率为72MHz,这是我在网上查到的一个小经验,我在DATASHEET中没有找到相关的说明,最后的PWM频率说明这个小经验是正确的。网上提到分给APB1的频率,即提供给TIM3的定时器的工作频率会自动倍频。 RCC_PCLK1Config(RCC_HCLK_Div2);//设置APB1时钟 我在前面配置给APB1的时钟是系统时钟二分频,即36MHz,而网上提到的倍频,即提供定时器的工作频率其实还是72MHz,最后证明TIM3工作频率的确是倍频了,对其他的定时器没有验证,我猜测挂载在APB1上的定时器都具有倍频的功能,即同样定时器的工作频率都经过了倍频。 // Time base configuration / TIM_TimeBaseStructure.TIM_Period = PeriodValue; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); TIM_Period及 TIM_Prescaler的值通过前面的计算已经确定。其中TIM_Prescaler是确定定时器技术频率,TIM_Period是确定定时周期的。 // PWM1 Mode configuration: Channel1 / CCR_Val = (unsigned int) (PeriodValue / 2 ) ; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//选择第二个通道输出 TIM_OC2Init(TIM3, TIM_OCInitStructure); //选择第二个通道输出 以上是输出比较结构体的配置,他最后决定了PWM的参数,PWM的频率即前面的定时器定时周期。而占空比是由TIM_Pulse确定的。其中占空比公式为: DUTY = CCR寄存器的值 / ARR寄存器的值 DUTY = TIM_OCInitStructure.TIM_Pulse / TIM_TimeBaseStructure.TIM_Prescaler-1 //TIM3-CCER = 0xEEEF; // TIM3 enable counter TIM_ARRPreloadConfig(TIM3, ENABLE); TIM_Cmd(TIM3, ENABLE); TIM_CtrlPWMOutputs(TIM3,ENABLE); 定时器的最后使能配置。至此,有关定时器相关的结构体的配置就结束了。在配置完GPIO后就可以输出PWM波了。实际上,程序流程上是先配置GPIO的,但我在学习PWM时,在GPIO上花费了大量的时间,也对GPIO理解更加深刻了。