[其他ST产品] STM32定时器PWM输出原理与配置

[复制链接]
1236|18
 楼主| 键盘手没手 发表于 2023-10-28 14:47 | 显示全部楼层 |阅读模式
PWM是什么?
        脉冲宽度调制(PWM),利用微处理器的数字输出来对模拟电路进行控制。

1.PWM工作过程
        上一节说过,向上计数从0到ARR(自动装载值)产生中断。那么如何在计数过程中用到PWM呢?

        下图是向上计数,计数器在计数时,捕获比较寄存器(CCRx)和计数器的值相比较,当CCRx > 计数器的值就为低电平,CCRx < 计数器的值就为高电平(根据CCER寄存器来配置是高电平有效还是低电平有效),计数器的值到达ARR的值时,开始重装载,以此来循环。
89475653cae63d7216.png

 楼主| 键盘手没手 发表于 2023-10-28 14:47 | 显示全部楼层
PWM总结
        PWM模式(脉冲宽度调制模式)可以生成一个信号,该信号频率是由TIMx_ARR寄存器的值来决定的,其占空比则是由TIMx_CCRx寄存器值决定。

        PWM模式1:向上计数时,TIMx_CNT<TIMx_CCR1时,通道1为有效电平,否则为无效电平;在向下计数时,TIMx_CNT>TIMx_CCR1时,通道1为无效电平,否则为有效电平。

        PWM模式2:向上计数时,TIMx_CNT<TIMx_CCR1时,通道1为无效电平,否则为有效电平;在向下计数时,TIMx_CNT>TIMx_CCR1时,通道1为有效电平,否则为无效电平。
 楼主| 键盘手没手 发表于 2023-10-28 14:47 | 显示全部楼层
PWM编程流程(HAL库)
        

        1.开启TIM3和GPIO时钟

        __HAL_RCC_TIM3_CLK_ENABLE();

        __HAL_RCC_GPIOB_CLK_ENABLE();                // 复用的时候用

        2.初始化PWM时基参数

        HAL_TIM_PWM_Init();

        3.初始化PWM通道参数

        HAL_TIM_PWM_ConfigChannel();

        4.使能定时器PWM

        HAL_TIM_PWM_Start();

        5.配置IO口复用映射

        HAL_GPIO_Init();
 楼主| 键盘手没手 发表于 2023-10-28 14:47 | 显示全部楼层
小实验程序要求
        使用定时器PWM功能,输出占空比可变的PWM波,用来驱动LED灯,从而达到LED亮度由暗变亮,又从亮变暗,如此循环。
 楼主| 键盘手没手 发表于 2023-10-28 14:47 | 显示全部楼层
代码实现
        tip:1.PB0和PB1为小灯,PB1的话我们需要用复用TIM3_CH4(第4频道);

41354653cae9183eba.png
 楼主| 键盘手没手 发表于 2023-10-28 14:48 | 显示全部楼层
   2.在TIM3_PWM_Init()里占空比是固定的,所以创建TIM3_PWM_SetValue函数改变占空比的值。
 楼主| 键盘手没手 发表于 2023-10-28 14:48 | 显示全部楼层
1.pwm.h
  1. #ifndef __PWM_H
  2. #define __PWM_H

  3. #include "sys.h"

  4. void TIM3_PWM_Init(void);
  5. void TIM3_PWM_SetValue(TIM_HandleTypeDef *htim, uint32_t value);
  6. extern TIM_HandleTypeDef TIM3_PWM_Struct;

  7. #endif
 楼主| 键盘手没手 发表于 2023-10-28 14:48 | 显示全部楼层
