TI中文支持网
TI专业的中文技术问题搜集分享网站

外部中断使MSP430错误地发生复位,请教可能的原因?

分别试了MSP430F247、F5510,UART1连接至GPRS模块SIM900A,根据SIM900A的说明书介绍,当有电话呼入、或者接收到短信时,SIM900A的RI引脚分别会发生50ms、120ms的低电平(平时为高电平)。因此,想利用引脚 RI 产生的中断做为处理短信事件的一个依据。现在的问题是:

两款型号的MSP430都分别试用过P1.5、P2.4,当设置为 High -> Low、即 P1IES |= BIT5 或 P2IES |= BIT4,当电话呼入时会立即造成MSP430F247或F5510复位重启;如果将RI引脚断开、而设置不变,则不会发生复位现象。

当设置为 Low -> High、即 P1IES &=~BIT5 或 P2IES &=~BIT4,当电话呼入时MSP430F247、F5510都不会立即重启,但当挂断电话时立即会造成MSP430F247、F5510复位重启。

请问这种异常现象的可能原因?

Charles Wu:

看起来和外围线路无关,而和MSP430内部的程序有关系。中断处理函数正确嘛?把断点放在P1或者P2的中断处理函数看看是否能正常进入?430若允许了某中断向量发生中断,但却没有指定正确的中断处理函数,程序就会发生复位的情况。

Yun Zhang:

回复 Charles Wu:

void SMS_ISR(void)

{

 SIM_RI_PxSEL &=~SIM_RI_PIN;      // 普通IO

 SIM_RI_PxDIR &=~SIM_RI_PIN;      // input

 SIM_RI_PxIES |= SIM_RI_PIN;         // 1.5 Hi->Lo edge

 SIM_RI_PxIFG &=~SIM_RI_PIN;      // P1.5 IFG cleared  

 SIM_RI_PxIE  |= SIM_RI_PIN;          // P1.5 interrupt enabled,RI

}

#pragma vector = PORT1_VECTOR

__interrupt void port1_ISR (void)

{

 if(P1IFG & SIM_RI_PIN)                    // 处理进来的短信息或电话呼叫

 {

     SMS_call = 0;                                //状态变量,用于识别电话呼入或短信接收

  P1IFG &= SIM_RI_PIN;    

    TA20ms(1);                                    //这里发现问题:当TA20ms(1)执行完后会重新到前面的 SMS_call = 0;

    TA20ms(1);    

    if (!(SIM_RI_PxIN & SIM_RI_PIN)) SMS_call = 1;              // 40ms后仍为低,暂认为是电话呼入

  TA20ms(3);

     if (!(SIM_RI_PxIN & SIM_RI_PIN)) SMS_call = 2;             // 100ms后仍为低,判断为短信息接收

  TA20ms(2);

 }

}

单步跟踪发现,当电话呼入时,会进入P1的外部中断,但执行完第一个 TA20ms(1) 语句时就又从中断的入口进入,不停地反复进入P1口的中断。

本次测试时,使用的是F247、P1.5。

Yun Zhang:

回复 Yun Zhang:

void TA20ms(INT8U Times_N)

{

//采用定时器方式,TACLK=ACLK/2,LPM3(不考虑低功耗可采用LPM0)进行延时

//延时时间为 (TB0CCR0 +1)/定时器的时钟频率,同时需要考虑看门狗的喂狗间隔时间

 if (Times_N > 200)

   Times_N = 200;                                              // 最大Times_N限制为200,否则会超出TA0CCR0的范围65535

 TA0CCTL0 |= CCIE;                                         // TACCR0 interrupt enabled

 TA0CCR0 = 327;                                              // 最大允许数为65535

 TA0CCR0 *= Times_N;                                   // 扩大为 Times_N 倍

 TA0CTL = TASSEL_1 + MC_1 + TBCLR;       // TACLK = ACLK, upmode, clear TBR

 __bis_SR_register(LPM0_bits + GIE);              // LPM0, TA0_ISR will force exit

 TA0CCTL0 &= ~CCIE;                                      // Disable timer Interrupt

}

Yun Zhang:

回复 Yun Zhang:

初步想到一个办法:

进入P1.5的外部中断后,清除中断位、立即禁用P1.5的外部中断,置标志变量,在主程序内处理完任务后,再启用P1.5的外部中断。

尚未实测验证……

Charles Wu:

回复 Yun Zhang:

问题应该就处在TA20ms函数里,在一个IO口中断处理函数里,调用一个延时,且延时是通过定时器中断来实现的,而且还打开了GIE,这就是一个中断嵌套。太多的问题会导致楼主这种错误发生了,列举几种可能:

1.TimerA的中断处理函数是否没有做推出低功耗的处理?

2.是否能保证在在IO口中断发生后,一定只发生Timer的中断,而没有别的中断发生,比如IO口中断?

3.看门狗是否溢出?

Charles Wu:

回复 Charles Wu:

其实若要处理楼主的这种情况,我个人还是喜欢用Timer的捕获功能。

1.在主程序打开Timer的捕获功能,triger模式用下降沿。

2.RI下降沿发生后,进入Timer中断处理函数,记录当前CCRx的数值,然后将tigger模式改为上升沿。

3.当RI上升沿发生后,再次进入Timer中断,记录当前CCRx,将两次得到的CCRx数值相减,记得得到这个下降沿的宽度,再判断是哪种信号即可。

当然,楼主应该还需要加入一些冗余代码处理一些意外情况,比如RI信号的毛刺的处理,RI信号过长,导致超过Timer一个周期等等的情况。

Charles Wu:

回复 Charles Wu:

最后再啰嗦几句。

不能说430不支持中断嵌套,在中断处理函数里再次打开GIE即可实现中断嵌套。但是这样使用后,一定要注意整个中断的时序,一定一定不能发生中断函数递归的情况。猜测楼主这种情况最大的可能性就是发生了中断函数的递归,不断得重复进入中断函数,导致堆栈溢出,或者看门狗复位。

Young Hu:

回复 Charles Wu:

Yun Zhang,

按照Charles说的做肯定没错的。

Charles,

每次看您的回复都能学到很多东西啊!膜拜中。。。

赞(0)
未经允许不得转载:TI中文支持网 » 外部中断使MSP430错误地发生复位,请教可能的原因?
分享到: 更多 (0)