目录
背景
PWM 模式
影子寄存器和预装载寄存器
PWM对齐模式
PWM 边沿对齐模式
向上计数配置
向下计数的配置
PWM 中央对齐模式
程序
第一步、使能GPIOB组、AFIO、TIM3外设时钟
第二步、输出通道端口配置编辑
第三步、定时器配置产生频率
第四步、PWM输出配置
第五步、使能预装载寄存器
第六步、使能定时器TIM3
第七步、应用中设置捕获比较寄存器
背景
PWM是单片机的常用功能。比如我可以使用来调节LED的亮度等。通过本篇文章可以了解PWM的工作原理以及STM32如何来控制脉冲的占空比。
PWM 模式



影子寄存器和预装载寄存器


PSC预分频器的影子寄存器是默认开启的。在编程时对PSC,ARR,CCR写入值,这些直接写入的我称之为预装载寄存器。影子寄存器和预装载寄存器之间会有某种作用关系,我们称之为预装载功能
预加载使能 : 预装载寄存器在更新事件(计数器溢出,比较输出等事件)产生后再更新影子寄存器保护了原来的计数周期不受影响,在更新事件(UEV)产生后再开始新的计数
PWM对齐模式
PWM 边沿对齐模式
向上计数配置
向下计数的配置
PWM 中央对齐模式
程序
void TIM3_PWM_Init(u16 arr,u16 psc){ //TIM3 PWM初始化 arr重装载值 psc预分频系数GPIO_InitTypeDef GPIO_InitStrue;TIM_OCInitTypeDef TIM_OCInitStrue;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3和相关GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟(LED在PB0引脚)RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟(定时器3通道3需要重映射到BP5引脚)GPIO_InitStrue.GPIO_Pin=GPIO_Pin_0; // TIM_CH3GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; // 复用推挽GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz; //设置最大输出速度GPIO_Init(GPIOB,&GPIO_InitStrue); //GPIO端口初始化设置// GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //映射,重映射只用于64、100、144脚单片机//当没有重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PA6,PA7,PB0,PB1//当部分重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PB4,PB5,PB0,PB1 (GPIO_PartialRemap_TIM3)//当完全重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PC6,PC7,PC8,PC9 (GPIO_FullRemap_TIM3) TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue); //TIM3初始化设置(设置PWM的周期)TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM1; // PWM模式1:CNT < CCR时输出有效电平TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_High;// 设置极性-有效电平为:高电平TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能TIM_OC3Init(TIM3,&TIM_OCInitStrue); //TIM3的通道3 PWM 模式设置TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能预装载寄存器TIM_Cmd(TIM3,ENABLE); //使能TIM3
本例子时使用PB0作为PWM的输出通道。也就是说TIM3_CH3的默认通道时PB0。
第一步、使能GPIOB组、AFIO、TIM3外设时钟
如果硬件上PB0被用作其他的功能模块使用,可以使用重映像功能。本离职中TIM3_CH3只能时PB0.

第二步、输出通道端口配置

第三步、定时器配置产生频率



因为PCLK1的时钟通过2分频设置为36MHZ,所以到TIM2 3 4的时钟频率时36*2 = 72MHZ
这里面的预分频设置就是截图中的红框。
如果设置为7200-1,说明 计数器的时钟频率为72MHZ/7200 =10000HZ
TIM_Prescaler为什么要减1,主要是因为硬件会自动将设置的值加1,以防止预分频器(PSC)的值为0。在STM32中,预分频器(Prescaler)用于对输入时钟信号进行分频,从而降低定时器计数器的计数频率。预分频器的值(TIM_Prescaler)是一个无符号整数,它决定了输入时钟信号要经过多少次计数才会使定时器计数器加1。具体来说,当定时器的预分频器寄存器(TIMx_PSC)中的值为N时,输入时钟信号要经过N + 1个时钟周期,定时器计数器才会加1。因此,为了得到期望的分频系数,需要将计算得到的理论分频系数减1后再赋值给TIM_Prescaler
TIM_Period
TIM_Period的作用和设置方法
TIM_Period为什么要减1,主要是因为定时器的计数是从0开始的,当计数达到设定的值时才会产生中断或更新事件。因此,为了确保在计数到最后一个值时产生中断,需要将设定的值减1,这样计数器就可以在达到这个减1后的值时产生中断
TIM_Period代表定时器的自动重装载值(Auto-reload value),当定时器的计数值达到这个值时,定时器就会产生一个中断或更新事件。在实际使用中,需要将TIM_Period设置为所需计数值减去1,以确保在达到最大计数值时产生中断.
如果我们想要产生定周期为100HZ的PWM,我们可以设置为TIMx预分频后的频率/(TIM_Period设置为所需计数)值 -1(即 10000HZ/(100-1))
第四步、PWM输出配置
要特别注意TIM_OC3Init中的3表示的时TIMx定时器中的Channel3的意思。
第五步、使能预装载寄存器
第六步、使能定时器TIM3
第七步、应用中设置捕获比较寄存器
调节占空比
TIM_SetCompare3(TIM3,4500); //改变比较值TIM3->CCR2达到调节占空比的效果
TIM_SetCompare3中的3同样表示更改的是TIMx的通道3