打印
[MM32软件]

【MM32 eMiniBoard测评报告】四、PWM

[复制链接]
606|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
     本次实验利用开发板上的LD2、LD3、LD4所在的端口PB3、PB4、PB5输出同一频率、不同占空比的PWM波,使LD2、LD3、LD4呈现出不同的亮度。当然也可以让这三个LED呈现“呼吸”灯状态显示,输出固定占空比主要是方便对波型进行简单的定量分析。



从上图可以看到这三个端口可以被TIM2_CH2、TIM3_CH1、TIM3_CH2三个通道复用。TIM2、TIM3两个定时器都属“通用”定时器,但区别为TIM2为32位;TIM3为16位。下面是对这两个定时器更加具体的描述:





实验代码参考了官方DEMO。主要代码如下:
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);        //开启TIM3时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);          //开启GPIOB时钟

        GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_1);
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_1);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;         //TIM3_CH1 TIM3_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
         
        /*定时器时钟频率 = 48MHz/psc = 48MHz/(47+1)=1MHz
          定时时间 = 1MHz/arr = 1HMz/(999+1) = 1KHz = 0.001s = 1ms
        */
        TIM_TimeBaseStructure.TIM_Period = arr;                                 //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         80K
        TIM_TimeBaseStructure.TIM_Prescaler =psc;                         //设置用来作为TIMx时钟频率除数的预分频值  不分频
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;                 //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
       
        TIM_OCStructInit(&TIM_OCInitStructure);
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                                                 //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_Pulse = 0;                                                                                                                 //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                 //输出极性:TIM输出比较极性高
       
        TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC2Init(TIM3, &TIM_OCInitStructure);
       
        TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH1预装载使能         
        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH2预装载使能
       
        TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIM3在ARR上的预装载寄存器
       
        TIM_Cmd(TIM3, ENABLE);  //使能TIM1
}
void TIM2_PWM_Init(u16 arr,u16 psc)
{  
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);        //开启TIM2时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);          //开启GPIOB时钟
       
                GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_2);                //开启PB3端口复用

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                                                 //TIM2_CH2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                          //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   
    TIM_TimeBaseStructure.TIM_Period = arr;                                         //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         80K
    TIM_TimeBaseStructure.TIM_Prescaler =psc;                                 //设置用来作为TIMx时钟频率除数的预分频值  不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;                         //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
                TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
               
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                                                 //选择定时器模式:TIM脉冲宽度调制模式2
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    TIM_OCInitStructure.TIM_Pulse = 0;                                                                                                                 //设置待装入捕获比较寄存器的脉冲值
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;                 //输出极性:TIM输出比较极性低
   
                TIM_OC2Init(TIM2, &TIM_OCInitStructure);
               
                TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);                                                  //CH2预装载使能

    TIM_ARRPreloadConfig(TIM2, ENABLE);                                                                                                         //使能TIM2在ARR上的预装载寄存器
               
    TIM_Cmd(TIM2, ENABLE);                                                                                                                                                          //使能TIM2
}
int main(void)
{
        delay_init();       

        TIM2_PWM_Init(999,47);
        TIM3_PWM_Init(999,47);
       
        TIM3->CCR1 = 700;//PB4 LD4
        TIM3->CCR2 = 400;//PB5 LD3
        TIM2->CCR2 = 100;//PB3 LD2       
        while(1)
        {
  }       
}

从上面的配置中可以看出,定时器时钟频率使用了48分频,即48MHz/(47+1)=1MHz,周期值为1000,这样在这三个输出通道上即可产生频率为1KHz的PWM波。TIM3两个通道定时器输出比较极性为“高”;TIM2为“低”,其它部分两个定时器配置一样。另外还要注意就是配置中别忘记打开输出端口的“复用”。


阅读手册中关于GPIO端口复用寄存器的描述:



其中对于端口复用功能高位寄存器(GPIOx_AFRH)(x = A..D)的描述中[AF7:AF0]是不是应该写成[AF15:AF8]?也可能是我理解有误。

下面是逻辑分析仪抓取的波型,实验结果符合代码配置要求。


PWM(TIM2 TIM3).rar (257.74 KB)


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

14993

帖子

17

粉丝