PWM输出控制LED亮灭(通用定时器TIMx)

PWM即脉冲宽度调试,通过对周期内高低点平的所占时间长短(占空比)来调节GPIO的输出。

PWM的输出需要用到定时器。

配置步骤:

1、使能定时器时钟、GPIO时钟、复用时钟(若用到);
RCC_APBxPeriphClockCmd();
2、初始化GPIO
GPIO_Init();
3、映射定时器到复用的GPIO上
GPIO_PinRemapConfig();
4、初始化定时器
TIM_TimeBaseInit();
5、初始化定时器通道
TIM_OCxInit();
6、预加载定时器
TIM_OCxPreloadConfig();
7、使能定时器
TIM_Cmd();
8、不断改变OCRx值以达到更改占空比
TIM_SetComparex();

定时器初始化需要配置重装载值和预分频系数来控制PWM输出的周期

周期计算公式:Tout=(Period+1)(Prescaler+1)/Tclk
定时器初始化时需要配置的结构体成员变量及作用:

typedef struct
{
  uint16_t TIM_Prescaler;          //预分频系数     (主时钟分频)
  uint16_t TIM_CounterMode;              //计数模式   (向上对齐、向下对齐、中间对齐) 
  uint16_t TIM_Period;                         //重装载值     (定时器重新计时的值)         
  uint16_t TIM_ClockDivision;              //时钟分频因子 (定时器时钟的再分频,一般设为TIM_CKD_DIV1)
  uint8_t TIM_RepetitionCounter;         //重复次数   (无需配置)
} TIM_TimeBaseInitTypeDef;
定时器通道初始化时需要配置的结构体成员变量及作用:
typedef struct
{
  uint16_t TIM_OCPolarity;        //输出极性(有效时输出高或者低)
  uint16_t TIM_OCMode;       //定时器通道模式(PWM模式或者Compare模式)
  uint16_t TIM_OutputState;      //是否使能
  //以下PWM输出无需配置
  uint16_t TIM_OutputNState;     //是否使能(仅TIM1 和TIM8有效)
  uint16_t TIM_Pulse;             //直接操作寄存器控制输出波形
  uint16_t TIM_OCNPolarity;      //输出极性(有效时输出高或者低)(仅TIM1 和TIM8有效)
  uint16_t TIM_OCIdleState;      //设置空闲状态时的值(仅TIM1 和TIM8有效)
  uint16_t TIM_OCNIdleState;     //设置空闲状态时的值(仅TIM1 和TIM8有效)
} TIM_OCInitTypeDef;
改变CRR2值来调节占空比大小

TIM_SetComparex(TIMx,val);

参考代码:
int main(void)
 {    
    u8 i=1;        
    u16 led0pwmval;        
              
    GPIO_InitTypeDef     GPIO_InitStrue;
 TIM_OCInitTypeDef        TIM_OCInitStrue;
 TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
    
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3和相关GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 使能GPIO复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 使能GPIOB时钟
    
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_1;     // TIM_CH4
    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;    // 复用推挽
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;    //设置输出速度
    GPIO_Init(GPIOB,&GPIO_InitStrue);                //GPIO端口初始化设置
    
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);
   
     //溢出时间Tout=(Period+1)(Prescaler+1)/Tclk    500ms
    TIM_TimeBaseInitStrue.TIM_Period=4999;    //设置自动重装载值(改变该值大小试试灯的亮度 ^_^)
    TIM_TimeBaseInitStrue.TIM_Prescaler=7199;        //预分频系数(时钟72MHz)
    TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;    //计数器向上溢出
    TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;        //时钟的分频因子
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue);        //TIM3初始化设置(设置PWM的周期)
    
    TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM2;        // PWM模式2:CNT大于CCR时输出有效
    TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_High; // 设置极性-有效为高电平
    TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能
    TIM_OC4Init(TIM3,&TIM_OCInitStrue);        //TIM3的通道2PWM 模式设置

    TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);        //使能预装载寄存器
    
    TIM_Cmd(TIM3,ENABLE);        //使能TIM3
   

    while(1)
    {              
  if(i)
   led0pwmval++;        // 由暗变亮
  else
   led0pwmval--;        // 由亮变暗
  if(led0pwmval==0)
   i=1;        // 已达到最亮,开始变暗
        if(led0pwmval>50) // 将50改为其他值试试 ^_^
   i=0;     // 已达到最暗,开始变亮
        
        TIM_SetCompare4(TIM3,led0pwmval);        //改变比较值TIM3->CCR2达到调节占空比的效果      
    }
 }
定时器TIM3重映像关系表(其他定时器映射表自己尝试查查吧TIM3重映像关系表^_^)

PWM输出控制LED亮灭(通用定时器TIMx)_第1张图片
TIM3重映像关系表

试试将GPIOB 1 不设置复用模式配置成PWM输出

最终软件仿真出的波形

PWM输出控制LED亮灭(通用定时器TIMx)_第2张图片
波形周期500ms

---------------------------------------华丽分割--------------------------------------------

有小伙伴说软件仿真的波形不是500ms经过M君一番操作后发现可能是建立工程时设置的时钟晶振大小不是8MHz。

不妨将这里改一下再仿真看看呦。


PWM输出控制LED亮灭(通用定时器TIMx)_第3张图片
时钟8MHz

你可能感兴趣的:(PWM输出控制LED亮灭(通用定时器TIMx))