本文内容:熟悉脉冲宽度调制 (PWM) 和数模 / 模数转换原理用 STM32F103 输出一路 PWM 波形,建议采用定时器方法,用示波器观察输出波形。
一、PWM 简述
1)PWM 简介:
- 脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或 MOS 管栅极的偏置,来实现晶体管或 MOS 管导通时间的改变,从而实现开关稳压电源输出的改变。
- 这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。
- 脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
2)PWM 控制的基本原理:
- 冲量相等而开头不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。其中冲量指窄脉冲的面积;效果相同指环节输出响应波形基本相同。
- 用一系列等幅不等宽的脉冲来代替一个正弦半波。

- 其划分方式是将正弦半波分成 N 等分,可看成 N 个彼此相连的脉冲序列,宽度相等,但幅值不等;接下来使用矩形脉冲代替,而各个矩形脉冲等幅,不等宽,中点与脉冲序列重合,脉冲宽度按正弦规律变化,脉冲的总面积(冲量)与正弦半波相等。这个脉冲波形被称为 SPWM 波形,是一种极其典型的 PWM 波形。
二、定时器实现 PWM 波形输出
1)PWM 工作过程
- 寄存器的值从 0 开始到 ARR 值的过程中:
- 当其比 CCRx 中的值小的时候,输出低电平(0);
- 当其值大于 CCRx 值时,输出高电平(1)。
- 从图中可以看出周期是由 ARR 决定的,跟定时器的时钟有关系,而占空比则跟 CCRx 有关。

2)PWM 通道
- 捕获/比较通道的输出部分(通道1):

①CCR1寄存器:捕获/比较值寄存器:设置比较值;
②CCMR1寄存器:OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1或者PWM模式2;
③CCER寄存器:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。
④CCER寄存器:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。
PWM输出的模式区别:
通过设置寄存器 TIMx_CCMR1 的 OC1M[2:0] 位来确定 PWM 的输出模式:
- PWM 模式1:
①在向上计数时,一旦 TIMx_CNT
②在向下计数时,一旦 TIMx_CNT>TIMx_CCR1 时通道 1 为无效电平 (OC1REF=0),否则为有效电平 (OC1REF=1)。
- PWM 模式2:
①在向上计数时,一旦 TIMx_CNT
②在向下计数时,一旦 TIMx_CNT>TIMx_CCR1 时通道 1 为有效电平,否则为无效电平。
- 注意:并未说明 1 就表示有效电平
3)定时器3的输出通道引脚
- TIM3_CH1:PA6,完全重映像PC6
- TIM3_CH2:PA7,完全重映像PC7
- TIM3_CH3:PB0,完全重映像PC8
- TIM3_CH4:PB1,完全重映像PC9
4)相关配置
- 捕获/比较模式寄存器1(TIMx_CCMR1):
在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作。
- 捕获/比较使能寄存器(TIMx_CCER):
在PWM输出模式下,确定PWM的输出极性和输出使能。
- 捕获/比较寄存器1(TIMx_CCR1):
在PWM输出模式下,确定比较的值。
三、keil5 实现输出 PWM 波形
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1,引脚是PA8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
while(1)
{
delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare1(TIM1,led0pwmval);//设置不同的占空比
}
}
- 烧录后,可以看到 STM32 板子上的 LED 灯由亮变暗的过程。
- 利用 keil 仿真查看输出的波形如下:

- 从上图中可以发现该过程的占空比是逐渐在发送变化。
- 通过示波器可以观察到其波形如下:

