输出比较(OC)简介
·OC (Output Compare) 输出比较
·输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作, 用于输出一定频率和占空比的PWM波形
·每个高级定时器和通用定时器都拥有4个输出比较通道
·高级定时器的前3个通道额外拥有死区生成和互补输出的功能
PWM简介
·PWM (Pulse Width Modulation) 脉冲宽度调制
·在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参 量,常应用于电机控速等领域
·PWM参数:频率=1/Ts 占空比 = Ton/Ts 分辨率 =占空比变化步距
图1
输出比较通道(通用定时器)
图2
输出比较模式
图3
(本文使用的是PWM模式1)
配置PWM的基本结构
图4
可见还是要用到定时器的功能,通过不断比较CCR和CNT的值,在PWM模式1下就能输出PWM波形,通过修改CCR的值,就能产生不同占空比的PWM波形。
下面是关于PWM波形参数的计算公式
图5
初始化配置模板
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//选择复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//选择时基单元的时钟
TIM_InternalClockConfig(TIM2);//选择内部时钟来驱动 可不写 定时器上电默认使用内部时钟
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器计数模式
TIM_TimeBaseInitStructure.TIM_Period=100-1;//给ARR自动重装器赋值(0~65535)
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//给PSC预分频器赋值(0~65535)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器 高级计数器才有 置0
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//配置输出比较单元
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋一个初始值
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出比较模式 PWM模式1
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出比较极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出状态(使能或失能)
TIM_OCInitStructure.TIM_Pulse=50;//设置ccr寄存器的值 x=(0~0xFFFF)
/* 下面这些结构体参数高级定时器才用到
TIM_OCInitStructure.TIM_OCIdleState
TIM_OCInitStructure.TIM_OCNIdleState
TIM_OCInitStructure.TIM_OCNPolarity
TIM_OCInitStructure.TIM_OutputNState*/
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
//启动定时器
TIM_Cmd(TIM2,ENABLE);
这里的ARR=99,PSC=719,CCR=50,那么根据公式可知,输出的是一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形。
注意事项:初始化GPIO口时输出模式要设置为复用推挽输出,即GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;(对于普通的开漏/推挽输出,引脚的控制权是来自于输出数据寄存器的,如果想让定时器控制引脚,就需要使用复用开漏/推挽输出,这时输出数据寄存器被断开,输出控制权转移给片上外设,这里片上外设的引脚连接的是TIM2的CH1通道)
内部定时器配置和之前一样,主要是配置输出比较单元
TIM_OCMode对应图3里的输出比较模式
TIM_OCPolarity设置有效电平为高电平或低电平,一般设置为高电平
*这里用到了一个之前见过类似但没有用过的函数TIM_OCStructInit(&TIM_OCInitStructure);
它的作用是给结构体赋一个默认值,我之前就在想,配置结构体时我们都是把所有参数列出来,然后一一转到定义去配置,不明白这个函数有什么作用,但是模板里有些结构体参数是没有用到的,只有高级定时器才需要配置,但我们不去配置它们,程序可能会出错,所以在配置需要用到的参数之前,调用这个函数,再去配置我们需要用到的参数,这个函数就是这样用的。
最后打开通道1,即可在对应GPIO口输出PWM波形
图6
上图是定时器通道与引脚的对应关系,通用定时器有四个输出比较通道,我们选择打通CH1,即 TIM_OC1Init(TIM2,&TIM_OCInitStructure);函数,再初始化PA0引脚,那么在PA0引脚就能输出PWM波形。
重要函数
TIM_OC1Init,TIM_OC2Init,TIM_OC3Init,TIM_OC4Init
上面这四个函数分别对应输出比较的四个通道,用于配置输出比较模块
TIM_OCStructInit,给结构体赋一个默认值
TIM_SetCompare1,TIM_SetCompare2,TIM_SetCompare3,TIM_SetCompare4
上面这四个函数是用来单独给CCR赋值的,一般用上面四个函数来输出任意占空比的PWM波形
补充说明:TIM_CtrlPWMOutputs,在使用高级定时器输出PWM时,需要调用这个函数,使能主输出否则PWM将不能正常输出!!!
附:直流电机驱动模块
·直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作
·TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向
图7
上图是TB6612的引脚图,VM需接5V电压,不能用GPIO口置高电平
PWM控制启停,IN1和IN2控制正反转,可见右下角的真值表