pwm.c
  1. #include "pwm.h"

  2. TIM_HandleTypeDef TIM3_PWM_Struct;   // TIM_PWM句柄
  3. TIM_OC_InitTypeDef TIM3_OC_Sturct;   // TIM_OC句柄

  4. void TIM3_PWM_Init()         // PWM初始化
  5. {

  6.     TIM3_PWM_Struct.Instance = TIM3;
  7.     TIM3_PWM_Struct.Init.Prescaler = 90 - 1;                  // 预分频系数  
  8.     TIM3_PWM_Struct.Init.Period = 500 - 1;                     // 自动装载值  
  9.     TIM3_PWM_Struct.Init.CounterMode = TIM_COUNTERMODE_UP;      // 计数模式:向上计数

  10.     HAL_TIM_PWM_Init(&TIM3_PWM_Struct);                     // TIM_PWM初始化

  11.     TIM3_OC_Sturct.OCMode = TIM_OCMODE_PWM1;                // 选择PWM1,还是PWM2
  12.     TIM3_OC_Sturct.Pulse = 250;                             // 占空比:为Period(ARR)一半
  13.     TIM3_OC_Sturct.OCPolarity = TIM_OCPOLARITY_LOW;         // 因为小灯是低电平有效 选择低电平

  14.     HAL_TIM_PWM_ConfigChannel(&TIM3_PWM_Struct, &TIM3_OC_Sturct, TIM_CHANNEL_4);    // 初始化PWM通道参数
  15.    
  16.     HAL_TIM_PWM_Start(&TIM3_PWM_Struct, TIM_CHANNEL_4);     // 使能定时器PWM

  17. }

  18. void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
  19. {

  20.     if (htim->Instance == TIM3)
  21.     {
  22.         
  23.         GPIO_InitTypeDef GPIO_Struct;           // GPIO句柄
  24.         
  25.         GPIO_Struct.Pin = GPIO_PIN_1;           // PB1
  26.         GPIO_Struct.Mode = GPIO_MODE_AF_PP;     // 推挽输出
  27.         GPIO_Struct.Pull = GPIO_PULLUP;         // 上拉
  28.         GPIO_Struct.Speed = GPIO_SPEED_FAST;    // 高速
  29.         GPIO_Struct.Alternate = GPIO_AF2_TIM3;  // 复用为TIM3

  30.         HAL_GPIO_Init(GPIOB, &GPIO_Struct);  

  31.         __HAL_RCC_TIM3_CLK_ENABLE();            // TIM3时钟使能
  32.         __HAL_RCC_GPIOB_CLK_ENABLE();           // GPIOB时钟使能

  33.     }

  34. }

  35. void TIM3_PWM_SetValue(TIM_HandleTypeDef *htim, uint32_t value)      // 改变PWM占空比的值
  36. {

  37.     htim->Instance->CCR4 = value;                        // 占空比大亮度亮,占空比小亮度暗

  38. }
 楼主| 键盘手没手 发表于 2023-10-28 14:48 | 显示全部楼层
main.c
  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"
  5. #include "pwm.h"


  6. int main(void)
  7. {

  8.     uint8_t direction = 1;          // 方向(判断转向)
  9.     uint32_t led_pwm_value = 0;     // PWM占空比的值

  10.     HAL_Init();                     // 初始化HAL库   
  11.     Stm32_Clock_Init(360,25,2,8);   // 设置时钟,180Mhz
  12.     delay_init(180);                // 初始化延时函数
  13.     uart_init(115200);              // 初始化USART
  14.     LED_Init();                     // 初始化LED
  15.     TIM3_PWM_Init();                // 初始化PWM3
  16.        
  17.         while (1)
  18.     {
  19.         
  20.         delay_ms(10);
  21.         if (direction)              // 判断方向
  22.         {
  23.             led_pwm_value++;
  24.         }
  25.         else
  26.         {
  27.             led_pwm_value--;
  28.         }

  29.         if (led_pwm_value > 400)    // 值最好不要超过Period(ARR)的值
  30.         {
  31.             direction = 0;
  32.         }
  33.         
  34.         if (led_pwm_value == 0)
  35.         {
  36.             direction = 1;
  37.         }

  38.         TIM3_PWM_SetValue(&TIM3_PWM_Struct, led_pwm_value);
  39.         
  40.     }
  41.    

  42. }
童雨竹 发表于 2024-2-1 08:26 | 显示全部楼层

会使二极管导通
Wordsworth 发表于 2024-2-1 09:29 | 显示全部楼层

对于电力电路来说串联的电阻起阻尼作用
Clyde011 发表于 2024-2-1 10:32 | 显示全部楼层

甚至会造成模块电源的损坏
公羊子丹 发表于 2024-2-1 11:25 | 显示全部楼层

将ESD静电保护二极管并联于电路中
万图 发表于 2024-2-1 12:28 | 显示全部楼层

电阻阻值大小则需根据元器件可承受电流大小而决定
Uriah 发表于 2024-2-1 13:31 | 显示全部楼层

小型电子设备
帛灿灿 发表于 2024-2-1 15:27 | 显示全部楼层

电阻元件的电阻值大小一般与温度,材料,长度,还有横截面积有关
Bblythe 发表于 2024-2-1 16:30 | 显示全部楼层

灌封之前需要使用抽空机进行天然脱泡和真空脱泡预处理
周半梅 发表于 2024-2-1 18:26 | 显示全部楼层

当电压超过二极管的导通电压的时候
Pulitzer 发表于 2024-2-1 19:29 | 显示全部楼层

在低成本控制器内部有时候会没有钳位二极管
您需要登录后才可以回帖 登录 | 注册

本版积分规则

104

主题

1260

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部