This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123定时器中断问题

Other Parts Discussed in Thread: TM4C123GH6PM

用TN4C123编写的光电编码程序用的是WTimer1的A B可是一个轮子转,一个轮子不转。

  • 一个轮子是什么意思,请具体描述

  • match值控制的轮子速度会减为0,刚刚启动它会想转一下,但是转不起来。另一个轮子基本在加速。单独写的获取频率的值,也只能获取一个TIMER 的值
  • match值控制的轮子速度会减为0,刚刚启动它会想转一下,但是转不起来。另一个轮子基本在加速。单独写的获取频率的值,也只能获取一个TIMER 的值
  • 光电编码器,本质上还是脉冲,运动不起来,是你的定时器的配置就出问题了。你需要输出什么脉冲呢,或者你的光电编码器的原理是什么呢?另外,你的代码打开是混乱的,建议直接代码编辑上来。

  • 是的,输出的是高低电平脉冲呀,光电编码器的原理啊,就是测量脉冲。

    #include<stdint.h>
    #include<stdbool.h>
    #include"inc/tm4c123gh6pm.h"
    #include"inc/hw_gpio.h"
    #include"inc/hw_memmap.h"
    #include"driverlib/sysctl.h"
    #include"driverlib/gpio.h"
    #include"driverlib/pin_map.h"
    #include"driverlib/adc.h"
    #include"driverlib/interrupt.h"
    #include"driverlib/timer.h"

    unsigned long aulTimes1=0;
    unsigned long aulTimes2=0;
    unsigned int aulFlag=0;
    unsigned int aCaptuerSuccess=0;
    unsigned int aCaptuerFalse=0;

    unsigned long bulTimes1=0;
    unsigned long bulTimes2=0;
    unsigned int bulFlag=0;
    unsigned int bCaptuerSuccess=0;
    unsigned int bCaptuerFalse=0;

    unsigned int P1=0,P2=0,Q1=0,W1=0;

    void WT1A_BforPC6_7(void)
    {

    // Enable Peripheral Clocks 端口初始化
    SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    //PC6端口初始化
    GPIOPinConfigure(GPIO_PC6_WT1CCP0);
    GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_6);

    //PC7端口初始化
    GPIOPinConfigure(GPIO_PC7_WT1CCP1);
    GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_7);

    TimerDisable(WTIMER1_BASE, TIMER_A);
    TimerDisable(WTIMER1_BASE, TIMER_B);
    TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_TIME|TIMER_CFG_B_CAP_TIME);

    //捕获频率配置
    // TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_TIME);//WT3设置为 分开模式 TimerA 边沿计时模式 减计数
    TimerControlEvent(WTIMER1_BASE, TIMER_A,TIMER_EVENT_POS_EDGE);//WT1timerA设置为 上升沿触发
    TimerLoadSet(WTIMER1_BASE, TIMER_A,900000000);//初始值为90000000(32位timerA4294967296的范围内)
    TimerIntDisable(WTIMER1_BASE, TIMER_CAPA_EVENT|TIMER_TIMA_TIMEOUT);// 触发捕获模式中断 和 time out 中断
    IntEnable(INT_WTIMER1A);//使能WT3timerA的中断
    TimerDisable(WTIMER1_BASE,TIMER_A);//关闭WT3timerA

    //捕获频率配置
    // TimerConfigure(WTIMER1_BASE , TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_CAP_TIME);//WT3设置为 分开模式 TimerB 边沿计时模式 减计数
    TimerControlEvent(WTIMER1_BASE, TIMER_B,TIMER_EVENT_POS_EDGE);//WT3timerB设置为 上升沿触发
    TimerLoadSet(WTIMER1_BASE, TIMER_B,900000000);//初始值为90000000(32位timerA的范围内)
    TimerIntDisable(WTIMER1_BASE, TIMER_CAPB_EVENT|TIMER_TIMB_TIMEOUT);// 触发捕获模式中断 和 time out 中断
    IntEnable(INT_WTIMER1B);//使能WT3timerA的中断
    TimerDisable(WTIMER1_BASE,TIMER_B);//关闭WT3timerB

    //开全局中断
    //IntMasterEnable();

    TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer
    TimerEnable(WTIMER1_BASE, TIMER_A);

    TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer
    TimerEnable(WTIMER1_BASE, TIMER_B);
    }
    void TimeOut_T1B_T0AforPB5_6(void)
    {
    //配置捕获timeout定时器for左轮
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    TimerDisable(TIMER1_BASE, TIMER_B);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PERIODIC);
    TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
    IntEnable(INT_TIMER1B);
    TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    // TimerEnable(TIMER1_BASE,TIMER_B);

    //配置捕获timeout定时器for右轮
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerDisable(TIMER0_BASE, TIMER_A);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
    IntEnable(INT_TIMER0A);
    TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    // TimerEnable(TIMER0_BASE,TIMER_A);

    TimerIntEnable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    TimerEnable(TIMER1_BASE, TIMER_B);

    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerEnable(TIMER0_BASE, TIMER_A);
    }
    void WTimer1A_ISR_CAP(void)//中断:WT1A:PC6左轮::使用标志a
    {
    unsigned long IntState;

    IntState=TimerIntStatus(WTIMER1_BASE, true);//中断标志位获取

    if(IntState&TIMER_TIMA_TIMEOUT)//中断由time out引起时的操作
    {
    SysCtlDelay(40);
    //TimerIntClear(WTIMER1_BASE,TIMER_TIMA_TIMEOUT);
    Q1=1;
    }
    if(IntState&TIMER_CAPA_EVENT)//中断由触发捕获引起时的操作
    {
    W1=1;
    TimerIntClear(WTIMER1_BASE, TIMER_CAPA_EVENT);//清除中断标志
    if( aulFlag==0)//当ulFlag==0时,当前中断获取值赋值给ulTimes1,并将ulFlag置1(此为第一次值)
    {
    aulTimes1=TimerValueGet(WTIMER1_BASE, TIMER_A);
    aulFlag=1;

    }
    else//当ulFlag==1时,当前中断获取值赋值给ulTimes2,并将ulFlag置0(此为第二次值)
    {
    aulTimes2=TimerValueGet(WTIMER1_BASE, TIMER_A);

    TimerIntDisable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer(即重新开始)
    TimerDisable(WTIMER1_BASE, TIMER_A);

    TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
    TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    TimerDisable(TIMER1_BASE, TIMER_B);


    TimerLoadSet(WTIMER1_BASE, TIMER_A,900000000);//重新载入初始值(防止时间过长自动复位)
    aulFlag=0;

    aCaptuerSuccess=1;//两次值获取成功,获取完成将CaptuerSuccess置1
    }

    }

    }
    void WTimer1B_ISR_CAP(void)//中断:WT1B:PC7右轮::使用标志b
    {
    unsigned long IntState;

    IntState=TimerIntStatus(WTIMER1_BASE, true);//中断标志位获取

    if(IntState&TIMER_TIMB_TIMEOUT)//中断由time out引起时的操作,即是长时间无法捕获成功,也就是速度为0
    {
    SysCtlDelay(40);
    //TimerIntClear(WTIMER1_BASE,TIMER_TIMB_TIMEOUT);
    }
    if(IntState&TIMER_CAPB_EVENT)//中断由触发捕获引起时的操作
    {
    TimerIntClear(WTIMER1_BASE, TIMER_CAPB_EVENT);//清除中断标志
    if( bulFlag==0)//当ulFlag==0时,当前中断获取值赋值给ulTimes1,并将ulFlag置1(此为第一次值)
    {
    bulTimes1=TimerValueGet(WTIMER1_BASE, TIMER_B);
    bulFlag=1;

    }
    else//当ulFlag==1时,当前中断获取值赋值给ulTimes2,并将ulFlag置0(此为第二次值)
    {
    bulTimes2=TimerValueGet(WTIMER1_BASE, TIMER_B);

    TimerIntDisable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer(即重新开始)
    TimerDisable(WTIMER1_BASE, TIMER_B);

    TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
    TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerDisable(TIMER0_BASE, TIMER_A);

    TimerLoadSet(WTIMER1_BASE, TIMER_B,900000000);//重新载入初始值(防止时间过长自动复位)
    bulFlag=0;

    bCaptuerSuccess=1;//两次值获取成功,获取完成将CaptuerSuccess置1
    }

    }

    }
    void Timer1B_ISR(void) //设置1s的时间检测捕获是否超时
    {
    unsigned long IntState;

    IntState=TimerIntStatus(TIMER1_BASE, true);
    TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    if(IntState&TIMER_TIMB_TIMEOUT)
    {
    P1=1;
    aCaptuerSuccess=0;

    aCaptuerFalse=1;

    TimerIntDisable(WTIMER1_BASE,TIMER_CAPA_EVENT);//使能中断和timer(即重新开始)
    TimerDisable(WTIMER1_BASE, TIMER_A);

    TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    TimerDisable(TIMER1_BASE, TIMER_B);
    }

    }

    void Timer0A_ISR(void) //设置1s的时间检测捕获是否超时
    {
    unsigned long IntState;

    IntState=TimerIntStatus(TIMER0_BASE, true);
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    if(IntState&TIMER_TIMA_TIMEOUT)
    {
    bCaptuerSuccess=0;

    bCaptuerFalse=1;

    TimerIntDisable(WTIMER1_BASE,TIMER_CAPB_EVENT);//使能中断和timer(即重新开始)
    TimerDisable(WTIMER1_BASE, TIMER_B);

    TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerDisable(TIMER0_BASE, TIMER_A);
    }

    }

    void PWM_L(unsigned long match,unsigned long load) //匹配值和初值::timerA 左轮
    {
    TimerLoadSet(WTIMER0_BASE, TIMER_A, load);//设置初值
    TimerMatchSet(WTIMER0_BASE, TIMER_A, match);//设置匹配值
    //TimerEnable(WTIMER0_BASE, TIMER_A);//使能 WTimer0 的 TimerA
    }
    void PWM_R(unsigned long match,unsigned long load) //匹配值和初值::timerB 右轮
    {
    TimerLoadSet(WTIMER0_BASE, TIMER_B, load);//设置初值
    TimerMatchSet(WTIMER0_BASE, TIMER_B, match);//设置匹配值
    //TimerEnable(WTIMER0_BASE, TIMER_B);//使能 WTimer0 的 TimerB
    }

    void dianjichushihua ()
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE ,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4);
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4,0);
    //SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    //GPIOPinTypeGPIOInput(GPIO_PORTE_BASE ,GPIO_PIN_1|GPIO_PIN_2);//红外线PE1 PE2口

    SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    GPIOPinConfigure(GPIO_PC4_WT0CCP0);
    GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_4);

    GPIOPinConfigure(GPIO_PC5_WT0CCP1);
    GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_5);

    TimerDisable(WTIMER0_BASE, TIMER_A);
    TimerDisable(WTIMER0_BASE, TIMER_B);
    TimerConfigure(WTIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);

    TimerControlLevel(WTIMER0_BASE, TIMER_A, true);
    TimerMatchSet(WTIMER0_BASE, TIMER_A, 1);
    TimerLoadSet(WTIMER0_BASE, TIMER_A, 50000);
    TimerEnable(WTIMER0_BASE, TIMER_A);

    TimerControlLevel(WTIMER0_BASE, TIMER_B, true);
    TimerMatchSet(WTIMER0_BASE, TIMER_B, 1);
    TimerLoadSet(WTIMER0_BASE, TIMER_B, 50000);
    TimerEnable(WTIMER0_BASE, TIMER_B);
    }

    void dianjifangxiang(int a,int b)
    {
    if(a>0)
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,GPIO_PIN_1);//正转
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,0);
    }
    else if(a<0)
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,0);
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,GPIO_PIN_2);//反转
    }
    else
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_1,0);
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_2,0);
    }

    if(b>0)
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,GPIO_PIN_3);//正转
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,0);
    }
    else if(b<0)
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,0);//反转
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,GPIO_PIN_4);
    }
    else
    {
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_3,0);
    GPIOPinWrite(GPIO_PORTB_BASE ,GPIO_PIN_4,0);
    }
    }

    void dianjisudu(int a,int b)
    {
    if(a>50000||b>50000||a<0||b<0)
    return;

    TimerMatchSet(WTIMER0_BASE, TIMER_A, a);
    TimerMatchSet(WTIMER0_BASE, TIMER_B, b);
    }

    void dianjikongzhi(int a,int b)
    {
    dianjifangxiang(a,b);

    if(a<0)
    a=-a;
    if(b<0)
    b=-b;

    dianjisudu(a,b);
    }

    void main(void)
    {
    long Comp1=0,Comp2=0;
    long match=20000,load=50000;
    SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    //电机供电:
    dianjichushihua();
    dianjikongzhi(20000,20000);

    WT1A_BforPC6_7();//初始化
    //PWM_WT0A_BforPC4_5();
    TimeOut_T1B_T0AforPB5_6();


    PWM_L(match,load);
    PWM_R(match,load);
    //开全局中断
    IntMasterEnable();

    while(1)
    {
    if(aCaptuerSuccess==1) //a频率捕捉成功
    {
    Comp1=aulTimes1-aulTimes2;
    aCaptuerSuccess=0;
    TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//重新开始
    TimerEnable(WTIMER1_BASE, TIMER_A);

    TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
    IntEnable(INT_TIMER1B);
    TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    }
    if(aCaptuerFalse==1) //a频率捕捉失败
    {
    P2=1;
    Comp1=900000000;
    aCaptuerFalse=0;
    TimerIntEnable(WTIMER1_BASE,TIMER_CAPA_EVENT);//重新开始
    TimerEnable(WTIMER1_BASE, TIMER_A);

    TimerLoadSet(TIMER1_BASE, TIMER_B,SysCtlClockGet());
    IntEnable(INT_TIMER1B);
    TimerIntDisable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    }
    if(bCaptuerSuccess==1) //b频率捕捉成功
    {
    Comp2=bulTimes1-bulTimes2;
    bCaptuerSuccess=0;
    TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//重新开始
    TimerEnable(WTIMER1_BASE, TIMER_B);

    TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
    IntEnable(INT_TIMER0A);
    TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    }
    if(bCaptuerFalse==1) //b频率捕捉失败
    {

    bCaptuerFalse=0;
    Comp2=900000000;
    TimerIntEnable(WTIMER1_BASE,TIMER_CAPB_EVENT);//重新开始
    TimerEnable(WTIMER1_BASE, TIMER_B);

    TimerLoadSet(TIMER0_BASE, TIMER_A,SysCtlClockGet());
    IntEnable(INT_TIMER0A);
    TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    }

    if(Comp1>Comp2)//左轮慢时:数值小代表 间隔小,速度快
    {
    match+=100;//步进为100
    if(match>load)
    match=load;
    if(match<0)
    match=0;
    PWM_L(match,load);
    }
    if(Comp1<Comp2)//左轮快时
    {
    match-=100;//步进为100
    if(match>load)
    match=load;
    if(match<0)
    match=0;
    PWM_L(match,load);
    }


    }

    }

  • 函数写的太乱,没有看懂你的意思,建议模块化编写。先单独驱动1个电机进行测试,再搞配合。还有,你没有说明编码器和电机驱动的原理。程序中用到了好多中断,着重检查中断的配合,看看每个中断函数是否都执行到了。