打印

关于串口中断的问题?

[复制链接]
6613|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sinianzain|  楼主 | 2012-10-2 15:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sinianzain 于 2012-10-2 15:14 编辑

#include<reg52.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
void INIT_UART(void);
uchar DATA;
uchar code *ptr="Yes,man!";
void main(void)
{
uchar i;
INIT_UART();
while(1)
{
    if(!RI)                                   //判断是否进入过串口接收中断                                    
    {
        for(i=0;i<strlen(ptr);i++)   //向缓冲区发送数据
        {
            SBUF=ptr;
            while(!TI);                     //等待,是否发送完毕
                 TI=0;
         }
    }
}
}

void INIT_UART(void)
{
    TMOD|=0x20;    //定时器T1工作方式为2
    TH1=0xfd;         //T1封装初值,波特率为9600,晶振频率为11.0592.
    TL1=0xfd;
    SCON=0x50;    //(SM0=0/SM1=1(串口工作方式为1);REN=1(启动串口中断);)
   
    EA=1;
    ES=1;           
    ET1=1;
    TR1=1;
}

void INTERRUPT_UART(void) interrupt 4
{
    if(RI)                  //判断是否为接收中断
    {
        RI=0;             //RI清0,便于下次进入中断
        DATA=SBUF;   //读取缓冲区数据
        P1=DATA;       //将缓冲区的数据输出到P1口
        SBUF=DATA;   //把接收到的数据再发回电脑端
    }

    if(TI)                  //判断是否为发送中断
        TI=0;
}

在上面的程序中我选择让数据发送和数据接收都进串口中断,但是有些地方不明白,请指点,谢谢!
1、在发送完一个字节后,进入接收中断,也就是中断中的if(TI)部分,可是明明在中断中我已经将这个发送中断标志位清0,可为什么还要在返回中断现场时继续清0(main()函数中的TI=0),当我去掉中断现场的哪个TI=0,每次只显示Y m这两个字母?
2、RS232是全双工串口,那么这个发送中断和接收中断是否也是像数据发送和接收一样可以同时进行呢,或者是没发送一个字节便立刻接收一个字节?

相关帖子

沙发
sinianzain|  楼主 | 2012-10-2 15:20 | 只看该作者
在上面的程序中我选择让数据发送和数据接收都进串口中断,但是有些地方不明白,请指点,谢谢!
1、在发送完一个字节后,进入接收中断,也就是中断中的if(TI)部分,可是明明在中断中我已经将这个发送中断标志位清0,可为什么还要在返回中断现场时继续清0(main()函数中的TI=0),当我去掉中断现场的哪个TI=0,每次只显示Y m这两个字母?
2、RS232是全双工串口,那么这个发送中断和接收中断是否也是像数据发送和接收一样可以同时进行呢,或者是没发送一个字节便立刻接收一个字节?

下面是我想只让数据接收进中断的部分:
void main(void)
{
uchar i;
INIT_UART();
while(1)
{
    if(!RI)                                     //判断是否进入过串口接收中断                                    
    {
        ES=0;                                 //关串口中断
         for(i=0;i<strlen(ptr);i++)   //向缓冲区发送数据
        {
            SBUF=ptr;
            while(!TI);                     //等待,是否发送完毕
                 TI=0;
         }
         ES=1;                             //开串口中断
    }
}
}

void INTERRUPT_UART(void) interrupt 4
{
        RI=0;             //RI清0,便于下次进入中断
        DATA=SBUF;   //读取缓冲区数据
        P1=DATA;       //将缓冲区的数据输出到P1口
        SBUF=DATA;   //把接收到的数据再发回电脑端
}

虽然实验现象和第一个函数相同,达到实验目的了,但是有一点想不通,既然在发送数据前将中断关闭了,发送完整个字符串才开的中断,那是不是说SBUF可以将所有发送的字符串先暂存,然后等中断打开后(ES=1)才进行接收中断吗?

使用特权

评论回复
板凳
NE5532| | 2012-10-2 15:45 | 只看该作者
1.楼主既然用的是中断方式,主循环里怎么会有查询TI标志和清TI标志出现呢?楼主单片机中断章节不及格,打回重修!

2.全双工串口可同时收发,不存在谁先谁后。

使用特权

评论回复
地板
sinianzain|  楼主 | 2012-10-2 16:00 | 只看该作者
3# NE5532
我用中断时只显示Y m两个字母,但是在主函数中加while(!TI);TI=0;后就正常了,我就是这里不理解啊!

使用特权

评论回复
5
NE5532| | 2012-10-2 16:05 | 只看该作者
3# NE5532
我用中断时只显示Y m两个字母,但是在主函数中加while(!TI);TI=0;后就正常了,我就是这里不理解啊!
sinianzain 发表于 2012-10-2 16:00


当你犯了原理性的错误以后,应该从原理性上去改正,而不是在错误的基础上继续分析,既然已经知道中断不该在外面有标志判断,就改正。

