[STM32F1官方例程讲解1] TIM外设输出PWM波

第一章 PWM波

PWM的全称为Pulse-width modulation,是一种通过有效地将电信号切成离散部分来降低电信号传递的平均功率的方法。通过快速打开和关闭电源和负载之间的开关,可以控制进入负载的电压(和电流)的平均值。与关闭时间相比,开关打开的时间越长,提供给负载的总功率就越高。PWM常用于控制惯性负载(例如电机)。PWM的主要优点是开关器件的功耗非常低。当开关断开时,几乎没有电流,而当开关导通且功率正在传递到负载时,开关两端几乎没有压降。因此,作为电压和电流的乘积的功率损耗在两种情况下都接近于零。PWM还可以与数字控件配合使用,由于其开/关特性,可以轻松设置所需的占空比,进而完成控制任务。PWM在Boost-buck电路电机控制开关切换呼吸灯中都有着极其重要的地位。本文基于stm32f10x_stdperiph_lib_um.chm文档中的TIM_PWM_Output章节编写。

1.1 PWM波的主要参数

在这里插入图片描述

参数定义
周期T一次高低电平结束的时间
频率f1/T
占空比Duty Cycle在一个脉冲循环内,通电时间(高电平)占周期的比例。

1.2 STM32F1平台的PWM外设

1.2.1 PWM外设映射关系

在STM32F1平台上,PWM外设隶属于TIMER外设。以STM32F103C8T6芯片为例,通过查阅数据手册,确定TIMER外设在引脚上的映射关系。

引脚默认映射重映射
PA0TIM2_CH1_ETR
PA1TIM2_CH2
PA2TIM2_CH3
PA3TIM2_CH4
PA6TIM3_CH1TIM1_CH1_BKIN
PA7TIM3_CH2TIM1_CH1_CH1N
PA8TIM1_CH1
PA9TIM1_CH2
PA10TIM1_CH3
PA11TIM1_CH4
PA12TIM1_ETR
PA15TIM2_CH1_ETR
PB0TIM3_CH3TIM1_CH2N
PB1TIM3_CH4TIM1_CH3N
PB3TIM2_CH2
PB4TIM2_CH3
PB5TIM2_CH4
PB6TIM4_CH1
PB7TIM4_CH2
PB8TIM4_CH3
PB9TIM4_CH4
PB10TIM2_CH3
PB11TIM2_CH4

其中,TIM1属于高级定时器(advanced-control timer),一些带后缀的功能不在这里讨论(如ETR,互补输出CHxN等)。后面程序中选用的是通用定时器(general -purpose timer)TIM3的CH1~CH4作为PWM波的输出口。

1.2.2 PWM外设的寄存器的配置过程

在这里插入图片描述
首先,对于一个外设而言,最重要的就是时钟的使能与配置,相关操作见2.1 时钟配置。查阅参考手册的相应章节,可知时钟可由外部输入产生,也可通过使能内部RCC(Reset and clock control)上的TIM外设来利用系统的时钟CK_INT(STM32F103为72MHz)。在这里我们选择的是后一种方法。
在这里插入图片描述
在产生了CK_INT内部TIM时钟信号后,先进入PSC Prescaler寄存器进行预分频(由TIM_Prescaler +1决定,定时器实际获得的计数频率为 f C K _ C N T = f C K _ I N T / ( T I M _ P r e s c a l e r + 1 ) f_{CK\_CNT} = f_{CK\_INT}/(TIM\_Prescaler +1) fCK_CNT=fCK_INT/(TIM_Prescaler+1))。而后,APR寄存器的值(由TIM_Period决定)决定了PWM波的周期。外设以 f C K _ C N T f_{CK\_CNT} fCK_CNT 的频率计数,并存储在CNT counter寄存器内,这部分内容详见2.3 定时器配置中的TIM_TimeBaseInit()函数。当CNT counter寄存器内的值与APR寄存器的值相等时,产生中断(在此例子中未用到),并置零CNT counter寄存器(根据设置)。此外,CNT counter寄存器内的值还与Capture/Compare x register内的值(由TIM_Pulse决定)进行比对,可分别设置大于/小于时的输出电平。

综上,可得PWM波的频率 f P W M f_{PWM} fPWM

f P W M = f C K _ I N T / ( T I M _ P r e s c a l e r + 1 ) / ( T I M _ P e r i o d + 1 ) f_{PWM}=f_{CK\_INT}/(TIM\_Prescaler+1)/(TIM\_Period+1) fPWM=fCK_INT/(TIM_Prescaler+1)/(TIM_Period+1)

占空比(假设CNT counter寄存器内的值比Capture/Compare x register内的值小时输出高电平)为:

D u t y C y c l e = ( T I M _ P u l s e + 1 ) / ( T I M _ P e r i o d + 1 ) Duty Cycle=(TIM\_Pulse+1)/(TIM\_Period+1) DutyCycle=(TIM_Pulse+1)/(TIM_Period+1)

同样的,可以看出对于同一个TIM外设,4通道的PWM波输出周期是相同的,而占空比是可分别调节的。

第二章 相关函数配置

2.1 时钟配置

需要使能挂载在APB1上的TIM3时钟,与挂载在APB2上的GPIOA,GPIOB的时钟。具体如下所示:

