发新帖本帖赏金 2.00元(功能说明)我要提问
返回列表
打印

外部中断引起死机

[复制链接]
1548|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yinshiyouquan|  楼主 | 2015-12-3 01:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yinshiyouquan 于 2015-12-3 01:17 编辑

  近日弄了一个小东西,功能要求是把P11和P12设置为外部中断,中断唤醒之后解除低功耗模式,如果是P11中断唤醒则把P11改为输出模式,同时输出持续5
s高电平,最后重新转入睡眠状态;同理如果是P12被唤醒同样处理
  现在出现的问题是:假如P11被唤醒,我改变P11由输入变为输出,同时输出高电平,在高电平期间,P12发生中断事件,此时系统立马奔溃无法挽救,我用led测试发现P12中断发生时候,根本没进入中断服务函数,直接就停在那了,所以个人认为是死机了,那么有谁可以告诉我是怎么回事,有没什么解决建议
  
   附上io输入和输出配置函数:


/*************************************
函数名称:Config_IOIN_Mode
功    能:io口配置为输入模式,并根据 IS_OpenInt判断是否开启中断
参    数:IO_Pin,IS_OpenInt
返回值  :无
*************************************/
void Config_IOIN_Mode(char IO_Pin,char IS_OpenInt)
{
  P1DIR &= ~IO_Pin; //设置IO-Pin为输入模式
  P1REN |= IO_Pin;  //使能上下拉电阻
  P1OUT &= ~IO_Pin; //配置为下拉电阻
  if(IS_OpenInt == ENABLE)
  {
    P1IE  |= IO_Pin;  //使能IO_Pin外部中断
    P1IES &= ~IO_Pin;  //中断触发方式:上升沿
    P1IFG &= ~IO_Pin;  //清除中断标志
  }
}

/*************************************
函数名称:Config_IOIN_Mode
功    能:io口配置为输入模式
参    数:IO_Pin
返回值  :无
*************************************/
void Config_IOOut_Mode(char IO_Pin)
{
  P1DIR |= IO_Pin;  //设置IO-Pin为输出模式
  P1REN &= ~IO_Pin; //关闭上下拉电阻使能
  P1IE  &= ~IO_Pin; //关闭中断
  P1OUT &= ~IO_Pin; //默认输出低电平
}

打赏榜单

21ic小管家 打赏了 2.00 元 2015-12-03

相关帖子

沙发
xyz549040622| | 2015-12-3 08:43 | 只看该作者
是不是你逻辑上的问题,在唤醒后,又发生了P12的唤醒中断,本来就是醒的,你如何再次唤醒呢?你的程序停在哪里了呢?

使用特权

评论回复
板凳
yinshiyouquan|  楼主 | 2015-12-3 09:05 | 只看该作者
是这样的,后来我取消低功耗模式,P11外部中断触发之后执行输出高电平命令过程中,P12发生中断事件,但mcu没有执行中断处理函数,5s时间到了P11还是处于输出状态;另外我做了这样测试,P11发生中断输出高电平期间,P12不发生中断,5s后P11可实现重新变为输入,程序运行就正常

使用特权

评论回复
地板
dirtwillfly| | 2015-12-3 09:55 | 只看该作者
你的程序整体逻辑结构是怎么样的?是不是你把IO的输出高电平操作放中断服务程序里了?

使用特权

评论回复
5
ayl439| | 2015-12-3 10:19 | 只看该作者
养成好习惯,把清除中断标志位放在中断使能语句前面,另外代码贴全一点,这样看不出来什么问题

使用特权

评论回复
6
yinshiyouquan|  楼主 | 2015-12-3 10:26 | 只看该作者
dirtwillfly 发表于 2015-12-3 09:55
你的程序整体逻辑结构是怎么样的?是不是你把IO的输出高电平操作放中断服务程序里了? ...

这里描述有误,P11中断发生后,中断服务函数里面设置P11事件发生变量置1,主函数里面根据这个标量标志启动P11为输入模式,同时输出5s高电平,5s一到重新设置输入模式,中断服务函数只有判断是哪种外部中断触发,同时设置对应标志变量,不做其他事情

使用特权

评论回复
7
dirtwillfly| | 2015-12-3 10:40 | 只看该作者
方便把完整的代码贴出来吗?

使用特权

评论回复
8
yinshiyouquan|  楼主 | 2015-12-3 11:46 | 只看该作者
//#include "msp430g2201.h"
//#include "msp430g2302.h"
#include "msp430g2553.h"
#define SET       1
#define RESET     0
#define ENABLE    1
#define DISABLE   0

