本笔记基于b站江协科技学习
芯片:stm32F103C8T6
定时器
1.Tim的简介
1)定时器通过对输入时钟进行计数,并在达到特定值时触发中断(定时触发中断)
2)定时器的输出比较功能,产生pwm波形,用于驱动电机等
3)定时器输入捕获功能,测量方波频率
4)定时器编码器接口,读取正交编码器输出
定时器的类型
2.定时器使用内部时钟计时中断
1)打开时钟(根据定时器的总线选择)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//这里使用TIM2
2)选择时钟模式
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
//选择内部时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//ITRX外部时钟模式一
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter);
//TIX外部时钟一
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//ETR外部时钟一
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
//ETR外部时钟二
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//单独配置ETR引脚
3)配置时基单元(16位计数器,自动重装寄存器,预分频器等)
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//分频系数
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//psc预分频器值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值(高级定时器才有)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//初始化TIM2
这里分频系数选择不分频,最大72MHz
* 初始化定时器的时候指定我们预分频系数psc,这里是将我们的系统时钟(72MHz)进行分频
* 然后指定重装载值arr,这个重装载值的意思就是当 我们的定时器的计数值 达到这个arr时,定时器就会重新装载其他值.
例如当我们设置定时器为向上计数时,定时器计数的值等于arr之后就会被清0重新计数
* 定时器计数的值被重装载一次被就是一个更新(Update)
因此时间t = ((arr+1)*(psc+1))/Tclk,这里的话为1s,当到达这个时间就会触发中断。
为什么要这么麻烦?可以更加稳定
PSC决定了计数器计数的速度,ARR则决定了计数的最大值。
如果不设置PSC,在高频时钟下ARR的计数速度会非常快,难以达到较长定时周期。
分频比PSC设置合理,可以让计数速度在一个易控制的范围内。
一般将PSC设置为能让计数周期在1ms到几十ms的范围内。
4)中断输出控制
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除标志位,不然复位后程序从中断处开始
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);打开使能中断
5)配置NVIC,配置中断优先级(类似外部中断)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//指定中断请求通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
6)对TIM2上电
TIM_Cmd(TIM2, ENABLE);
3.定时器使用外部时钟的外部中断
要注意哪个GPIO口对应哪个外部定时时钟
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
//配置外部时钟模式2(对应外部触发预分频器,外部触发极性,外部触发滤波器)
4.定时器的输出比较功能,产生pwm波形,驱动电/舵机
由上图,黄线为ARR,蓝线为CNT(这里是向上计数),红线为CCR(捕获比较寄存器)
PWM的占空比决定模拟电压的大小,频率决定时间,分辨率影响其输出的稳定性
重要部分配置输出比较单元
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//设定一个初始值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式一
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置有效电平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
还有GPIO口的设置,PWM对应io口由定时器来控制
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//设置为复用推挽输出
若想改变CCR的值
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);//CCR
}
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(i);
Delay_ms(10);
}
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(100 - i);
Delay_ms(10);
}
这可以使得CCR的值在0到100来回摆动,以此来达到呼吸灯的目的
舵机的角度
通过PWM时间公式,算出周期20ms(比如:ARR=19999,PSC=71)
PWM_SetCompare2(Angle / 180 * 2000 + 500);//角度转换