单片机学习小组
直播中

王林

7年用户 192经验值
私信 关注

为什么delay延时的外部中断触发时程序就不行了?

我delay延时了10秒,10秒内触发串口中断没问题,但10秒内触发外部中断,就不行了,无论之后怎么触发外部中断都没反应,但串口接收还可以,请问这是为什么呢?有解决办法吗?不胜感激!
//有人进门发送协议:ff ff 01 fc fc
//设防接受协议:ff 0a 01 fc fc
//取消设防协议:ff 0a 00 fc fc
#define MAIN_Fosc                11059200L        //定义主时钟
#include        "15W4KxxS4.H"
#define  uint unsigned int  
#define  uchar unsigned char
//#define BAUD 9600                            // 波特率
#define BAUD 2400                            // 波特率
//串口初始化相关        
#define S3_S  0x02
//串口中断相关
bit busy;
uchar temp1;      //接收缓冲区
uchar mode[5];      //接收指令存放区
uchar uart3_rflage;               
#define S3RI 0x01
#define S3ti 0x02
//发送指令
uchar youren[5]={0xff,0xff,0x01,0xfc,0xfc};    //有人指令
uchar num=0;     //串口数据长度,数组位
/**********************
引脚别名定义
***********************/
***it rs485_dr=P3^5;        //使能控制485收发芯片使能引脚
***it led6=P0^6;   //蓝色LED用IO口P06
***it led7=P0^7;   //红色LED用IO口P07
***it beep=P0^3;    //BEEP
***it red=P0^2;     //red light
***it green=P0^4;   //green light
bit HW1,HW2;      //红外1和2的标志
bit sf=0;         //1为设防,0为不设防
bit sf_mode;      //接收完一帧指令后的标志
/**************************************
功能描述:外部中断服务程序
入口参数:无
返回值:无
***************************************/
void delay_ms(uint x)
{  
        uint j,i;   
        for(j=0;j         {   
                for(i=0;i<1100;i++);   
        }  
}
void WAI_INIT(void)
{
    //外部中断0的初始化配置        
        IE0  = 0;             //将INT0中断请求标志位清"0"
        EX0 = 1;             //使能INT0中断允许位
        IT0 = 1;                   //选择INT0为下降沿触发方式
        EA = 1;                     //允许总中断
//外部中断1的初始化配置
        IE1  = 0;             //将INT1中断请求标志位清"0"
        EX1 = 1;             //使能INT1中断允许位
        IT1 = 1;                   //选择INT1为下降沿触发方式        
        EA = 1;                     //允许总中断
}
void INT0_int (void) interrupt INT0_VECTOR               
{   
    HW1=1;
}
void INT1_int (void) interrupt INT1_VECTOR               
{   
    HW2=1;
}
/***************************************************************************
* 描  述 : 串口3初始化函数
* 入  参 : 无
* 返回值 : 无
**************************************************************************/
void Uart3_Init(void)
{               
    P_SW2|=S3_S;//串口3引脚p00,p01映射到引脚p50,p51         
        S3CON=0x50; //8位UART T3作为波特率发生器  运行串口3接收数据        
        T3H=(65536-(MAIN_Fosc/12/4/BAUD))/256;   //初值
        T3L=(65536-(MAIN_Fosc/12/4/BAUD))%256;
        T4T3M = 0x08;             //允许定时器3运行
        IE2 |= 0x08;              // 串口3中断打开        
        EA=1;                      //总中断打开
}
/***************************************************************************
* 描  述 : 串口3中断服务函数
* 入  参 : 无
* 返回值 : 无
**************************************************************************/
void Uart3() interrupt 17
{         
    IE2 &= 0xF7;                                   // 串口3中断关闭                  
        if(S3CON & S3RI)      //如果接收完
        {
                S3CON &= ~S3RI;          //接收中断标志清0
                temp1 = S3BUF;    //数据缓存
                uart3_rflage = 1;  //串口接收标识符置1
        mode[num]=temp1;     //加上这一条,接收数据后,返回的数据变长了,
        temp1=0;
        if(mode[0]==0xff)    //如果包头为0xff,则继续接收
        {
            if(num==4)
            {           
                led6=~led6;
                sf_mode=1;        //接受完一帧的数据标志
                num=0;            //清楚接收的数组位
            }
            else num++;
        }
        else mode[0]=0;           //如果包头不为0xff,清掉,此时数据变为00 0a 00(或01) fc fc
        }
        if(S3CON & S3TI)        //如果发送完
        {
                T3H=(65536-(MAIN_Fosc/12/4/BAUD))/256;
                T3L=(65536-(MAIN_Fosc/12/4/BAUD))%256;
                S3CON &= ~S3TI;      //发送中断标志清0
                busy=0;             //发送完,就不busy了
        }
    IE2 |= 0x08;                     // 串口3中断打开
}
//串口发送函数
void SendDataByUart3(uchar dat)
{
        while(busy);           //不busy就可以发送下一个了
        ACC=dat;
        busy=1;                //准备要发送了,先告诉别人我在忙
        S3BUF=ACC;
}
void SendStringByUart3(char *s)
{
    uchar i=5;
//        while(*s)   //指针指向地方有多少个字节发多少个
while(i--)     //只允许发5个字节
        {
                SendDataByUart3(*s++);   //单个字节发送
        }
}
//void jiaoyan()       //接受数据校验
//{
//    uchar i;
//    if((mode[0]!=0xff)&&(mode[4]!=0xfc))
//    {
//        num=0;
//        for(i=0;i<5;i++)
//        {
//            mode=0;
//        }   
//    }   
//}
int setmode()    //设防模式选择
{
    if(sf_mode=1)
    {
        sf_mode=0;
        switch(mode[2])            
        {
            case 0x01:return 1;   //遇到return立即结束当前函数,所以不用break;设防,返回1  
            case 0x00:return 0;   //不设防,返回0
        }   
    }
    else return 0;                //没接收有效指令,返回0
}
/***********************
功能描述:主函数
入口参数:无
返回值:无
************************/
int main()
{
/////////////////////////////////////////////////
//注意: STC15W4K32S4系列的芯片,上电后所有与PWM相关的IO口均为
//      高阻态,需将这些口设置为准双向口或强推挽模式方可正常使用
//相关IO: P0.6/P0.7/P1.6/P1.7/P2.1/P2.2
//        P2.3/P2.7/P3.7/P4.2/P4.4/P4.5
/////////////////////////////////////////////////
//        P0M1 &= 0x3F;        P0M0 &= 0x3F;          //设置P0.6、P07为准双向口(led灯,测试用)
    P0M1 &= 0x23;        P0M0 &= 0x23;          //设置P0.6、P07为准双向口(led灯,测试用),P0.2、P03 、P04为准双向口(继电器用)
    P3M1 = 0;        P3M0 = 0;        //设置P3.0~P3.7为准双向口
        P5M1 = 0;        P5M0 = 0;        //设置P5.0~P5.7为准双向口
    rs485_dr=0;   //控制485接收
    WAI_INIT();       //外部中断初始化
    Uart3_Init();     //串口初始化
  while (1)
        {   
            if(HW1==1&&HW2==0)    //进门
        {      
            delay_ms(180);
            if(HW1==1&&HW2==1)
            {
                HW1=0;       //外部中断标志1清零
                HW2=0;       // 外部中断标志1清零
                rs485_dr=1;   //控制485发送     
                SendStringByUart3(youren);//发送指令
                SendStringByUart3(mode);//发送指令
                delay_ms(5);   //缓冲,延时等485发送完(必须加,因为485发送停止位只发到一半,延时等发完另一半)                 
                rs485_dr=0;   //控制485接收
                led7=~led7;
                if(setmode())          //如果是设防模式,setmode()=1;则开启警报灯蜂鸣器并延时3秒
                {
                    EX0=0;              //关闭外部中断0
                    EX1=0;              //关闭外部中断1
                    red=0;
                    green=0;
                    beep=0;
                    delay_ms(10000);
                    EX0=1;             //打开外部中断0
                    EX1=1;             //打开外部中断0
                    red=1;
                    green=1;
                    beep=1;
                }
            }
        }
        else if(HW1==0&&HW2==1)  //出门
        {
              HW2=0;         //出门,被首先触发的外部中断2清零
              delay_ms(350);//触发外部中断2的路人(出门)必须在该延时内触发外部中断1
              HW1=0;        //若上面延时内被人触发外部中断1,清掉外部中断0内的标志
        }
        }
}

回帖(3)

阎锐

2019-11-8 09:28:36
本来是不加关掉中断的,出现同样的问题,我以为是冲突了,就加上去了,而且我在后面不是加了开启中断吗
举报

陈涛

2019-11-8 09:42:11
求原子哥帮帮忙
举报

RoyZo

2019-11-12 14:32:29
  EX0=0;              //关闭外部中断0
                    EX1=0;              //关闭外部中断1
                    red=0;
                    green=0;
                    beep=0;
                    delay_ms(10000);
                    EX0=1;             //打开外部中断0
                    EX1=1;             //打开外部中断0
                    red=1;
                    green=1;
                    beep=1;
将延时函数放在打开中断后面,才能将中断打开10秒:)
举报

更多回帖

发帖
×
20
完善资料,
赚取积分