本文主要介绍了什么是PWM,PWM的基本结构,PWM波的生成过程,如何用代码生成PWM波以及通过示波器观察生成的PWM波形。
前期准备:32芯片、示波器。
一、PWM的概念
1.引言
关于PWM,常听到的有“用示波器抓PWM波啊”“PWM的占空比”……这些都是啥,我很好奇,所以我去学习了PWM波,知道了什么是占空比、频率是什么、怎样用PWM实现呼吸灯、为啥提及PWM就会提到定时器……
2.PWM的概念
PWM:Pulse Width Modulation,脉冲宽度调制。如下图所示三种信号,皆为脉冲信号,脉冲是指电子技术中经常运用的一种像脉搏似的短暂起伏的电冲击(电压或电流)信号。PWM脉冲宽度调制是一种调制技术,用于控制输出(模拟)信号的平均值。如下图所示,在PWM中,信号由一系列固定周期的脉冲组成。脉冲的宽度表示信号的高电平时间,而周期表示脉冲的重复时间。通过改变脉冲的宽度与周期之间的比例,即占空比(占空比:高电平在一个脉冲周期之内所占的时间比),即改变高电平时间,可以模拟出不同的电压或功率级别,即控制信号的平均电压或功率。
3.PWM基本结构
要想通过单片机输出一个PWM波形需要两部分动作,如图上蓝框所示,一是时基单元,即TIM定时器,用于生成PWM信号,即计数和重装载,它只能发送PWM信号,并不能生成PWM波;二是输出比较单元GPIO端口,用于接收PWM信号,并通过GPIO口输出相应的高低电平信号,即PWM波。简单介绍一下大概过程:
1.首先选择可用于生成PWM的定时器,一般选择通用定时器,并配置好定时器的时钟频率CK_PSC。定时器的时钟频率来源有内部时钟模式、外部时钟模式2、外部时钟模式1和编码器模式,一般选择RCC内部时钟生成(其他用得较少,可自行CSDN),RCC内部时钟取决于定时器TIM挂载的总线的时钟频率,可通过时钟树查询(详情见嵌入式——时钟一文),一般为72MHz。
2.确定CK_PSC后,由PWM的频率计算公式,根据需要生成的PWM波的频率确定预分频值PSC和自动重装值ARR。预分频器PSC即对定时器的时钟频率进行分频,得到较小的所需的频率;自动重装器ARR即用于设置PWM波的周期,综合可得单个PWM波的频率/周期。
PWM的频率计算公式:Frequence=CK_PSC/(PSC+1)/(ARR+1)。
3.确定PSC和ARR后即确定了PWM波的周期,CNT为定时器自动计数值,它是自动增加的,当CNT增加到ARR即计数一个周期后会清零重新计数。同时,CNT会传递给输出比较单元与CCR进行比较确定输出高电平或低电平。
4.CCR捕获/比较器,CCR的值是自己确定的,它主要用于与计数值CNT作比较,当CNT<CCR时,输出高电平;当CNT≥CCR时,输出低电平(PWM模式1如此),此时即可得到PWM信号。所以,CCR是控制输出高电平值的参数,当CCR较大,则高电平占整个PWM周期的时间则较多,也就是占空比越大。故CCR决定了PWM波的占空比。
5.得到PWM信号后,由输出比较单元通道传递给GPIO端口,进而输出PWM波,用示波器即可看到生成的PWM波形。一个定时器有4个输出比较单元。
二、PWM实操
利用单片机生成PWM波的步骤如下:
定时器时钟源选择,RCC开启时钟(TIM外设、GPIO外设)。
配置GPIO(把定时器PWM通道对应的GPIO口初始化为复用推挽输出)。
配置时基单元(PSC和ARR的值)。
配置输出比较单元(CCR的值、输出比较模式、极性选择、输出使能)。
运行控制,启动计数器。
通过示波器连接GPIO口观察PWM波形(可选)。
以下代码均来自于国民N32G455芯片官方例程!不同芯片函数名可能会不同,但大抵是相似的。
1.选择定时器时钟源,开启TIM和GPIO的RCC时钟。
void RCC_Configuration(void) {
/* TIM3 clock enable */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_EnableAPB2PeriphClk( RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_AFIO, ENABLE);
}
选择定时器3(TIM3)作为PWM波生成的时钟源,时钟频率为72MHz,开启TIM3和GPIO所挂载的总线的RCC时钟,TIM3挂载在APB1,GPIO挂载在APB2。
2.配置GPIO(把定时器PWM通道对应的GPIO口初始化为复用推挽输出)。
void GPIO_Configuration(void) {
GPIO_InitType GPIO_InitStructure;
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
}
TIM3所对应的4路PWM输出通道为CH1(PA6)、CH2(PA7)、CH3(PB0)、CH4(PB1),这四个GPIO口均配置为复用推挽输出模式。
3.配置时基单元(PSC和ARR的值)
/* Compute the prescaler value */
PrescalerValue = (uint16_t)(SystemCoreClock / 24000000) - 1; //5
/* Time base configuration */
TIM_TimeBaseStructure.Period = 665; //ARR
TIM_TimeBaseStructure.Prescaler = PrescalerValue; //PSC
TIM_TimeBaseStructure.ClkDiv = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;//向上计数
TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure);
PrescalerValue预分频值即为PSC,Period周期即为ARR,定时器计数模式为向上计数。
4.配置输出比较单元(CCR的值、输出比较模式、极性选择、输出使能)
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR1_Val; //CCR1
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_HIGH;
TIM_InitOc1(TIM3, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
/* PWM1 Mode configuration: Channel2 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR2_Val; //CCR2
TIM_InitOc2(TIM3, &TIM_OCInitStructure);
TIM_ConfigOc2Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
/* PWM1 Mode configuration: Channel3 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR3_Val; //CCR3
TIM_InitOc3(TIM3, &TIM_OCInitStructure);
TIM_ConfigOc3Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
/* PWM1 Mode configuration: Channel4 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR4_Val; //CCR4
TIM_InitOc4(TIM3, &TIM_OCInitStructure);
TIM_ConfigOc4Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
TIM_ConfigArPreload(TIM3, ENABLE);
CCR1、CCR2、CCR3、CCR4为定时器四个PWM输出通道的占空比。
5.运行控制,启动计数器
void TIM_Enable(TIM_Module* TIMx, FunctionalState Cmd) {
/* Check the parameters */
assert_param(IsTimAllModule(TIMx));
assert_param(IS_FUNCTIONAL_STATE(Cmd));
if (Cmd != DISABLE) {
/* Enable the TIM Counter */
TIMx->CTRL1 |= TIM_CTRL1_CNTEN; }
else {
/* Disable the TIM Counter */
TIMx->CTRL1 &= (uint32_t)(~((uint32_t)TIM_CTRL1_CNTEN)); }
}
-
通过示波器连接GPIO口观察PWM波形(可选)
由上图可知,
PWM波的频率为18.0184KHz。(Frequence=f=CK_PSC/(PSC+1)/(ARR+1)=72MHz/6/666=18.0180KHz)
PWM波的周期为55.50μs。(T=1/f=1/18018=55.5μs)
通道一(CH1)PWM波的占空比为50%。(333/665≈50%)
通道二(CH2)PWM波的占空比为37.38%。(249/665≈37.38%)
通道三(CH3)PWM波的占空比为24.91%。(166/665≈24.91%)
通道四(CH4)PWM波的占空比为12.44%。(83/665≈12.44%)
以上内容仅为个人学习分享,若有错误,敬请指正。
标签:TIM3,定时器,嵌入式,TIM,GPIO,PWM,时钟 From: https://blog.csdn.net/qq_51390570/article/details/142882849