stm32的定时器又多又复杂,但复杂意味着强大吧。我用的是stm32f103ZET6,有2个基本定时器TIM6和TIM7可以用来触发DAC,4个通用定时器TIM2,TIM3,TIM4,TIM5,两个高级定时器TIM1和TIM8,还有两个专用定时器SysTick和RTC。
TIM2,3,4,5,6挂在APB1总线上,TIM1,8挂在APB2总线上,V3.5固件库默认时钟为APB1=36MHz,APB2=72MHz。不过由于对于定时器来说APB1预分频系数为1时频率*2,所以定时器计数时钟TIMXCLK都为72MHz。
通用定时器功能:1、基本时基功能计时。2、输入捕获(可用于测量脉冲周期和占空比)。3、输出比较(四个通道可以当做四个定时器使用)。4、PWM功能。5、正交编码器。
基本定时器:首先也是最重要的当然是定时器的时钟配置了,如果TIMXCLK是72MHz,根据你的需要对时钟进行分频,分频就是对结构体中的两个成员进行赋值,
.TIM_Prescaler //这个成员是预分频,对应一个16位的分频寄存器,也就是说你可以进行1-65536分频。这个分频一般都能满足需求。 .TIM_ClockDivision //这个是分频可能会对,定时器外部计数时的滤波器有影响,所以不用它就行,直接赋值为TIM_CKD_DIV1一分频,就是不分频。因为.TIM_Prescaler这个分频就够用了。
简单定时功能配置方式如下:
void tim2Config(void) //简单定时功能 { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能时钟 TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure); TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInitStructure.TIM_Prescaler = 71; //71+1分频,1MHz周期1us TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;//时钟不分频 TIM_TimeBaseInitStructure.TIM_Period = 1000-1; //溢出周期1000 = 1ms TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开启溢出中断计数到TIM_Period时,发生中断 TIM_Cmd(TIM2, ENABLE); //使能TIM2 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //配置中断向量 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
关于中断向量可以看一下这个博客:http://www.cnblogs.com/dyllove98/archive/2013/08/01/3230973.html
中断函数:
void TIM2_IRQHandler(void) { if( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) //是否为溢出中断 { TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); //清除中断挂起位 } }
这里注意一定要清除中断挂起位,不然会一直中断。
2、PWM模式:
PWM模式理解起来简单其实就是有两个寄存器,一个是周期寄存器,另一个是比较寄存器。周期寄存器控制周期,比较寄存器控制有效电平(是高电平还是低电平由.TIM_OCPolarity_High的值决定)时间。假如向上计数时,计数器寄存器从零计数,计数到达比较寄存器中的值之前一直为有效电平,之后为另一个电平。计数到周期寄存器中的值时,一个周期完成。这样就成了PWM了。
1、配置GPIO模式。2、配置TIM_TimeBaseInitTypeDef结构体。3、配置TIM_OCInitTypeDef结构体。
static void TIM3_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* TIM3 clock enable */ //PCLK1经过2倍频后作为TIM3的时钟源等于72MHz RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* GPIOA and GPIOB clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); /*GPIOA Configuration: TIM3 channel 1 and 2 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*GPIOB Configuration: TIM3 channel 3 and 4 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); } /* * 函数名:TIM3_Mode_Config * 描述 :配置TIM3输出的PWM信号的模式,如周期、极性、占空比 * 输入 :无 * 输出 :无 * 调用 :内部调用 */ static void TIM3_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* PWM信号电平跳变值 */ u16 CCR1_Val = 500; u16 CCR2_Val = 375; u16 CCR3_Val = 250; u16 CCR4_Val = 125; /* ----------------------------------------------------------------------- TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles: TIM3CLK = 72 MHz, Prescaler = 0x0, TIM3 counter clock = 72 MHz TIM3 ARR Register = 999 => TIM3 Frequency = TIM3 counter clock/(ARR + 1) TIM3 Frequency = 72 KHz. TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50% TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5% TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25% TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5% ----------------------------------------------------------------------- */ /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 999; //当定时器从0计数到999,即为1000次,为一个定时周期 TIM_TimeBaseStructure.TIM_Prescaler = 71; //设置预分频:不预分频,即为72MHz TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //设置时钟分频系数:不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //设置跳变值,当计数器计数到这个值时,电平发生跳变 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //当定时器计数值小于CCR1_Val时为高电平 TIM_OC1Init(TIM3, &TIM_OCInitStructure); //使能通道1 TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel2 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR2_Val; //设置通道2的电平跳变值,输出另外一个占空比的PWM TIM_OC2Init(TIM3, &TIM_OCInitStructure); //使能通道2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel3 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR3_Val; //设置通道3的电平跳变值,输出另外一个占空比的PWM TIM_OC3Init(TIM3, &TIM_OCInitStructure); //使能通道3 TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel4 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR4_Val; //设置通道4的电平跳变值,输出另外一个占空比的PWM TIM_OC4Init(TIM3, &TIM_OCInitStructure); //使能通道4 TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3, ENABLE); // 使能TIM3重载寄存器ARR /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); //使能定时器3 } /* * 函数名:TIM3_PWM_Init * 描述 :TIM3 输出PWM信号初始化,只要调用这个函数 * TIM3的四个通道就会有PWM信号输出 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void TIM3_PWM_Init(void) { TIM3_GPIO_Config(); TIM3_Mode_Config(); }
改变PWM占空比,即是改变比较寄存器的值。使用这个函数
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
使用方法简单例如要改变,TIM3通道1的占空比就这样,TIM_SetCompare1(TIM3, 900); 900为新的比较寄存器的值。
工程文件链接timer.c timer.h stm32f10x_it.c