一.输出比较原理

1.输出比较
通过定时器的外部引脚对外输出控制信号,将通道X(x=1,2,3,4)通常设置为PWM1、PWM2模式。
2.比较寄存器
当计数器CNT 和比较寄存器CCR 的值相等时,输出参考信号OCxREF的信号的极性发生改变,其中OCxREF=1(高电平)称为有效电平,OCxREF=0(低电平)称为无效电平,并且产生比较中断CCxI ,相应的标志位CCxIF会置位。
OCxREF再经过一系列的控制之后成为真正的输出信号OCx/OCxN。
3.输出引脚
输出比较的输出信号最终通过定时器的外部IO输出,分别为CH1/2/3/4 ,以及互补输出通道CH1/2/3N。
二.PWM输出模式
1.PWM输出
对外输出脉宽(即占空比)可调的方波信号。
2.信号频率
由自动重装载寄存器ARR 的值决定,PWM频率 = TIM_CLK/{(PSC+1)(ARR+1)}。
3.占空比
由比较寄存器CCR 的值决定,占空比=CCR/(ARR+1)。
4.常用的值
TIM_CLK:72MHZ;ARR:自动装载寄存器的值 ;CCR: 比较寄存器; PSC:计数器时钟分频因子。
5.PWM边沿对齐模式

在递增计数模式下,计数器从0计数到自动装载寄存器的值(ARR),然后重新从0开始计数并生成计数器上溢事件。
上图中,ARR=8,CCR=4,CNT从0开始计数,使用递增模式。
CNT<CCR 时,OCxREF为有效的高电平。
CCR=<CCR<=ARR 时,OCxREF为无效的低电平。
之后,CNT从0开始计数并生成计数器上溢事件,以此循环往复。
二.输出比较初始化结构体
c
typedef struct {
uint16_t TIM_OCMode; // 比较输出模式
uint16_t TIM_OutputState; // 比较输出使能
uint16_t TIM_OutputNState; // 比较互补输出使能
uint32_t TIM_Pulse; // 脉冲宽度
uint16_t TIM_OCPolarity; // 输出极性
uint16_t TIM_OCNPolarity; // 互补输出极性
uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态
uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;;
(1)IM_OCMode :比较输出模式选择,总共有八种,常用的为 PWM1/PWM2,即TIM_OCMode_PWM1/TIM_OCMode_PWM2。
(2)TIM_OutputState :比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出,即TIM_OutputState_Enable。
(3)TIM_OutputNState: 比较互补输出使能,决定 OCx 的互补信号 OCxN 是否通过外部引脚输出。
(4)TIM_Pulse :比较输出脉冲宽度,实际设定比较寄存器 CCR 的值,决定脉冲宽度 。可设置范围为 0 至 65535。
(5)TIM_OCPolarity :比较输出极性,可选 OCx 为高电平有效或低电平有效,它决定着定时器通道有效电平。即:TIM_OCPolarity_High/TIM_OCPolarity_LOW
HIGH:CNT< CCR(比较寄存器) 时,定时器通道CH输出高电平;
LOW:CNT< CCR(比较寄存器) 时, 定时器通道CH输出低电平。
(6)TIM_OCNPolarity:比较互补输出极性,可选 OCxN 为高电平有效或低电平有效。
(7)TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出 1 或输出 0。
(8)TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出 1 或输出 0
三.源代码
1.bsp_generalpwm.h
c
#ifndef BSP_GENERAL_PWM_H
#define BSP_GENERAL_PWM_H
#include "stm32f10x.h"
void INIT_GENERAL_GPIO_CONFIG();
void INIT_GENERAL_PWM_CONFIG();
#endif
2.bsp_generalpwm.c
c
#include "bsp_generalpwm.h"
//使用TIM3的 输出比较通道1,2,3,4 对应的GPIO初始化
void INIT_GENERAL_GPIO_CONFIG()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//PA6 PA7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//推免输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PB0 PB1
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/* ---------------- PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)
void INIT_GENERAL_PWM_CONFIG()
{
//初始化 TIM_TimeBaseInitTypeDef
//开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//72MHZ/((72-1)+1) = 1MHZ 分频因子
TIM_TimeBaseInitStructure.TIM_Period = 9-1;//重载寄存器的值
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
//占空比设置
uint8_t OC1_VALUE = 8;
uint8_t OC2_VALUE = 5;
uint8_t OC3_VALUE = 4;
uint8_t OC4_VALUE = 2;
//初始化 TIM_OCInitTypeDef
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//使用PWM1模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出通道电平极性 高电平有效;CNT< CCR(比较寄存器) 时,定时器通道CH输出高电平;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse = OC1_VALUE;//占空比:TIM_Pulse/(Period +1)
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_Pulse = OC2_VALUE;
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_Pulse = OC3_VALUE;
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_Pulse = OC4_VALUE;
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
//使能计数器
TIM_Cmd(TIM3,ENABLE);
}
3.man.c
c
#include "bsp_generalpwm.h"
int main(void)
{
INIT_GENERAL_GPIO_CONFIG();
INIT_GENERAL_PWM_CONFIG();
while(1)
{
}
}