你要死纠缠在这个程序为什么会这样执行上面,需要更高的功力才能解释清楚,我能分析出来,但是我不想去分析,因为对我对你都没有作用,我建议你在正确的方法基础上去研究怎么改对。

使用特权

评论回复
6
sinianzain|  楼主 | 2012-10-2 16:08 | 只看该作者
本帖最后由 sinianzain 于 2012-10-2 16:12 编辑

5# NE5532
既然能找出原因,那何不讲讲,新手有时候就会很纠结某些问题上,还请不吝赐教!
中断没有问题,应该是发送和读取时间上的问题,发送后加个延时应该能解决。

使用特权

评论回复
7
NE5532| | 2012-10-2 16:12 | 只看该作者
因为我不需要找这种原因来证明我的能力,在你没搞懂中断原理的情况下给你讲了对你成长也无益,我曾经尝试过给一个研究生分析串口上奇怪的现象,最后的结果就是把他给吓辞职了…………

所以楼主还是从正确的道路上思考问题吧,这也是各路高手的共识。

使用特权

评论回复
8
sinianzain|  楼主 | 2012-10-2 16:18 | 只看该作者
7# NE5532
1、我是彻底的业余者,所以来论坛里虚心请教,只要能回答问题的我都尊敬,对第一个回答我先表感谢;
2、你来这个地方是想证明自己能力给别人看吗,答不答无所谓,什么研究生什么辞职,和回答问题有关系吗?我认为有能力的人会直接之处问题给出原因和解决办法,比扯这么多更有说服力吧!

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
hp34401a + 1 同意,有例程讲解方便很多!
9
NE5532| | 2012-10-2 16:24 | 只看该作者
不要妄图用激将法让我帮你看程序哈,早就习惯了。

不给你看程序原因很简单,因为世界上正确的路只有1条,错误的路由千千万,人的生命长度有限,所以我们只能在正确的路上走,如果把所有错误的路都走一遍,我们一生就做不了几件事了。

使用特权

评论回复
10
sinianzain|  楼主 | 2012-10-2 16:40 | 只看该作者
9# NE5532
你想多了,我这个帖子你可以不用回不用看了。

使用特权

评论回复
11
darlin520| | 2012-10-2 17:59 | 只看该作者
我们作为新手还是谦虚点好,论坛里的前辈只是提供给我们一个思路,既然犯了常识性的错误就应该敢于承认,记住这里的人没有义务为你回答问题。

使用特权

评论回复
12
darlin520| | 2012-10-2 18:07 | 只看该作者
不妨试试这样:
void INTERRUPT_UART(void) interrupt 4
{
    if(RI)  
{
           DATA=SBUF;   //读取缓冲区数据
        P1=DATA;       //将缓冲区的数据输出到P1
            RI=0;
    }  
  esle
{
    SBUF=DATA;
     TI=0;
     }
}

使用特权

评论回复
13
sinianzain|  楼主 | 2012-10-2 18:32 | 只看该作者
本帖最后由 sinianzain 于 2012-10-2 18:34 编辑

11# darlin520 话到是对,我知道这个是常识性错误,只是不明白为什么按照正确的调试不出结果,却这个很明显错误的却有结果,所以才真心请教的。

使用特权

评论回复
14
sinianzain|  楼主 | 2012-10-2 18:39 | 只看该作者
12# darlin520 谢谢回答。
这里应该没用问题,关键是为什么在中断中已经将数据发送位清0却在主函数中还要写上才能调试正确;还有另一个是主函数中已经在for循环前关闭中断了,可是SBUF好像只能接收一个字节的数据,也就是说每次发送数据后必须被读取,而这个读取就必须要进中断,似乎程序也的确进了中断了,但是开中断的语句却在整个for循环之后,这里岂不是矛盾了?

使用特权

评论回复
15
darlin520| | 2012-10-2 19:41 | 只看该作者
我明白你意思了,原因很简单,因为你的
void INTERRUPT_UART(void) interrupt 4
{
    if(RI)                  //判断是否为接收中断
    {
        RI=0;             //RI清0,便于下次进入中断
        DATA=SBUF;   //读取缓冲区数据
        P1=DATA;       //将缓冲区的数据输出到P1口
        SBUF=DATA;   //把接收到的数据再发回电脑端
    }

    if(TI)                  //判断是否为发送中断
        TI=0;
}
这个函数里的if(TI)TI=0;
根本就是多余的,你发送数据的时候既然用了查询为什么还要用中断,你觉得发送的时候能进入中断吗

使用特权

评论回复
16
darlin520| | 2012-10-2 19:52 | 只看该作者
你是在用查询方式发送完以后才打开的串口中断ES=1;建议能还是好好看看程序。

使用特权

评论回复
17
hlshhpy| | 2012-10-2 20:47 | 只看该作者
看不懂泡吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

17

帖子

0

粉丝