微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 为啥无法进中断?

为啥无法进中断?

时间:10-02 整理:3721RD 点击:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit jw=P1^3;                        //继电器开关
sbit beep=P2^6;                        //蜂鸣器
sbit PWM_OUT = P2^7;   //PWM输出接口(p2.7连接舵机的信号线)
sbit  sck=P2^3;         //ds1302
sbit  io = P2^4;
sbit  res = P2^5;
sbit rs=P1^2;         //rs1602
sbit rw=P1^1;         //rw
sbit en=P1^0;         //en
bit OUT;                //高低电平切换标志位
uchar  tmp;
uchar SG1;    //舵机角度          
uint a;
uint d=0;
uchar time_date[7] ={15,5,22,5,17,38,00};//年,yue ,日,星期, 时,分,秒
uchar write_add[7] ={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80};         //写的地址
uchar read_add[7] ={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};   //读的地址     年   月  日   星期   时   分   秒
uchar disp[16],dispb[16];
  uchar  nian,nian1,nian2,yue,yue1,yue2,ri,ri1,ri2,zhou1,zhou2,shi,shi1,shi2,fen1,fen2,miao1,miao2;
   uchar openri1,openri2,openshi1,openshi2,openfen1,openfen2,openmiao1,openmiao2;

//void init();            //串口初始化
// void ctrl();            //接收处理函数
//  void write_ds1302_byte(uchar date);
//  uchar read_ds1302(uchar add);         //返回的为十六进制数
//  void read_rtc();                                                          
//  void time_pros();
//  void time_pros0();
//  void display1();
//  void ini1602();
//  void baocun();

void delay(int z)
{
        int x,y;
        for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}
void write_cmd(uchar cmd)        //1602
{
         rs=0;
         P0=cmd;
         delay(5);
         en=1;
         delay(5);
         en=0;
}
void write_date(uchar date)           //1602
{
        rs=1;
        P0=date;
        delay(5);
        en=1;
        delay(5);
        en=0;
}
void ini1602()                                    //1602初始化
{
        rw=0 ;
        rs=0 ;
        en=0;
        write_cmd(0x38); //16X2  
        write_cmd(0x0c); //
        write_cmd(0x06); //
        write_cmd(0x01); //清屏
}
  void init()        //串口初始化
{             
                  SCON = 0x50;                        // REN=1允许串行接受状态,串口工作模式1,                                                 
                  TMOD = 0x21;      // 定时器1工作于方式2,8位自动重载模式, 用于产生波特率
                  PCON &= 0x7f;                       // 波特率不倍增
        //  EA = 0;//中断总开关
          TH0 = 0xFF; //16位计数寄存器T0高8位
          TL0 = 0xF5; //16位计数寄存器T0低8位
          ET0 = 1; //T/C0中断开关
          TH1=TL1=0xFD;                       // 波特率9600 (本次测试采用晶振为11.0592)  
              ET1 = 0; //T/C0中断开关
              EA=1;
          TR1 = 1;                                                          //定时器1开始工作,产生波特率                                                                          
              TI=0;//发送标志位置0                                                       
                  RI=0;        //接收标志位置0  
              ES=1;
               
  }
  void write_ds1302_byte(uchar date)        //单字节写
        {  
                uchar i;
                for(i=0;i<8;i++ )
                {
                         sck=0;
                        io=date&0x01;
                        date=date>>1;
                        sck=1;
                }
        }

        uchar read_ds1302(uchar add)
        {
                    uchar i,value;
                        res = 0;
                        _nop_();
                        sck = 0;       
                        _nop_();
                        res = 1;       
                        _nop_();
                        write_ds1302_byte(add);
                        for(i = 0;i<8;i++ )
                          {
                                value = value>>1; //value是字符型
                                sck = 0;
                                if(io == 1)
                                value = value|0x80;
                                 sck = 1;
                          }
                        res = 0;
                         _nop_();
                        sck = 0;
                        _nop_();
                        sck = 1;
                        io = 0;
                        _nop_();
                        return value;
        }
       
  void read_rtc()         //读出时间,存入数组中,十六进制形式
        {
                uchar i;
                for(i= 0;i<7;i++)
                {
                 time_date[i]=read_ds1302(read_add[i]);
                }
        }
  void time_pros0()                  //把读出的时间转化十位个位
        {
               
               
            nian1=time_date[0]/16;
                nian2=time_date[0]%16;
                nian=nian1*10+nian2;
                yue1=time_date[1]/16;
                yue2=time_date[1]%16;
                yue=yue1*10+yue2;
                ri1=time_date[2]/16;
                ri2=time_date[2]%16;
                ri=ri1*10+ri2;
                zhou1=time_date[3]/16;
                zhou2=time_date[3]%16;
                shi1=time_date[4]/16;
                shi2=time_date[4]%16;
                shi=shi1*10+shi2;
                fen1=time_date[5]/16;
                fen2=time_date[5]%16;
                miao1=time_date[6]/16;
                miao2=time_date[6]%16;
        }
       
   void baocun()
  {
          
       
        openri1=ri1;
    openri2=ri2;
    openshi1=shi1;
    openshi2=shi2;
    openfen1=fen1;
    openfen2=fen2;
    openmiao1=miao1;
    openmiao2=miao2;          
  }
   void time_pros()          //存入数组  
        {                                                        
                                        //年       
                disp[0]=nian1+'0';                //十位         
                disp[1]=nian2+'0';                 //个位                 
                disp[2]='-';       
                                                                                        //月
                disp[3]=yue1+'0';   //十位
                disp[4]=yue2+'0';                 //个位                 
                disp[5]='-';       
                disp[6]=ri1+'0';        //日                 
                disp[7]=ri2+'0';
                
                disp[8]=shi1+'0';       
                disp[9]=shi2+'0';
                disp[10]=':';
               
            disp[11]=fen1+'0';
                disp[12]=fen2+'0';
        disp[13]=':';
               
        disp[14]=miao1+'0';
        disp[15]=miao2+'0';               

            dispb[0]='O';               
                dispb[1]='P';
                dispb[2]='E';
                dispb[3]='N';
                dispb[4]=':';
               
                dispb[5]=openri1+'0';
                dispb[6]=openri2+'0';                        //miao       
                dispb[7]=' ';               
               
                dispb[8]=openshi1+'0';
                dispb[9]=openshi2+'0';
                dispb[10]='-';
               
                dispb[11]=openfen1+'0';
                dispb[12]=openfen2+'0';
                dispb[13]='-';
               
                dispb[14]=openmiao1+'0';
                dispb[15]=openmiao2+'0';
        }
                               
