目录
一、概念
二、输出比较的8种模式
三、输出比较输出PWM波形的基本结构
配置步骤
四、示例代码
一、概念
OC(OutPut Compare)输出比较。输出比较可以通过比较CNT与CCR寄存器的关系,来对输出电平进行置1/置0/翻转的操作,可以用来输出一定频率和一定占空比的PWM波形。
虽然手册中他的名字是输出比较,但是我更喜欢称他为比较输出,因为他是用CNT和CCR的值进行比较,然后再输出高低电平/翻转电平的。
每一个高级定时器和通用寄存器都拥有4个输出比较通道:这意味着同一时刻,可以有4路IO口进行独立的输出比较操作,即每一路比较都可以根据CNT(计数器)与CCR(捕获比较寄存器)的值进行,从而控制对应的输出电平。如果每一路的CCR寄存器中写的值都不一样,那么这4路与CNT比较后,会有多种不一样的效果。
通用定时器框图
高级定时器框图
二、输出比较的8种模式
上图是4个输出比较通道的其中一个:可以看到本质就是开启TIM定时器,让TIM定时器不断++,其当前的数值是暂时存储在CNT寄存器中,然后我们对CCR寄存器设置一个初始值,随着TIM不断运行,CCR寄存器和CNT寄存器里面的值会不断比较,一旦符合了条件,就会向外部输出高/低/翻转电平。
三、输出比较输出PWM波形的基本结构
PWM的基本结构就是由之前的内部时钟中断,去掉了后面的中断部分,然后替换称为了输出比较部分。
配置步骤
- 初始化系统时钟。(图左边部分)
- 配置GPIO:将定时器输出引脚配置为复用推挽输出模式。(因为我们要输出PWM波形,肯定要有一个GPIO口作为输出比较的出口)。复用推挽模式和普通推挽模式有什么区别呢?普通推挽模式的GPIO口的电平状态完全由CPU来控制,而复用推挽模式的GPIO口电平是由外设来控制,在这里是输出比较模块来控制(相当于CPU放弃对GPIO口电平状态的控制,由外设全权负责)
- 配置定时器:(图右边部分)
- 定时器时钟源。
- 预分频器。
- 自动重装载寄存器(ARR)。
- 输出比较模式(PWM模式)。
- 捕获/比较寄存器(CCR)。
下图是STM32的TIM2的输出比较通道连接的GPIO口PA0的查看
四、示例代码
// 使能GPIOA和TIM2的时钟(一个用来定时,一个用来输出)
void RCC_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
/*配置时钟源TIM2为内部时钟源*/
TIM_InternalClockConfig(TIM2);
}
// 配置PA0 (TIM2_CH1) 为复用推挽输出模式
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//配置TIM2为输出比较,用来输出PWM波形
void TIM2_PWM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置TIM2的时间基单元
TIM_TimeBaseStructure.TIM_Period = 1000-1; // 设置PWM周期 (ARR寄存器的值)
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 设置预分频器 (PSC寄存器的值)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置TIM2的输出比较通道1 (PWM模式1)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能输出
TIM_OCInitStructure.TIM_Pulse = 499; // 设置PWM占空比 (CCR寄存器的值)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 设置输出极性为高
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
// 使能TIM2的预装载寄存器
TIM_ARRPreloadConfig(TIM2, ENABLE);
//使能TIM2,定时器开始运行
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare); //设置CCR1的值
}