目录
一、概述
主要介绍通用定时器输出比较功能,在GPIO口输出PWM来控制舵机旋转角度和直流电机的转速。调节PWM波,有三个参数:①PWM频率;②占空比;③分辨率。
二、PWM简单介绍
PWM之前在51单片机中学习过,它相当于D/A转换器,把单片机输出的数字量通过调节PWM的占空比可以模拟出模拟量。常用于电机调速
- PWM(Pulse Width Modulation)脉冲宽度调制
- 在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
- PWM参数: 频率 = 1 / TS 占空比 = TON / TS 分辨率 = 占空比变化步距
三、通用定时器输出比较
3.1 输出比较简介
- OC(Output Compare)输出比较
- 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
- 每个高级定时器和通用定时器都拥有4个输出比较通道
- 高级定时器的前3个通道额外拥有死区生成和互补输出的功能
3.2 输出比较通道
- 输出模式选择:确定ref信号。
- 极性选择。高极性ref不变,低极性ref高低电平取反。
- 输出使能。
输出比较模式:
模式 | 描述 |
冻结 | CNT=CCR时,REF保持为原状态 |
匹配时置有效电平 | CNT=CCR时,REF置有效电平 |
匹配时置无效电平 | CNT=CCR时,REF置无效电平 |
匹配时电平翻转 | CNT=CCR时,REF电平翻转 |
强制为无效电平 | CNT与CCR无效,REF强制为无效电平 |
强制为有效电平 | CNT与CCR无效,REF强制为有效电平 |
PWM模式1 | 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平 |
PWM模式2 | 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平 向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平 |
3.3 产生PWM的过程
- 使能TIM2时钟。
- 选择进入时基单元的时钟(内部时钟)。
- 初始化时基单元。
- 初始化输出比较单元,包括输出模式选择、极性选择和输出使能。
- 使能GPIO时钟。
- 初始化GPIO,记得是复位推挽输出模式,由TIM控制GPIO口的输出。
- 使能TIM2。
四、实验硬件介绍及PWM模块程序
4.1 舵机简介
- 一个PWM周期是20ms。
- 高电平宽度为0.5ms~2.5ms,对应舵机输出轴转角0~180°。
4.2 直流电机及驱动芯片TB6612
TB6612芯片的硬件电路:
4.3 PWM模块驱动程序
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//GPIO复用
// TIM_InternalClockConfig(TIM2);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=100-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=36-1;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCStructInit(&TIM_OCInitStruct);
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse=0;
TIM_OC2Init(TIM2,&TIM_OCInitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_Cmd(TIM2,ENABLE);
}
void TIM_SetCCR(uint16_t CCR)
{
TIM_SetCompare2(TIM2,CCR);
}