void display1()     //
{
        uchar i;
        write_cmd(0x80);      //第一行    实时时间   格式:年-月-日时-分-秒
        for(i=0;i<16;i++)
        {
                write_date(disp[i]);
                delay(30);
        }
        write_cmd(0x80+0x40);       //第二行    开门时间记录
        for(i=0;i<16;i++)
        {
                write_date(dispb[i]);
                delay(10);
        }
    delay(20);               
}

       
void T_C0 (void) interrupt 1           //定时器0中断子程序
   {
   EA=0;          
   d++ ;
           if(d==300)
             {SG1=90;beep=1;}   //舵机归位
       if(d==400)
             {d=0;TR0=0;jw=1;}   //关中断,继电器断开
  if(OUT==0) //判断高低脉冲标志//
          {
          a= 0x0A*SG1+0x01F3;//0x0A是1度的时间长,0x01F3是0.5mS时间长。
          a= 0xFFFF - a;//算出定时开始值
          TH0 = a/0xFF; //16位计数寄存器T0高8位
          TL0 = a%0xFF; //16位计数寄存器T0低8位
          OUT = 1;//标志切换
          PWM_OUT=1;//PWM输出高电平
       }
  else
                {
                a= 0x4E1F - (0x0A*SG1+0x01F3);//0x4E1F是20mS的时间长
                a= 0xFFFF - a;//算出定时开始值
                TH0 = a/0xFF;
                TL0 = a%0xFF;
                OUT = 0;
                PWM_OUT=0;//PWM输出低电平
                }
                EA=1;
}
void ctrl(void)                            //接收处理函数
{
            switch(tmp)
              {
        case '1':     
                        jw=0;
               
                        beep=1;
                        SG1=130;//角度为130度                                            
            TR0 = 1; //T/C0启动开关(定时器)
                //        delay(100);
                        break;                                       
        case '2':       
                    jw=0;                               
         
                        beep=1;
                        SG1=90;//角度为90度
            TR0 = 1; //T/C0启动开关
                    delay(200);
                    break;                                               
         default:                   //其他
                        break;                                             
          }
}               
void main()
{            
     init();
       
          ini1602();        //1602初始化          
          while(1)
          {                                                            
           if(RI==1)                     // 是否有数据到来
               {
                                  EA=0;
                  RI = 0;
                  tmp = SBUF;                 // 暂存接收到的数据                                                                 
                                  EA=1;          
                              ctrl();
                                                  
                            }
                                 read_rtc();
                       time_pros0();  
                                 baocun();
              time_pros();
                           display1();                                       
                  }
}

没看到有TR0=1这句话啊…………没让定时器0开始计时吧。

进入定时器0的时候你不要把总中断EA给关了,只关定时器0的中断就可以了!

main函数的定时器0中断没有打开。

感觉没有中断服务函数呢               

中断服务程序是有的!

开中断是在ctrl函数里的!

在ctrl函数里面有!

调试过程中你可以在特定的地方加入让LED灯闪烁的语句(比如LED^=1,其中LED为某个I/O口的位定义),比如你的这个程序可以在ctrl函数的case0和case1中分别让不同的灯闪烁,通过观察LED灯有没有闪烁就可以直观的发现有没有执行这段程序。我觉得没进中断的原因就是没打开定时器,也就是说每次检测tmp都是执行default那段,也就没执行到TR0=1这句。

你把TH1=TL1=0XFD这句程序分开写,TH1=0XFD,TL1=0XFD。我觉得是这句有问题

主函数中,我只留那么if语句,其他都注释掉,可以进中断,不注释就不进中断

除了if语句就剩下6个函数,这六个函数你每次仅打开一个,看看能不能进中断,也可以试出是哪个函数导致的进不了中断。

现在发现可以进中断,但是进入中断再出来1602显示就不正常了,第一行全亮!第二行全灭!

看了一下不知道什么问题。不过我建议中断函数中不要执行那么长的程序,如果对OUT的状态判断确实要在中断发生时才检测,那可以定义一个标志位在中断函数中置位,然后在主函数的while(1)中检测这个标志位是否置位,如果是,就说明中断发生,然后执行对OUT的状态判断程序。

问题已解决,串口接收将查询法改成了中断法,可以进中断了,谢谢!

嗯。恭喜你!继续加油!

恩,那再看看是不是别的地方写错了

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top