打印
[STM32F1]

STM32高级定时器和普通定时器出来的效果不一样疑问

[复制链接]
4772|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
大家好,我遇到一个很奇怪现象,同样的程序,普通定时器和高级定时器出来的相位不一样,请问该怎样解决;

//PWM~定时器1
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能
                                                                                                               
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11; //TIM_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &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(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;//选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能//正向通道有效
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable;
  TIM_OCInitStructure.TIM_Pulse = 0;  //设置待装入捕获比较寄存器的脉冲值
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出极性
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC3Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC4Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
        TIM_Cmd(TIM1, ENABLE);  //使能TIMx外设
        TIM_CtrlPWMOutputs(TIM1, ENABLE);
//PWM~定时器2
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能

  GPIO_PinRemapConfig(GPIO_FullRemap_TIM2,ENABLE);//定时器2完全映射
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_10|GPIO_Pin_11; //
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &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_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
                 
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能//正向通道有效//        TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//反向通道无效

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC1Init(TIM2, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC2Init(TIM2, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC3Init(TIM2, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
        TIM_OC4Init(TIM2, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIMx在CCR2上的预装载寄存器       

        TIM_ARRPreloadConfig(TIM2, ENABLE); //使能TIMx在ARR上的预装载寄存器
       
        TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设


我跑下面的程序,发现两个定时器出来的效果不一样;
                        switch (js/64)         
                        {
                                         case 3:  M5_A=DATA1;      DR=0; break; //(+A)(+B)
                                         case 2:  M5_A=DATA2;      DR=1; break;         //(-A)(+B)
                                         case 1:  M5_A=DATA2;      DR=1; break; //(-A)(-B)
                                         default: M5_A=DATA1;      DR=0; break; //(+A)(-B)
                  }               
普通定时器,效果符合要求


高级定时器,感觉有点移相,跟DR的波形配不上。


请朋友们帮帮忙,搞不明是怎么回事。
沙发
mmuuss586| | 2014-12-4 21:12 | 只看该作者
没看明白,你具体要实现啥功能啊?

使用特权

评论回复
板凳
billy_2005|  楼主 | 2014-12-4 21:29 | 只看该作者
mmuuss586 发表于 2014-12-4 21:12
没看明白,你具体要实现啥功能啊?

是这样的,波形里蓝色部分是普通IO的定时高低电平变化,而黄色是PWM,当我用普通定时器来生产PWM,可以看出,PWM有段时间都是低电平时,蓝色IO管脚也跟着是低电平,这效果是可以的。但是当我用定时器1生产PWM时(同样的程序),就发现PWM有段时间都是低电平时,蓝色IO管脚不是匹配跟着低电平,我怀疑是定时器1哪里设置不对导致这个生成的相位跟普通定时器生成的相位有时延

使用特权

评论回复
地板
mmuuss586| | 2014-12-4 21:37 | 只看该作者
billy_2005 发表于 2014-12-4 21:29
是这样的,波形里蓝色部分是普通IO的定时高低电平变化,而黄色是PWM,当我用普通定时器来生产PWM,可以看 ...

定时器1用PWM1模式;
IO低电平的时候,你如果需要关PWM输出,一条指令即可实现TIM1的3路PWM任意通道的开关;

定时器2还是用PWM2模式吧;

使用特权

评论回复
5
billy_2005|  楼主 | 2014-12-4 21:46 | 只看该作者
mmuuss586 发表于 2014-12-4 21:37
定时器1用PWM1模式;
IO低电平的时候,你如果需要关PWM输出,一条指令即可实现TIM1的3路PWM任意通道的开 ...

刚才试验了把定时器1改成PWM1输出,效果还是没变。我这个程序是关于步进电机运动转动的,DR是换向IO,要求是在换相时,PWM生成接近0电压PWM,如果在切换点,PWM有“延时”,会导致直接一个高电压和地的瞬间过程。我不明的是为什么定时器2出来的效果可以,定时器1出来的效果就不行。

使用特权

评论回复
6
mmuuss586| | 2014-12-4 21:50 | 只看该作者
这是我用PWM1模式实现的初始化:
/**********************************************************************
* Description    : None
* Input          : None
* Output         : None
* Return         : None
* Attention      : None
**********************************************************************/
void BLDC_TIM1Config(void)
{
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;                                   //基本结构体变量定义
   TIM_OCInitTypeDef  TIM_OCInitStructure;                         //输出结构体变量定义
   TIM_BDTRInitTypeDef  TIM_BDTRInitStructure;                                                   //死区刹车结构体变量定义

   TIM_DeInit(TIM1);

   TIM_TimeBaseStructure.TIM_Prescaler = 0;                                                                   //2,TIM基本初始化
         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseStructure.TIM_Period = 2999;                                                                   //PWM =64/3000=2.1333K
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
   TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //TIM输出通道初始化
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
   TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;                  
   TIM_OCInitStructure.TIM_Pulse =300;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
   TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;           
   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
   TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;   
   TIM_OC1Init(TIM1,&TIM_OCInitStructure);

   TIM_OCInitStructure.TIM_Pulse =400;
   TIM_OC2Init(TIM1,&TIM_OCInitStructure);

   TIM_OCInitStructure.TIM_Pulse =500;
   TIM_OC3Init(TIM1,&TIM_OCInitStructure);         

   TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;        //死区刹车初始化
   TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
   TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
   TIM_BDTRInitStructure.TIM_DeadTime = 100;
   TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
   TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
   TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

   TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);

   TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);  //使能捕获比较寄存器预装载(通道1)
   TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);         //使能捕获比较寄存器预装载(通道2)
   TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);         //使能捕获比较寄存器预装载(通道3)   
  
   TIM_CtrlPWMOutputs(TIM1,ENABLE);
   TIM_Cmd(TIM1,ENABLE);
}

