使用Time1的重复计数器RCR输出一定数量PWM

2019-08-14 18:13发布

我现在使用定时器1输出两路PWM信号,现在需要开始输出一定数量的PWM信号,对比了一下几种实现方法,选择使用重复计数器进行。
但通过软件仿真,发现重复计数器RCR数值有在减小,可以进中断,但还是每次溢出更新产生中断,而不是等RCR减小到0才中断的,RCR没起作用似的。设置中断里关闭定时器好像也不起作用。
手册说明:
如果使用了重复计数器功能,在向上计数达到设置的重复计数次数(TIMx_RCR)时,产生更新事
件(UEV);否则每次计数器溢出时产生更新事件。

void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能定时器3时钟

   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO


   //初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3;  //TIM向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 10;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 TIM_ITConfig( TIM1, TIM_IT_Update, ENABLE); // 中断源, TIM 触发中断源 使能
 
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器


//初始化TIM3 Channel2 PWM模式  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
  TIM_OC2Init(TIM1, &TIM_OCInitStructure); 

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); 

// TIM_ClearFlag(TIM1, TIM_FLAG_Update); //清中断,以免一启用中断后立即产生中断
 TIM_CtrlPWMOutputs(TIM1,ENABLE);
TIM_Cmd(TIM1, ENABLE);  //使能TIM3

}

void TIM1_UP_IRQHandler(void)   //TIM3中断
{  

if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update );  //清除TIMx的中断待处理位:TIM 中断源 

 TIM_ITConfig(TIM1,TIM_IT_Update, DISABLE);
  TIM_CtrlPWMOutputs(TIM1,DISABLE);
  TIM_Cmd(TIM1, DISABLE);  //关TIM1
}  
   
 }


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
lf9335
1楼-- · 2019-08-14 22:36
最近两天在弄这个,花了一天时间搞清楚咋回事了,这个用仿真是不行的,必须烧到片子里,然后用示波器波形就好了,似乎是仿真不出来的原因。
代码(中文注释copy过来就乱了,可以看附件里面的源文件):
//StepMotor.c
#include "StepMotor.h"
#include "SysTick.h"

void StepMotor_Init(u16 TIM1per,u16 PulseNum)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  TIM_OCInitTypeDef TIM_OCInitStruct;
  GPIO_InitTypeDef GPIO_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//ê1Äü¶¨ê±Æ÷1μÄê±Öó
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//ê1ÄüPORTAμÄê±Öó
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ê1Äü¸′óÃ1|ÄüμÄê±Öó

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//íÆíìêä3öÄ£ê½
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;//PA8ÎaTIM1_CH1
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GPIO_InitStruct);
          
  //TIM1ê±»ùéèÖÃ
  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//2»·Ö¸îê±Öó
  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//ÏòéϼÆêy
  TIM_TimeBaseInitStruct.TIM_Prescaler = 720;//Ô¤·ÖÆμÖμ,ÿ10us¼Æêy1′Î
  TIM_TimeBaseInitStruct.TIM_Period = TIM1per;//ÖØ×°ÔØÖμ
        TIM_TimeBaseInitStruct.TIM_RepetitionCounter=PulseNum;//Öظ′′Îêy
  TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);
       
        TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//&#212;ú&#207;òé&#207;&#188;&#198;êyê±,ò&#187;μ&#169;TIMx_CNT<TIMx_CCR1ê±&#206;a&#206;TD§μ&#231;&#198;&#189;,·&#241;&#212;ò&#206;aóDD§μ&#231;&#198;&#189;
  TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//OC4ê1&#196;üê&#228;3&#246;
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//óDD§μ&#231;&#198;&#189;&#206;a&#184;&#223;μ&#231;&#198;&#189;
  TIM_OCInitStruct.TIM_Pulse = TIM1per/2;//±è&#189;&#207;2&#182;&#187;&#241;4μ&#196;&#212;¤×°&#212;&#216;&#214;μ
  TIM_OC4Init(TIM1,&TIM_OCInitStruct);


        TIM_UpdateDisableConfig(TIM1,DISABLE);
       
       
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);       
                NVIC_InitStruct.NVIC_IRQChannel=TIM1_UP_IRQn;
                NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
                NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;
                NVIC_InitStruct.NVIC_IRQChannelSubPriority =0;
                NVIC_Init(&NVIC_InitStruct);

                TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
                TIM_Cmd(TIM1,DISABLE);//&#189;&#251;ó&#195;TIM1
}

