STM32的定时器如何产生pwm的?(HAL库开发)

这是一个简单的 PWM 原理示意图。
图中,我们假定定时器工作在向上计数 PWM模式,且当 CNT<CCRx 时,输出 0 ,当 CNT>=CCRx 时输出 1 。那么就可以得到如上的 PWM 示意图:当 CNT 值小于 CCRx 的时候, IO 输出低电平 (0) ,当 CNT 值大于等于 CCRx 的时候, IO 输出高电平 (1) ,当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。 改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的 频率,这就是 PWM 输出的原理。
一、
        使 STM32 的通用定时器 TIMx 产生 PWM 输出,要用到三个寄存器来控制PWM,这三个寄存器分别为捕获 /比较模式寄存器( TIMx_CCMR1/2 ) 、 捕 获 / 比 较 使 能 寄 存 器 ( TIMx_CCER ) 、 捕 获 / 比 较 寄 存 器TIMx_CCR1~4)。
        首先是捕获/ 比较模式寄存器 TIMx_CCMR1/2 ),该寄存器总共有 2 个, TIMx _CCMR1
TIMx _CCMR2 TIMx_CCMR1 控制 CH1 2 ,而 TIMx_CCMR2 控制 CH3 4 。该寄存器
的各位描述如图 所示:
        这里需要说明的是模式设置位 OCxM ,此部分由 3 位组成。 总共可以配置成 7 种模式,我们使用的是 PWM 模式,所以这 3 位必须设置为 110/111 。这两种 PWM 模式的区别就是输出电平的极性相反。
        接下来,介绍捕获 / 比较使能寄存器 TIMx_CCER ),该寄存器控制着各个输入输出 通道的开关。
        只用到了 CC1E 位,该位是输入 / 捕获 2 输出使能位,要想PWM 从 IO 口输出,这个位必须设置为 1 ,所以我们需要设置该位为 1。
最后,捕获 / 比较寄存器 TIMx_CCR1~4 ),该寄存器总共有 4 个,对应 4 个输通道 CH1~4
在输出模式下,该寄存器的值与 CNT (计数器) 的值比较,根据比较结果产生相应动作。利用这点, 我们通过修改这个寄存器的值,就可以控制 PWM 的输出脉宽了。
        现在我使用的是 TIM3 的通道 1 ,所以需要修改 TIM3_CCR1 以实现脉宽控制 DS6 的亮度。
        现在要利用 TIM3 CH1 输出 PWM 来控制 DS6 的亮度,但是 TIM3_CH1 默认是接在 PA6
上面的,而我们的 DS6 接在 PC6 上面,如果普通 MCU ,可能就只能用飞线把 PA6 飞到 PC6
上来实现了,不过,我们用的是 STM32 ,它比较高级,可以通过重映射(AFIO)功能,把 TIM3_CH1 映射到 PC6 上。STM32 的重映射控制是由复用重映射和调试 IO 配置寄存器( AFIO_MAPR)控制的。下面是TIM3_REMAP[1:0] 重映射控制表
        
下面是PWM.C文件
    TIM_HandleTypeDef TIM3_Handler; //定时器句柄
    TIM_OC_InitTypeDef TIM3_CH1Handler; //定时器 3 通道 1 句柄
    //TIM3 PWM 部分初始化
    //arr:自动重装值。
    //psc:时钟预分频数
    //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
    //Ft=定时器工作频率,单位:Mhz
void TIM3_PWM_Init(u16 arr,u16 psc)
{ 
     TIM3_Handler.Instance=TIM3; //定时器 3
     TIM3_Handler.Init.Prescaler=psc; //定时器分频
     TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
     TIM3_Handler.Init.Period=arr; //自动重装载值
     TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
     TIM3_Handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    //使能自动重载
     HAL_TIM_PWM_Init(&TIM3_Handler); //初始化 PWM
 
     TIM3_CH1Handler.OCMode=TIM_OCMODE_PWM1; //模式选择 PWM1
     TIM3_CH1Handler.Pulse=arr/2; 
    //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为
    50%
     TIM3_CH1Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,
    &TIM3_CH1Handler,TIM_CHANNEL_1);//配置 TIM3 通道 1
     HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_1);//开启 PWM 通道 1 
}
    //定时器底层驱动,时钟使能,引脚配置
    //此函数会被 HAL_TIM_PWM_Init()调用
    //htim:定时器句柄
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
     if(htim->Instance==TIM3)
    {
    __HAL_RCC_TIM3_CLK_ENABLE(); //使能定时器 3
    __HAL_AFIO_REMAP_TIM3_ENABLE(); //TIM3 通道引脚完全重映射使能
    __HAL_RCC_GPIOC_CLK_ENABLE(); //开启 GPIOC 时钟
    GPIO_Initure.Pin=GPIO_PIN_6; //PC6
    GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP; //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
    HAL_GPIO_Init(GPIOC,&GPIO_Initure); 
    }
}
//设置 TIM3 通道 1 的占空比
//compare:比较值
void TIM_SetTIM3Compare1(u32 compare)
{
    TIM3->CCR1=compare; 
}

主函数main.c

int main(void)
{
u16 led6pwmval=0; 
u8 dir=1;
 HAL_Init(); //初始化 HAL 库 
 Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
 delay_init(72); //初始化延时函数
uart_init(9600); //初始化串口
 LED_Init(); //初始化 LED 
TIM3_PWM_Init(899,0); //不分频。PWM 频率=72000/(899+1)=80Khz 
while(1)
{
delay_ms(10);
if(dir)led6pwmval++; //dir==1 led6pwmval 递增
else led6pwmval--; //dir==0 led6pwmval 递减
if(led6pwmval>300)dir=0; //led6pwmval 到到 300 后,方向改为递减
if(led6pwmval==0)dir=1; //led6pwmval 递减到 0 后,方向改为递增
TIM_SetTIM3Compare1(led6pwmval);//修改比较值,修改占空比 
}

实验总结:从死循环函数可以看出,我们将 led6pwmval这个值设置为PWM比较值,也就 是通过 led6pwmval 来控制 PWM 的占空比,然后控制 led6pwmval 的值从 0 变到 300,然后又 从 300 变到 0,如此循环,因此 DS6 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于这 里的值,我们为什么取 300,是因为 PWM 的输出占空比达到这个值的时候,我们的 LED 亮度 变化就不大了(虽然最大值可以设置到 899),因此设计过大的值在这里是没必要的。

实验现象:如果没有错误,我们将看 DS6 不停的由暗变到亮,然后又从 亮变到暗。每个过程持续时间大概为 3 秒钟左右。

  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

No Bugs ToDay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值