四、总结
- 通过输出的波形,可以观察到输出的占空比是发生变化,而 PWM 的原理就是通过占空比的改变来表示波形,采用示波器可以清楚的观察到占空比的改变,而 keil 的仿真不是特别的明显,当然也可以利用库函数提供的函数,实现改变频率,从而改变 LED 的亮度情况,实现 LED 闪烁的多样变化。
本文内容:熟悉脉冲宽度调制 (PWM) 和数模 / 模数转换原理用 STM32F103 输出一路 PWM 波形,建议采用定时器方法,用示波器观察输出波形。
一、PWM 简述
1)PWM 简介:
- 脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或 MOS 管栅极的偏置,来实现晶体管或 MOS 管导通时间的改变,从而实现开关稳压电源输出的改变。
- 这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。
- 脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
2)PWM 控制的基本原理:
- 冲量相等而开头不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。其中冲量指窄脉冲的面积;效果相同指环节输出响应波形基本相同。
- 用一系列等幅不等宽的脉冲来代替一个正弦半波。

- 其划分方式是将正弦半波分成 N 等分,可看成 N 个彼此相连的脉冲序列,宽度相等,但幅值不等;接下来使用矩形脉冲代替,而各个矩形脉冲等幅,不等宽,中点与脉冲序列重合,脉冲宽度按正弦规律变化,脉冲的总面积(冲量)与正弦半波相等。这个脉冲波形被称为 SPWM 波形,是一种极其典型的 PWM 波形。
二、定时器实现 PWM 波形输出
1)PWM 工作过程
- 寄存器的值从 0 开始到 ARR 值的过程中:
- 当其比 CCRx 中的值小的时候,输出低电平(0);
- 当其值大于 CCRx 值时,输出高电平(1)。
- 从图中可以看出周期是由 ARR 决定的,跟定时器的时钟有关系,而占空比则跟 CCRx 有关。

2)PWM 通道
- 捕获/比较通道的输出部分(通道1):

①CCR1寄存器:捕获/比较值寄存器:设置比较值;
②CCMR1寄存器:OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1或者PWM模式2;
③CCER寄存器:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。
④CCER寄存器:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。
PWM输出的模式区别:
通过设置寄存器 TIMx_CCMR1 的 OC1M[2:0] 位来确定 PWM 的输出模式:
- PWM 模式1:
①在向上计数时,一旦 TIMx_CNT
②在向下计数时,一旦 TIMx_CNT>TIMx_CCR1 时通道 1 为无效电平 (OC1REF=0),否则为有效电平 (OC1REF=1)。
- PWM 模式2:
①在向上计数时,一旦 TIMx_CNT
②在向下计数时,一旦 TIMx_CNT>TIMx_CCR1 时通道 1 为有效电平,否则为无效电平。
- 注意:并未说明 1 就表示有效电平
3)定时器3的输出通道引脚
- TIM3_CH1:PA6,完全重映像PC6
- TIM3_CH2:PA7,完全重映像PC7
- TIM3_CH3:PB0,完全重映像PC8
- TIM3_CH4:PB1,完全重映像PC9
4)相关配置
- 捕获/比较模式寄存器1(TIMx_CCMR1):
在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作。
- 捕获/比较使能寄存器(TIMx_CCER):
在PWM输出模式下,确定PWM的输出极性和输出使能。
- 捕获/比较寄存器1(TIMx_CCR1):
在PWM输出模式下,确定比较的值。
三、keil5 实现输出 PWM 波形
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1,引脚是PA8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
while(1)
{
delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare1(TIM1,led0pwmval);//设置不同的占空比
}
}
- 烧录后,可以看到 STM32 板子上的 LED 灯由亮变暗的过程。
- 利用 keil 仿真查看输出的波形如下:

- 从上图中可以发现该过程的占空比是逐渐在发送变化。
- 通过示波器可以观察到其波形如下:

四、总结
- 通过输出的波形,可以观察到输出的占空比是发生变化,而 PWM 的原理就是通过占空比的改变来表示波形,采用示波器可以清楚的观察到占空比的改变,而 keil 的仿真不是特别的明显,当然也可以利用库函数提供的函数,实现改变频率,从而改变 LED 的亮度情况,实现 LED 闪烁的多样变化。
举报