//ê&#228;3&#246;ò&#187;′&#174;&#214;&#184;&#182;¨&#198;μ&#194;êoíêyá&#191;μ&#196;&#194;&#246;3&#229;
//Cycle:&#194;&#246;3&#229;μ&#196;&#214;ü&#198;ú£&#172;μ¥&#206;&#187;us
//Pulse_Num:&#194;&#246;3&#229;μ&#196;&#184;&#246;êy£&#172;D&#161;óú255
void StepMotor_Run(u16 Cycle, u16 Pulse_Num)
{
  u16 TIM1per = 0;

  //&#184;&#196;±&#228;TIM1μ&#196;&#214;&#216;×°&#214;μ&#184;&#196;±&#228;&#194;&#246;3&#229;&#198;μ&#194;ê£&#172;&#213;aà&#239;éè&#214;&#195;&#194;&#246;3&#229;&#213;&#188;&#191;&#213;±è&#206;a50%
  TIM1per = Cycle/10;       //&#212;¤·&#214;&#198;μ&#206;a720,10us&#188;&#198;êy1′&#206;
  TIM_SetAutoreload(TIM1, TIM1per-1);//éè&#214;&#195;TIM3μ&#196;&#214;&#216;×°&#212;&#216;&#214;μ
  TIM_SetCompare4(TIM1,TIM1per/2);//&#213;&#188;&#191;&#213;±è&#206;a50%
        TIM_CtrlPWMOutputs (TIM1,ENABLE);
        TIM_Cmd(TIM1,ENABLE);//ê1&#196;üTIM1
}

//TIM1μ&#196;Update&#214;D&#182;&#207;′|àíoˉêy
void StopTim1(void)
{
        if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)
        {
                TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
                TIM_CtrlPWMOutputs (TIM1,DISABLE);       
                TIM_Cmd(TIM1,DISABLE);//ê§&#196;üTIM1
                Delay_us(5000);
                TIM_CtrlPWMOutputs (TIM1,ENABLE);
                TIM_Cmd(TIM1,ENABLE);//ê1&#196;üTIM1
        }
}


仿真的效果和楼主的一样,但是在示波器上看就没问题。

正点原子
2楼-- · 2019-08-15 03:39
 精彩回答 2  元偷偷看……
laoguren1122
3楼-- · 2019-08-15 07:15
用这个重复计数器没有实现,总是每次有溢出就中断,没有等待RCR减少到0中断,干脆使用一个变量计数实现输出固定脉冲数,以后有时间再弄;
另采用主从定时器的门控模式也能实现了固定脉冲输出,这个方面结束。
lf9335
4楼-- · 2019-08-15 10:11
最近两天在弄这个,花了一天时间搞清楚咋回事了,这个用仿真是不行的,必须烧到片子里,然后用示波器波形就好了,似乎是仿真不出来的原因。
代码(中文注释copy过来就乱了,可以看附件里面的源文件):
//StepMotor.c
#include "StepMotor.h"
#include "SysTick.h"

