OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3500|回复: 2

进入输入捕获中断后不能返回主程序

[复制链接]

1

主题

2

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2017-3-21
在线时间
7 小时
发表于 2017-3-21 13:53:23 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 chenaidong 于 2017-3-21 14:20 编辑

我编写一段“测试PWM信号的周期及脉冲宽度”的程序,TIM3作为PWM信号输出,TIM5作为输入捕获,但进入中断后,无法返回主程序运行,求助!
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);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB     //使能GPIO外设时钟使能
                         | RCC_APB2Periph_AFIO, ENABLE);    //使能AFIO复用功能模块时钟使能

    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);   //Timer3部分重映射  TIM3_CH2->PB5

                                                  //用于 TIM3的CH2输出的PWM通过该LED显示

    //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;      //TIM_CH2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //GPIO_WriteBit(GPIOA, GPIO_Pin_7,Bit_SET);     // PA7上拉

    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_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_OC2Init(TIM3, &TIM_OCInitStructure);       //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);     //使能TIMx在CCR2上的预装载寄存器

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

void TIM5_Cap_Init(u16 arr,u16 psc)
{
    uint16_t tmpccmr1 = 0;
    uint16_t tmpccer = 0;

    TIM_ICInitTypeDef  TIM5_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;



    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  //使能TIM5时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //使能GPIOA时钟

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;      //PA0 清除之前设置  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;     //PA0 输入  
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);        //PA0 下拉

    //初始化定时器5 TIM5  
    TIM_TimeBaseStructure.TIM_Period = arr;      //设定计数器自动重装值 0xFFFF
    TIM_TimeBaseStructure.TIM_Prescaler = psc;      //预分频器       72-1
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);    //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

    //中断分组初始化
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;     //TIM5中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;   //先占优先级3级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);         //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

    //初始化TIM5输入捕获参数
    TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1;      //CC1S=01  选择输入端 IC1映射到TI1上
    TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising ;  //上升沿捕获
    TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //CC1通道配置为输入,IC1映射到TI1上  0x0001
    TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;     //配置输入分频,不分频
    TIM5_ICInitStructure.TIM_ICFilter = 0x00;       //IC1F=0000 配置输入滤波器 不滤波
    TIM_ICInit(TIM5, &TIM5_ICInitStructure);


    tmpccmr1 = TIM5->CCMR1;
    tmpccer = TIM5->CCER;
    //选择TIMx_CCR2的有效输入:置TIMx_CCMR1寄存器的CC2S=10(选择TI1)。
    tmpccmr1 &= (uint16_t)(((uint16_t)~(uint16_t)TIM_CCMR1_CC2S));
    tmpccmr1 |= 0x0200;
    //选择TI1FP2的有效极性(捕获数据到TIMx_CCR2):置CC2P=1(下降沿有效)
    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P));
    tmpccer |= 0x0020;
    //使能捕获:置TIMx_CCER寄存器中CC1E=1且CC2E=1
    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2E));
    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1E));

    tmpccer |= 0x0011;

    TIM5->CCMR1 = tmpccmr1;
    TIM5->CCER = tmpccer;

    //Select the TIM3 Input Trigger: TI2FP2

    //选择有效的触发输入信号:置TIMx_SMCR寄存器中的TS=101(选择TI1FP1)
    //TS[2:0]触发选择,选择同步计数器的触发输入
    //TS[2:0] = 101 ,滤波后的定时输入1(TI1FP1)


    TIM_SelectInputTrigger(TIM5,TIM_TS_TI1FP1);     //TIM_TS_TI1FP1 = 0x0050

    //Select the slave Mode: Reset Mode  
    //配置从模式控制器为复位模式:置TIMx_SMCR中的SMS=100。
    //SMS[2:0]从模式选择,当选择了外部信号,触发信号(TRGI)的有效边沿与选中的外部输入极性相关
    //SMS[2:0] = 100 ,复位模式,选中的触发输入(TRGI)的上升沿重新初始化计数器,并产生一个更新寄存器信号
    TIM_SelectSlaveMode(TIM5,TIM_SlaveMode_Reset);    //TIM_SlaveMode_Reset = 0x0004

    // Enable the Master/Slave Mode
    //MSM,主/从模式
    //MSM = 1 ,触发输入(TRGI)上的事件被延时了,以允许在当前定时器(通过TRGO)与它的从定时器间的完美同步
    TIM_SelectMasterSlaveMode(TIM5,TIM_MasterSlaveMode_Enable);//TIM_MasterSlaveMode_Enable = 0x0080

    TIM_ITConfig(TIM5,TIM_IT_CC1 | TIM_IT_CC2,ENABLE);   //允许CC1IE、CC2IE捕获中断

    TIM_Cmd(TIM5,ENABLE );           //使能定时器5
}



//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
    // TIM_Cmd(TIM5,DISABLE );

    if(TIM_GetFlagStatus(TIM5,TIM_FLAG_CC1) == SET)
    {
        TIM_ClearFlag(TIM5,TIM_FLAG_CC1);
        IC1Value = TIM_GetCapture1(TIM5) + 1;  
        printf("PWM波形周期: %d;\r\n",IC1Value);
   
        TIM_ClearFlag(TIM5,TIM_FLAG_CC1);
    }  
    else if(TIM_GetFlagStatus(TIM5,TIM_FLAG_CC2) == SET)
    {
        TIM_ClearFlag(TIM5,TIM_FLAG_CC2);
        IC2Value = TIM_GetCapture2(TIM5) + 1;
  
        printf("PWM脉冲宽度: %d;\r\n",IC2Value);
        TIM_ClearFlag(TIM5,TIM_FLAG_CC2);  
    }
}



int main(void)
{  
    // u32 temp=0;
    delay_init();              //延时函数初始化   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);          //串口初始化为115200

    LED_Init();               //LED端口初始化

    TIM3_PWM_Init(35999,1);         //8分频,PWM频率=72000000/(36000*2)=1Khz(周期1000us)
    TIM_SetCompare2(TIM3,32400);       //

    TIM5_Cap_Init(0XFFFF,72-1);       //以1Mhz的频率计数(1us)
  
    while(1)
    {
        delay_ms(1000);
        printf("DutyCycle: %d;IC2Value:%d !\r\n",IC1Value,IC2Value);
  
        LED1 = !LED1;
    }
}





最佳答案

查看完整内容[请看2#楼]

问题已解决。 将中断中的“printf”函数删除就正常了 具体原因不清楚
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2017-3-21
在线时间
7 小时
 楼主| 发表于 2017-3-21 13:53:24 | 显示全部楼层
问题已解决。
将中断中的“printf”函数删除就正常了
具体原因不清楚
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2017-3-22 01:57:14 | 显示全部楼层
说明你中断服务函数处理有问题,没有正常返回
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 11:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表