使用特权

评论回复
7
mmuuss586| | 2014-12-4 21:52 | 只看该作者
这是PWM2实现的初始化;不过我控制的是BLDC,也许无法实现你的需求;
/**********************************************************************
* Description    : None
* Input          : None
* Output         : None
* Return         : None
* Attention      : None
**********************************************************************/
void BLDC_TIM1Config(void)
{
                TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;                                           //基本结构体变量定义
                TIM_OCInitTypeDef  TIM_OCInitStructure;                         //输出结构体变量定义

                TIM_DeInit(TIM1);

                TIM_TimeBaseStructure.TIM_Period = 3199;                                                                   //PWM =64/3200=20K
                TIM_TimeBaseStructure.TIM_Prescaler = 0;                                                                   //1,TIM基本初始化   
                TIM_TimeBaseStructure.TIM_ClockDivision = 0;
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
                TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;                    //周期计数器值
                TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

//                TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//                TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//                TIM_OCInitStructure.TIM_Pulse = 0;
//                TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                
  /* Channel 1, 2,3 and 4 Configuration in PWM mode */
                TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
                TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
                TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
                TIM_OCInitStructure.TIM_Pulse = 0;
                TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
                TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
                TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
                TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
                TIM_OC1Init(TIM1,&TIM_OCInitStructure);       

                TIM_OCInitStructure.TIM_Pulse =0;
                TIM_OC2Init(TIM1,&TIM_OCInitStructure);

                TIM_OCInitStructure.TIM_Pulse =0;
                TIM_OC3Init(TIM1,&TIM_OCInitStructure);         

//                TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);                          //使能捕获比较寄存器预装载(通道1)
//                TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);                                 //使能捕获比较寄存器预装载(通道2)
//                TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);                                 //使能捕获比较寄存器预装载(通道3)   

//                TIM_ARRPreloadConfig(TIM1, ENABLE);               
                TIM_Cmd(TIM1,ENABLE);
                TIM_CtrlPWMOutputs(TIM1,ENABLE);
}

使用特权

评论回复
8
billy_2005|  楼主 | 2014-12-4 22:15 | 只看该作者
mmuuss586 发表于 2014-12-4 21:52
这是PWM2实现的初始化;不过我控制的是BLDC,也许无法实现你的需求;
/********************************** ...

很感谢超级版主,我在你的代码基础上改了一下(增加了第四路PWM),效果好很多了,但现在第四路PWM竟然没输出,是不是哪里设置不对?

TIM_BDTRInitTypeDef  TIM_BDTRInitStructure;                                                   //死区刹车结构体变量定义

                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能
                                                                                                               
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11; //TIM_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   TIM_DeInit(TIM1);

   TIM_TimeBaseStructure.TIM_Prescaler = psc;                                                                   //2,TIM基本初始化
         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseStructure.TIM_Period = arr;                                                                   //PWM =64/3000=2.1333K
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
   TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //TIM输出通道初始化
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
   TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;                  
   TIM_OCInitStructure.TIM_Pulse =300;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
   TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;           
   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
   TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;  

   TIM_OCInitStructure.TIM_Pulse =0;
   TIM_OC1Init(TIM1,&TIM_OCInitStructure);

   TIM_OCInitStructure.TIM_Pulse =0;
   TIM_OC2Init(TIM1,&TIM_OCInitStructure);

   TIM_OCInitStructure.TIM_Pulse =0;
   TIM_OC3Init(TIM1,&TIM_OCInitStructure);         

   TIM_OCInitStructure.TIM_Pulse =0;
   TIM_OC4Init(TIM1,&TIM_OCInitStructure);  
         
   TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;        //死区刹车初始化
   TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
   TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
   TIM_BDTRInitStructure.TIM_DeadTime = 100;
   TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
   TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
   TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

   TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);

   TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);  //使能捕获比较寄存器预装载(通道1)
   TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);         //使能捕获比较寄存器预装载(通道2)
   TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);         //使能捕获比较寄存器预装载(通道3)      
         TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);         //使能捕获比较寄存器预装载(通道4)
         
   TIM_CtrlPWMOutputs(TIM1,ENABLE);
   TIM_Cmd(TIM1,ENABLE);

使用特权

评论回复
9
billy_2005|  楼主 | 2014-12-5 09:41 | 只看该作者
mmuuss586 发表于 2014-12-4 21:52
这是PWM2实现的初始化;不过我控制的是BLDC,也许无法实现你的需求;
/********************************** ...

mmuuss586,我用你这个例子可以了,十分感谢:handshake

使用特权

评论回复
10
mmuuss586| | 2014-12-5 12:15 | 只看该作者
billy_2005 发表于 2014-12-5 09:41
mmuuss586,我用你这个例子可以了,十分感谢

不客气;
谢谢对21IC,还有ST版块的支持;

:'(
有个网友说,我天天逛论坛,公司逛垮了;
每天休息时间上来回答问题,不容易啊;

使用特权

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

本版积分规则

33

主题

84

帖子

1

粉丝