dongfengge555 发表于 2014-4-13 12:39:15

51单片机外部中断使用求助

大家好
   本人近期在把玩51单片机,在工程里实现一些简单的功能,用到了定时器0中断,串口中断以及外部中断0和外部中断1,现在将详细解释一下:
(问题;在外没有触发外部中断0或者是外部中断1时,串口通信正常,但是当外部一旦触发了外部中断0或者是外部中断1的操作时,串口通信就不正常了,我用串口调试助手发送数据,没有返回。请问各位大神,这个问题出现在哪了?)
   定时器0:用于定时刷新数码管显示,并作1秒计数加1后放在数码管上显示;
   串口中断:用于和外部通信,
   外部中断0:触发方式为低电平,检测到低电平信号时,打开蜂鸣器;
   外部中断1:触发方式为低电平,检测到低电平信号时,关闭蜂鸣器;
   //main.c
#include <reg51.h>
#include "uart.h"
#include "delay.h"
#include "crc.h"
sbit LED_G1 = P2^0;
sbit LED_G2 = P2^1;
sbit LED_G3 = P2^2;
sbit LED_G4 = P2^3;
sbit LED_G5 = P2^4;
sbit LED_G6 = P2^5;
sbit LED_G7 = P2^6;
sbit LED_G8 = P2^7;
sbit SPK    = P1^4;
sbit SMG1 = P1^0;
sbit SMG2 = P1^1;
sbit SMG3 = P1^2;
sbit SMG4 = P1^3;
//共阳段码编码表0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F(本程序中用共阳)
unsigned char code SMG_TabV[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//共阴段码编码表0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F
unsigned char code SMG_TabG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char qian,bai,shi,ge;
unsigned intsmg_count;
unsigned int t0_count;
unsigned char next_c;
extern unsigned char rx_buf;
extern unsigned char rx_count;
unsigned char tx_buf={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};

void timer0_init(void);
void SMG_data(void);
void exit_int01_init(void);
int main()
{
        timer0_init();
        exit_int01_init();
        uart_init();
        EA = 1;//开全局总中断       
        while(1)
        {                 
               if((rx_buf==2)&&(usMBCRC16(rx_buf,rx_count)==0))
               {
                       tx_buf = rx_count;
                        data8_send(tx_buf,9);
                        rx_buf = 0;
                        rx_count= 0;
               }
        }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//定时器0中断入口函数
void timer0_isr(void) interrupt 1 using 1
{
       t0_count++;
       next_c++;
       TH0= 0XF8; //定时2ms,装置数据高8位
       TL0= 0X30; //定时2ms,装置数据低8位
       if(next_c == 1)
       {
              SMG_data();
               P0 = SMG_TabV;
               SMG1 = 1;
               SMG2 = 1;
               SMG3 = 1;
               SMG4 = 0;
       }
       else if(next_c == 2)
       {
               SMG_data();
               P0 = SMG_TabV;
               SMG1 = 1;
               SMG2 = 1;
               SMG3 = 0;
               SMG4 = 1;
       }
       else if(next_c == 3)
       {
               SMG_data();
               P0 = SMG_TabV;
               SMG1 = 1;
               SMG2 = 0;
               SMG3 = 1;
               SMG4 = 1;
       }
       else if(next_c == 4)
       {
               SMG_data();
               P0 = SMG_TabV;       
               SMG1 = 0;
               SMG2 = 1;
               SMG3 = 1;
               SMG4 = 1;
       }
       if(next_c == 4)
       {
               next_c = 0;
       }
}

//定时器0 实现10ms定时初始化
void timer0_init(void)
{
        TMOD = 0X01; //使能定时器0,工作方式1,16位计数
        TH0= 0XF8; //定时2ms,装置数据高8位
        TL0= 0X30; //定时2ms,装置数据低8位
        TR0= 1;       //使能定时器0
        ET0= 1;       //允许定时器0中断
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void exit_int01_init(void)
{
        EX0 = 1;//允许外部中断0开
    IT0 = 0;//电平触发方式,低电平有效,若为1,则为脉冲触发方式,下降沿有效

        EX1 = 1;//允许外部中断1开
    IT1 = 0;//电平触发方式,低电平有效,若为1,则为脉冲触发方式,下降沿有效
}

void int0_isr(void) interrupt 0 using 0
{
        IE0 = 0;
        SPK = 0;//打开蜂鸣器
}

void int1_isr(void) interrupt 2 using 1
{
        IE1 = 0;
        SPK = 1;//关闭蜂鸣器
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SMG_data(void)
{
        if(t0_count == 500)
        {
                t0_count = 0;
                LED_G1 = ~LED_G1;
                LED_G2 = ~LED_G2;
                LED_G3 = ~LED_G3;
                LED_G4 = ~LED_G4;
                LED_G5 = ~LED_G5;
                LED_G6 = ~LED_G6;
                LED_G7 = ~LED_G7;
                LED_G8 = ~LED_G8;
                //数码管显示计数,1秒累加一次
                smg_count++;
                ge   = smg_count%10;
                shi= (smg_count/10)%10;
                bai= (smg_count/100)%10;
                qian = smg_count/1000;
        }
}

以下部分为串口中断//////////////////////////////////////////////////////////////////////////////////////////
unsigned char rx_buf={0};
unsigned char rx_count=0;

void uart_init(void)
{
        SCON= 0X50;//8位UART,波特率可变
        TMOD |= 0X20;//定时器1工作方式2,产生9600 baudrate
        TH1   = 0XFD;//装置波特率参数
        TR1   = 1;       //使能定时器1工作
        ES    = 1;   //便能串口中断       
}

void uart_isr() interrupt 4 using 1
{
        if(RI == 1)                        //判断是接收中断产生
        {
                RI = 0;                        //标志位清零
                rx_buf = SBUF;   //读缓冲区的值                  
        }
    if(TI == 1)                        //如果是发送标志位,清零
        {
                TI=0;
        }
}

void data8_send(unsigned char *tx_dat,unsigned char len)
{
        unsigned char i;
        for(i=0;i<len;i++)
        {
                SBUF = *(tx_dat+i);
                delay_ms(1);
        }
}
问题;
       在外没有触发外部中断0或者是外部中断1时,串口通信正常,但是当外部一旦触发了外部中断0或者是外部中断1的操作时,串口通信就不正常了,我用串口调试助手发送数据,没有返回。请问各位大神,这个问题出现在哪了?
      真的是非常感谢了哦。

zyyn123 发表于 2014-4-13 12:58:50

中断分级别的,外中断0最高,T0第二,外中断1第三,T1第四,串口中断最低。

NemoGu 发表于 2014-4-13 16:49:07

外部中斷使用電平觸發方式,低電平維持時間有多久?

dongfengge555 发表于 2014-4-13 17:00:24

NemoGu 发表于 2014-4-13 16:49
外部中斷使用電平觸發方式,低電平維持時間有多久?

外部有个按键,我用手按下去的。时间应该是足够了

dongfengge555 发表于 2014-4-13 17:48:25

zyyn123 发表于 2014-4-13 12:58
中断分级别的,外中断0最高,T0第二,外中断1第三,T1第四,串口中断最低。 ...

恩是的,分了级别的。呵呵

ourAVR_m16 发表于 2014-4-13 18:28:45

建议设置中断优先级管理寄存器IP,将串行口中断优先级设置为最高后观察效果
页: [1]
查看完整版本: 51单片机外部中断使用求助