stm32标准库开发(四):TIM输出比较
输出比较
输出比较(Output Compare,OC)是通用、高级定时器的一个功能,主要作用是产生高低电平输出,即PWM(Pulse width modulation,脉冲脉宽调制)波。 依赖于三个寄存器,前两个是前文提到的自动重载预装寄存器和计数器CNT,现在多了一种称为捕获/比较寄存器(Capture Compare Register,CCR)。根据CNT和CCR的大小关系,决定输出电平的高低。CCR本身也是影子寄存器。
除了常规的PWM波,还有其他几种工作模式:下表简单认为有效电平为高电平、无效电平为低电平:
最常用的是PWM模式1:假设向上计数时,0——CCR输出高电平,CCR——重载值输出低电平,实现了灵活的占空比。
PWM模式2是PWM模式1的反相;
其余几种模式在特殊场合有用,匹配时电平反转可以输出50%占空比的PWM波形等。
几组公式: 前面用过的分频公式:
占空比也容易理解:
比较少见的是分辨率,PWM的分辨率衡量了每提高计数1,对占空比的影响,例如计数为100,每提高1占空比就提高1%,而如果计数为10000,提高1占空比提高0.01%,对于一些需要精细调制信号的外设比较重要。
PWM波输出
不同PWM设备只是对频率的要求不同,根据频率和占空比进行调制即可,需要分辨率再额外调制。
### PWM驱动LED呼吸灯 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52void PWM_Init_Motor(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //GPIO
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //定时器
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //GPIO复用推挽输出:PA6gpio复用为TIM3_CH1
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM3); //内部时钟
//时基电路
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; //1分频 = 不分频72M
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInitStruct.TIM_Period=100-1; //100kHz计100个数,即1kHz
TIM_TimeBaseInitStruct.TIM_Prescaler=720-1; //100kHz
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0; //仅高级定时器有效:重复计数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
//配置OC比较电路
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1; //PWM模式1:0——CCR输出高电平
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High; //即有效电平就是高电平
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; //OC输出使能
TIM_OCInitStruct.TIM_Pulse=0; //CCR寄存器初始化为0,开始输出低电平,通过额外函数修改灵活调节
TIM_OC1Init(TIM3,&TIM_OCInitStruct);
TIM_Cmd(TIM3,ENABLE);
}
//设置CCR值,占空比=Pulse/TIM_Period+1
void PWM_Set(uint16_t Pulse)
{
TIM_SetCompare3(TIM2,Pulse);
}
//main.c
uint8_t i;
PWM_Init();
while(1){
for(i=0;i<=60;i++){ //逐渐亮:占空比最大60%
PWM_Set(i);
Delay_ms(20); //缓慢变亮
}
for(i=60;i>=1;i--){ //逐渐灭
PWM_Set(i);
Delay_ms(20);//缓慢变暗
}
}
驱动SG90舵机
根据数据手册修改分频和重载,要求20ms周期,0.5ms分辨率,采用72+20000组合每次变化500;
1
2
3
4
5
6
7
8
9
10
11
12
13
14TIM_TimeBaseInitStruct.TIM_Period=20000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;
//main.c
Servo_Init();
uint16_t i;
while(1){
for(i=500;i<=2500;i+=500) //0.5ms——2.5ms,每次变化0.5,对应0、45、90、135、180五个角度;
{PWM_Set(i);
Delay_ms(1000); //1s更新一次方向
if(i>2500) //复位
i=500;
}
}
驱动直流电机
普通的电机对频率没有要求,但如果落在人耳频率可能会发出短鸣声,因此应该适当提高输出频率,重要控制占空比即可。
1
2TIM_TimeBaseInitStruct.TIM_Period=100-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;