void RCC_Configuration(void)
{
 /* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
}

2.2 GPIO配置

STM32F103C8T6属于的类型是STM32F10X_MD,中等存储容量Medium-density的STM32F10X系列产品,进入的是下半部分的程序(即else之后的代码)。

void GPIO_Configuration(void)
 {
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef STM32F10X_CL
/*GPIOB Configuration: TIM3 channel1, 2, 3 and 4 */
GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);     
#else
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
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_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
}

上述代码使能了STM32F103C8T6的PA6, PA7, PB0, PB1引脚(分别对应TIM3的CH1~CH4),并将其设置为复用推挽模式

2.3 定时器配置

void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
uint16_t CCR1_Val = 333;
uint16_t CCR2_Val = 249;
uint16_t CCR3_Val = 166;
uint16_t CCR4_Val = 83;
uint16_t PrescalerValue = 0;
PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
/* -----------------------------------------------------------------------
TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles:
The TIM3CLK frequency is set to SystemCoreClock (Hz), to get TIM3 counter
clock at 24 MHz the Prescaler is computed as following:
- Prescaler = (TIM3CLK / TIM3 counter clock) - 1
SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density and Connectivity line devices and to 24 MHz for Low-Density Value line and Medium-Density Value line devices
The TIM3 is running at 36 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1) = 24 MHz / 666 = 36 KHz
TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
----------------------------------------------------------------------- 
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 665;					//装载入ARR中的系数
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;	//预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = 0;  			//外部输入分频,在PWM输出时无作用效果
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
/* PWM1 Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}

在如上配置下,可以通过计算得到PWM波的频率
f P W M = f C K _ I N T / ( T I M _ P r e s c a l e r + 1 ) / ( T I M _ P e r i o d + 1 ) = 72 M H z / ( 2 + 1 ) / ( 665 + 1 ) = 36.04 k H z f_{PWM}=f_{CK\_INT}/(TIM\_Prescaler+1)/(TIM\_Period+1)=72MHz/(2+1)/(665+1)=36.04kHz fPWM=fCK_INT/(TIM_Prescaler+1)/(TIM_Period+1)=72MHz/(2+1)/(665+1)=36.04kHz

各通道的占空比Duty Cycle为:

通道引脚占空比
CH1PA650%
CH2PA737.5%
CH3PB025%
CH4PB125%

上述代码的程序已上传。

第三章 实现效果

采用便携式示波器测试,结果如下,能够很好地与前文所述的设置匹配上。
在这里插入图片描述
之后,我有时间的话会把STM32官方库的所有例程讲解一遍,敬请期待

  • 8
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: STM32F1标准例程是指针对STMicroelectronics公司的STM32F1系列微控制器开发的一套标准程序代码,通过使用这套例程,开发者可以快速启动并进行STM32F1的开发工作。 STM32F1标准例程为开发者提供了各种功能和模块的实现方法,包括但不限于GPIO控制、定时器和计数器、PWM输出、UART通信、SPI和I2C通信等。这些例程是根据STM32F1系列微控制器的特性和功能设计的,并且经过STMicroelectronics官方的验证和测试。 使用STM32F1标准例程可以实现快速开发和验证。开发者可以在例程中找到许多已经编写好的代码段,根据自己的需求进行修改和定制,从而快速实现特定功能。此外,例程还提供了详细的注释和说明,开发者可以借助这些信息更好地理解代码实现的原理和逻辑。 另外,为了方便开发者使用,STMicroelectronics还提供了一套完整的开发工具链,包括STMCubeMX配置工具、MDK-ARM开发环境等。开发者可以使用这些工具与STM32F1标准例程结合,提高开发效率。 总之,STM32F1标准例程是一套方便开发者使用和定制的代码集合,能够帮助开发者快速启动并实现STM32F1系列微控制器的各种功能。通过使用这些例程,开发者可以节省大量的时间和精力,快速开发出高质量的应用程序。 ### 回答2: stm32f1标准例程是指STM32F1系列微控制器的官方示例代码。它提供了一系列标准例程,展示了STM32F1系列微控制器的各种功能和应用方案。这些例程覆盖了各个核心模块,包括时钟控制、GPIO控制、中断处理、定时器、串口通信、ADC转换、PWM输出等。通过学习和使用这些例程,可以快速了解和上手STM32F1系列微控制器。 标准例程通常有详细的代码注释,结构清晰,易于学习和理解。用户可以通过官方网站或官方提供的软件开发工具下载和使用这些例程。首先,用户需要根据自己的需求选择合适的例程,并下载到开发环境中。然后,根据例程的指导和注释,进行初始化配置和功能实现。用户可以根据自己的需求进行修改和扩展,以满足具体应用的要求。 使用STM32F1标准例程可以节省开发时间,提高开发效率。它为开发者提供了一个学习和实践的平台,帮助他们快速掌握STM32F1系列微控制器的使用方法和开发技巧。同时,标准例程还提供了一些经典应用的范例,可以供开发者参考和借鉴,快速完成项目开发。 总之,STM32F1标准例程是一套官方提供的示例代码,用于演示和学习STM32F1系列微控制器的各种功能和应用方案。通过使用这些例程,开发者可以快速上手STM32F1系列微控制器,提高开发效率,并实现各种应用需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值