一、TIM输出比较简介
OC(Output Compare)输出比较 //英文直译的英文缩写
输出比较可以通过比较CNT与CCR(捕获比较)寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
每个高级定时器和通用定时器都拥有4个输出比较通道
高级定时器的前3个通道额外拥有死区生成和互补输出的功能
注:智能车 电机驱动用的比较多
注:CNT和CCR比较,形成PWM波
一个定时器有四个输出比较通道,可以同时输出四路PWM波形,有各自的CCR寄存器,但是共用一个CNT寄存器
二、PWM简介
1、解释![](https://i-blog.csdnimg.cn/direct/d36642b1a5894d9e8b2660b5fe26b83f.png)
注:PWM 数字系统等效输出模拟量
占空比=高电平的占用时间/一个周期
2、输出比较模式
注:
匹配时电平翻转模式:翻转两次为一个周期,适用于连续输出一个数
匹配时置有效和匹配时置无效适用于一次性的设置
PWM模式1和PWM模式2是一个相反的状态。
3、PWM参数计算
4、死区生成和互补输出的作用
上路导通:输出高电平
下路导通:输出低电平
死区生成:在上路和下路在导通和断开相互转换的时候延时,以避免造成上路没断干净,下路就导通造成短路的情况发生
5、舵机
舵机内部有直流电机 ,是一个电机执行系统
三、PWM输出比较初始化过程解读
1、初始化模块解释过程
1、初始化过程相关函数解读
①首先开启时钟树,确定时钟树,可以在stm32F10x_rcc.c文件中查看
开启一个GPIO端口的时钟树,我们选择的时GPIOA端口,在APB2上
② 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 = 20000 - 1;
//计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
//预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
//重复计数器,高级定时器才会用到
输出比较初始化:输出比较有专门的一部分初始化模块
-
TIM_OCStructInit(&TIM_OCInitStructure);
这行代码调用
TIM_OCStructInit
函数来初始化一个名为TIM_OCInitStructure
的结构体。这个函数会将结构体的所有成员设置为它们的默认值。这样做的目的是确保即使结构体中某些成员没有在后续的代码中被明确赋值,它们也会有一个确定的起始状态,避免了因未初始化而可能引入的不确定行为。 -
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
这里设置了定时器的输出比较模式为PWM模式1。在PWM模式1下,当计数器的值等于捕获/比较寄存器(CCR)中的值时,输出会切换状态。如果计数器从0开始递增,并且CCR值小于自动重装载寄存器(ARR)的值,那么在CCR值等于计数器值时,输出会从低电平切换到高电平;当计数器值达到ARR值并重新置零时,输出会从高电平切换回低电平。
-
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
设置输出极性为高。这意味着在PWM模式下,当输出应该激活时,输出引脚会变为高电平。如果选择的是低极性,输出引脚在激活时会变成低电平,即输出电平会被取反。
-
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
这一行代码使能了输出。如果不使能输出,即使配置了其他的参数,输出引脚也不会有任何信号。
-
TIM_OCInitStructure.TIM_Pulse = 0;
设置CCR寄存器的初始值为0。在PWM模式下,CCR寄存器的值决定了PWM信号的占空比。初始值设为0意味着PWM信号的初始占空比为0%。
-
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
最后,这行代码将之前配置的
TIM_OCInitStructure
结构体参数应用到TIM2的输出比较通道1上,完成对TIM2 OC1通道的PWM功能配置。
注:重复计数器的作用是重复进行几次计数才会触发中断模式
2、初始化过程图例
3、初始化代码示例
void PWM_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO重映射*/
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO的时钟,重映射必须先开启AFIO的时钟
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); //将TIM2的引脚部分重映射,具体的映射方案需查看参考手册
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //将JTAG引脚失能,作为普通GPIO引脚使用
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为复用推挽输出
//受外设控制的引脚,均需要配置为复用模式
/*配置时钟源*/
TIM_InternalClockConfig(TIM2); //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
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的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
/*输出比较初始化*/
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 = 0; //初始的CCR值
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1
/*TIM使能*/
TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行
}