目标
使用PWM驱动舵机,直流电机,呼吸灯
输出比较OC(OutputCompare)
- 输出比较可以通过比较CNT与RCC寄存器值的关系,来对输出电平进行置0,1或翻转的操作,用于输出一定频率和占空比的PWM波形
- 每个高级定时器和通用定时器都有4个输出比较通道(同时生成4个PWM波,CNT共用,但CCR各有各的值)
- 高级定时器的前三个通道额外拥有死区生成和互补输出功能(驱动三相无刷电机)
CNT----计数的值,
CCR(R-register寄存器)----捕获-比较寄存器,当使用输出比较时,就是输出比较寄存器,使用输入捕获时,就是输入捕获寄存器
输出比较时:
比较CNT和CCR的值,CNT自增,CCR是我们给定的值.当CNT > CCR CNT == CCR CNT < CCR时,就会置1,0,1,0
PWM波
输出的是数字信号(也就是0101)PWM就是用数字量模拟模拟信号,比如对于LED灯,我们让它亮、灭、亮、灭,频率足够大时,它看起来就是一个中等亮度。我们调控通电、断电的时间比,就可以控制亮度。
一定要在惯性系统中。比如人眼有视觉暂留,LED灭后不会立即灭。PWM就是利用这种“惯性”。
上图中左图的黑线是输出的电平(数字信号),紫色线是它等效的模拟信号。TS是输出的变化周期,周期的倒数即频率(频率=1/Ts),频率越大,模拟效果越好,占空比:高电平时间占一个周期的百分比(占空比越大,等效输出越趋近于高电平的电压)占空比变化时有一个间距(如以1%为步距变化,就是1%,2%,1%。。。这个变化的间距,就是分辨率,表示PWM波变化的细腻程度)
输出比较通道(通用)
左边是在比较,比较的结果输出到REF(reference)。CC1P上面这里写0不翻转,写1翻转(输入1输出0)输出使能这里是看看是不是要输出
左边比较的模式(可简单理解无效电平为低电平,有效电平为高电平):
强制输出模式:想暂停PWM输出时可以考虑
PWM模式:输出频率和占空比都可调的PWM波,一般使用向上计数。模式2可看作模式1的取反
上图蓝线是CNT值,黄线是ARR值,CNT自增,到ARR后清零。CCR是红线,CNT小于CCR,输出高电平,大于CCR,输出低电平(CCR越高,占空比越大)PWM的一个周期=计数器溢出周期
CNT从0~29是高电平,一个周期计100个数(0~99)
CCR的值可以在0~ARR中,所以分辨率是上面的公式
舵机简介
此处舵机是SG90,有三根输入线,两根电源线,一根信号线。轴会固定在某个角度,这个角度是由PWM波控制的。电位器会检测角度,大于输入角度就反转。可理解为PWM成为了一种通信协议。
注意:电机是大功率设备,最好单独供电
直流电机
H桥可以控制电流方向,O1,O2这里接一个电机,左右是两路推挽输出
VM这里的要求同上,要一个能接大电流的电源 ,这里电压要与额定电压一样。
有三个GND,随便选一个接
PWMA,AIN1,AIN2控制AO1,AO2的电机,PWMA,AIN1,AIN2输出低功率到AO1,AO2,这样AO1,AO2就会从VM汲取电流控制电机。
STBY这里接3.3V正常工作,接地进入待机模式(接GPIO,给高低电平也能控制)
反转:IN1给低,IN2给高,PWM高转低不转
正转:IN1给高,IN2给低,PWM高转低不转
接线
程序部分
PWM波驱动
打通硬件电路即可
分别配置四个输出比较单元OC(output compare)
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
强制输出配置
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
更改CCR寄存器值(和CNT计数值比较的那个值,可以调占空比)
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);
先到这了,下期再分享程序部分~