void StepMotor_Init(u16 TIM1per,u16 PulseNum)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  TIM_OCInitTypeDef TIM_OCInitStruct;
  GPIO_InitTypeDef GPIO_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//ê1&#196;ü&#182;¨ê±&#198;÷1μ&#196;ê±&#214;ó
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//ê1&#196;üPORTAμ&#196;ê±&#214;ó
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ê1&#196;ü&#184;′ó&#195;1|&#196;üμ&#196;ê±&#214;ó

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//í&#198;íìê&#228;3&#246;&#196;£ê&#189;
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;//PA8&#206;aTIM1_CH1
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GPIO_InitStruct);
          
  //TIM1ê±&#187;ùéè&#214;&#195;
  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//2&#187;·&#214;&#184;&#238;ê±&#214;ó
  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//&#207;òé&#207;&#188;&#198;êy
  TIM_TimeBaseInitStruct.TIM_Prescaler = 720;//&#212;¤·&#214;&#198;μ&#214;μ,&#195;&#191;10us&#188;&#198;êy1′&#206;
  TIM_TimeBaseInitStruct.TIM_Period = TIM1per;//&#214;&#216;×°&#212;&#216;&#214;μ
        TIM_TimeBaseInitStruct.TIM_RepetitionCounter=PulseNum;//&#214;&#216;&#184;′′&#206;êy
  TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);
       
        TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//&#212;ú&#207;òé&#207;&#188;&#198;êyê±,ò&#187;μ&#169;TIMx_CNT<TIMx_CCR1ê±&#206;a&#206;TD§μ&#231;&#198;&#189;,·&#241;&#212;ò&#206;aóDD§μ&#231;&#198;&#189;
  TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//OC4ê1&#196;üê&#228;3&#246;
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//óDD§μ&#231;&#198;&#189;&#206;a&#184;&#223;μ&#231;&#198;&#189;
  TIM_OCInitStruct.TIM_Pulse = TIM1per/2;//±è&#189;&#207;2&#182;&#187;&#241;4μ&#196;&#212;¤×°&#212;&#216;&#214;μ
  TIM_OC4Init(TIM1,&TIM_OCInitStruct);


        TIM_UpdateDisableConfig(TIM1,DISABLE);
       
       
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);       
                NVIC_InitStruct.NVIC_IRQChannel=TIM1_UP_IRQn;
                NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
                NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;
                NVIC_InitStruct.NVIC_IRQChannelSubPriority =0;
                NVIC_Init(&NVIC_InitStruct);

                TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
                TIM_Cmd(TIM1,DISABLE);//&#189;&#251;ó&#195;TIM1
}

//ê&#228;3&#246;ò&#187;′&#174;&#214;&#184;&#182;¨&#198;μ&#194;êoíêyá&#191;μ&#196;&#194;&#246;3&#229;
//Cycle:&#194;&#246;3&#229;μ&#196;&#214;ü&#198;ú£&#172;μ¥&#206;&#187;us
//Pulse_Num:&#194;&#246;3&#229;μ&#196;&#184;&#246;êy£&#172;D&#161;óú255
void StepMotor_Run(u16 Cycle, u16 Pulse_Num)
{
  u16 TIM1per = 0;

  //&#184;&#196;±&#228;TIM1μ&#196;&#214;&#216;×°&#214;μ&#184;&#196;±&#228;&#194;&#246;3&#229;&#198;μ&#194;ê£&#172;&#213;aà&#239;éè&#214;&#195;&#194;&#246;3&#229;&#213;&#188;&#191;&#213;±è&#206;a50%
  TIM1per = Cycle/10;       //&#212;¤·&#214;&#198;μ&#206;a720,10us&#188;&#198;êy1′&#206;
  TIM_SetAutoreload(TIM1, TIM1per-1);//éè&#214;&#195;TIM3μ&#196;&#214;&#216;×°&#212;&#216;&#214;μ
  TIM_SetCompare4(TIM1,TIM1per/2);//&#213;&#188;&#191;&#213;±è&#206;a50%
        TIM_CtrlPWMOutputs (TIM1,ENABLE);
        TIM_Cmd(TIM1,ENABLE);//ê1&#196;üTIM1
}

//TIM1μ&#196;Update&#214;D&#182;&#207;′|àíoˉêy
void StopTim1(void)
{
        if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)
        {
                TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
                TIM_CtrlPWMOutputs (TIM1,DISABLE);       
                TIM_Cmd(TIM1,DISABLE);//ê§&#196;üTIM1
                Delay_us(5000);
                TIM_CtrlPWMOutputs (TIM1,ENABLE);
                TIM_Cmd(TIM1,ENABLE);//ê1&#196;üTIM1
        }
}


仿真的效果和楼主的一样,但是在示波器上看就没问题。

正点原子
5楼-- · 2019-08-15 14:28
帮顶
只等下雪
6楼-- · 2019-08-15 20:13
我想请问一下楼主的这个程序里面可以换为其它计时器吗,比如TIM2、TIM3等,我想输出一定数量的PWM波,可是网上找了好多代码,看了很多资料,还是实现不了。

一周热门 更多>