#define P10       0x01  //中断1辅助测试灯
#define P11       0x02
#define P12       0x04
#define P13       0x08 //外部中断1
#define P14       0x10 //外部中断2
#define P16       0x40 //中断2辅助测试灯


void Config_IOIN_Mode(char IO_Pin,char IS_OpenInt);
void Config_IOOut_Mode(char IO_Pin);
void Delay_Ms(unsigned int z);

unsigned int tmp = 0;//调试
unsigned char Key1_Flag = 0,Key2_Flag = 0;
unsigned int  KEY1_Count = 0,KEY2_Count = 0;
unsigned char P11Out_Flag = 0,P12Out_Flag = 0;

void main()
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  Config_IOIN_Mode((P13 | P14),ENABLE);
  Config_IOOut_Mode((P10|P16)); //配置P1.0,P1.6为输出模式
  
  //定时器配置
  CCTL0 = CCIE;//使能比较中断,打开定时器
  CCR0 = 10000;//比较器值,中断一次10ms
  TACTL = TASSEL_2 + MC_1;//SMCLK时钟源,up计数方式,定时器时钟不分频
  
   _EINT();//使能全局中断;
  // LPM4;   //进入LPM4低功耗模式
  while(1)
  {  
    if(Key1_Flag == SET)
    {
      if(P12Out_Flag == SET)//如果按键2执行动作中则取消动作,同时改为输入模式
      {
         P12Out_Flag = RESET;
         KEY2_Count = 0;
         P1OUT &= ~P16;//关闭测试灯
         P1OUT &= ~P14;//输出低电平               
         Config_IOIN_Mode(P14,ENABLE);//重新配置为输入模式
      // LPM4;   
      }
      else
      {
        Config_IOOut_Mode(P13);//io由输入变为输出
     // Delay_Ms(5);
        P11Out_Flag = SET;
      }
        Key1_Flag = RESET;
    }
   
    if(P11Out_Flag == SET)
    {        
      if(KEY1_Count < 500)//输出持续5s高电平
      {
        P1OUT |= P13;
      }
      else
      {
        KEY1_Count = 0;
        P11Out_Flag = RESET;
        P1OUT &= ~P13;
        Config_IOIN_Mode(P13,ENABLE);
       // Delay_Ms(10);
       // LPM4;   
       }
    }
      
    if(Key2_Flag == SET)
    {           
       if(P11Out_Flag == SET)//如果按键1执行动作中则取消动作,同时改为输入模式
       {
         P11Out_Flag = RESET;
         KEY1_Count = 0;
         P1OUT &= ~P10;//关闭测试灯LED1
         P1OUT &= ~P13;              
         Config_IOIN_Mode(P13,ENABLE);
       }
       else
       {
         Config_IOOut_Mode(P14);         
         P12Out_Flag = SET;
       }
       Key2_Flag = RESET;
    }
   
    if(P12Out_Flag == SET)
    {  
       if(KEY2_Count < 500)//输出持续5s高电平
       {  
         P1OUT |= P14;//测试灯打开
         P1OUT |= P16;
       }
       else
       {
         P12Out_Flag = RESET;
         KEY2_Count = 0;
         P1OUT &= ~P16;
         P1OUT &= ~P14;  
         Config_IOIN_Mode(P14,ENABLE);      
       //  Delay_Ms(10);
       //  LPM4;
        }
    }

    if(P11Out_Flag == SET)//测试灯
    {
      if(tmp < 10 ){P1OUT |= P10;}
      else if(tmp >= 10 && tmp <= 20){P1OUT &= ~P10;}
      else tmp = 0;
    }
  }
}

/*************************************
函数名称:外部中断0,1
功    能:外部中断0,1的中断服务函数
参    数:无
返回值  :无
*************************************/
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{   
  
  switch(P1IFG & 0x18)//判断是哪一个io发生中断
  {   
    case 0x08:
    {
      Delay_Ms(90);
      if(0x08 & P1IN)
      {
         while(0x08 & P1IN);//等待解除              
         P1IFG &= ~0x08;//清除中断P1.1标志
         Key1_Flag = SET;
        // LPM4_EXIT;
      }
      P1IFG &= ~0x08;//清除中断P1.1标志   
      break;
    }
    case 0x10:
    {
      //P1OUT ^= 0x40;
      Delay_Ms(90);
      if(0x10 & P1IN)
      {      
         while(0x10 & P1IN);
         P1IFG &= ~0x10;//清除中断P1.1标志
         Key2_Flag = SET;
        // LPM4_EXIT;
      }
      P1IFG &= ~0x10;//清除中断P1.2标志
      break;
    }
    default:break;
  }
}

/*************************************
函数名称:Timer_A
功    能:定时器A的中断服务函数
参    数:无
返回值  :无
*************************************/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
  //static unsigned int P11Int_Count = 0,P12Int_Count = 0;
   
  if(P11Out_Flag == SET)
  {
    tmp++;
    KEY1_Count++;
  }
   if(P12Out_Flag == SET)
  {
     KEY2_Count++;
  }
}

/*************************************
函数名称:Config_IOIN_Mode
功    能:io口配置为输入模式
参    数:IO_Pin
返回值  :无
*************************************/
void Config_IOIN_Mode(char IO_Pin,char IS_OpenInt)
{
  P1DIR &= ~IO_Pin; //设置IO-Pin为输入模式
  P1REN |= IO_Pin;  //使能上下拉电阻
  P1OUT &= ~IO_Pin; //配置为下拉电阻
  if(IS_OpenInt == ENABLE)
  {
    P1IFG &= ~IO_Pin;  //清除中断标志
    P1IE  |= IO_Pin;  //使能IO_Pin外部中断
    P1IES &= ~IO_Pin;  //中断触发方式:上升沿   
  }
}

/*************************************
函数名称:Config_IOIN_Mode
功    能:io口配置为输入模式
参    数:IO_Pin
返回值  :无
*************************************/
void Config_IOOut_Mode(char IO_Pin)
{
  P1DIR |= IO_Pin;  //设置IO-Pin为输出模式
  P1REN &= ~IO_Pin; //关闭上下拉电阻使能
  P1IE  &= ~IO_Pin; //关闭中断
  P1OUT &= ~IO_Pin; //默认输出低电平
}

void Delay_Ms(unsigned int z)
{
  unsigned int x,y;
  for(x = 0;x < 100;x++)
    for(y = 0;y < z;y++);
}

使用特权

评论回复
9
21ic小管家| | 2015-12-3 17:02 | 只看该作者
此打赏为十大热门打赏哦~

使用特权

评论回复
10
yinshiyouquan|  楼主 | 2015-12-3 17:43 | 只看该作者
在中断服务函数里面加一个测试指示灯,P13中断发生转为输出模式时候,我对P13触发中断操作,LED灯没有变化,确认io已经处于输出模式,失去中断能力,此时理论上,只有P14可触发中断,代码如下:
case 0x08:
    {
      
      Delay_Ms(90);
      P1OUT ^= P16;//测试指示灯
      if(0xP13 & P1IN)
      {
         while(P13 & P1IN);//等待解除              
         P1IFG &= ~P13;//清除中断P1.3标志
         Key1_Flag = SET;
        // LPM4_EXIT;
      }
      P1IFG &= ~P13;//清除中断P1.3标志   
      break;
    }

使用特权

评论回复
11
yinshiyouquan|  楼主 | 2015-12-3 22:45 | 只看该作者
原因找到了,是自己逻辑上失误,在P13变为输出高电平过程中,P14发生中断,在中断服务函数里,有这样一条指令 if(0xP13 & P1IN) ,毫无疑问,这条判断肯定为真,那么 这条指令while(P13 & P1IN);必然被执行,相信大家也看出来了,问题就出现在这边,前面说了,此时P13为高电平,这条指令就变成死循环,永远也跳不出中断服务函数。
  问题总算解决,不是什么大难题,主要还是逻辑上细节问题,感谢大家的关注与帮助,谢谢。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
dirtwillfly + 2 赞一个!
12
ayl439| | 2015-12-4 10:17 | 只看该作者
解决了就好~~~

使用特权

评论回复
13
布谷鸟2015| | 2015-12-16 15:59 | 只看该作者
学习学习,我也觉得是逻辑上出现了问题(O_O)

使用特权

评论回复
14
handleMessage| | 2015-12-16 16:13 | 只看该作者
不懂,P11和P12的设置差异在哪里呢?

使用特权

评论回复
15
vivilzb1985| | 2015-12-16 22:19 | 只看该作者
中断里面有死循环还是?或者是不断地进入到中断中的?

使用特权

评论回复
发新帖 本帖赏金 2.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

10

帖子

0

粉丝