51单片机串口通信中,SCON位寻址,REN=1;SM0=0;SM1=1;为什么串口中断

2019-07-15 11:26发布

  1. <p>#include <reg52.h>  
  2. #include <stdio.h>              //printf头文件  
  3. #define uc unsigned char   
  4. #define uint unsigned int  
  5.   </p><p>uc readByteCounter=0;   

  6. void init()  
  7. {  
  8.    TMOD=0x20;    //定时器工作方式,选择了定时器1,工作方式2 八位初值自动重装的8位定时器。         
  9.    TH1=0xfd;     //定时器1初值  ,设置波特率为9600 晶振11.0529MHZ?  
  10.    TL1=0xfd;  
  11.    TR1=1;        //开启定时器1  
  12. </p><p><font color="red">   REN=1;</font>        //允许串行口接收位  
  13.    <font color="red">SM0=0;</font>  
  14. <font color="red">   SM1=1;</font>        //10位异步接收,(8位数据)波特率可变  
  15.    
  16.    EA=1;         //允许中断(总闸)  
  17.    ES=1;         //允许串口中断  
  18. }  
  19. void main()  
  20. {  
  21.    init();  
  22.    while(1)  
  23.    {  

  24.     }     
  25. }  

  26.   
  27. void ser() interrupt 4  
  28. {  
  29.         if(RI)       //接收数据,手动将RI清0  
  30.         {   </p><p>                RI=0;
  31.                 ES=0;
  32.                 SBUF=readByteCounter;
  33.                 while(ti==0);
  34.                 TI=0;
  35.                 ES=1;
  36.                 readByteCounter++;</p><p>        }      


  37.         if(TI)     //发送数据  
  38.         {  
  39.         }      
  40. }  
  41. </p>
复制代码
我先说现象在设置串行口工作方式SCON的时候,我用的是位寻址顺序为这样
      REN=1;
      SM0=0;
      SM1=1;
每次复位,RI就自动置1,就,进入串口中断了
但是改为
      SM0=0;
      SM1=1;
      REN=1;
就ok

我的理解是这样的:这三位都是串行口控制寄存器SCON里的,单片机刚上电时SCON被清零,因为串口方式为0,穿行口为同步移位寄存器的输入/输出方式,当执行完REN = 1这条语句后,它便直接开始从RXD引脚接收数据,并不管它连接的系统有无发送数据这是SM0和SM1还未被操作,可单片机串口寄存器已经收到数据,并且已经产生了串口中断。REN位置不同,产生的疑问

但是问题来了,我直接
      SM0=0;
      SM1=0;
      REN=1;
或者
      REN=1;
      SM0=0;
      SM1=0;
不会出现复位就进入串口中断的现象??既然是串口方式0所引起的,我直接设为串口方式0,但没有出现位就进入串口中断的现象??和困惑


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
11条回答
上官梦舞
1楼-- · 2019-07-15 15:54
一般串口中断的使能都在各种配置之后,防止你说的还没配置完成就产生了中断。还有一个在开启中断之前应该先清除一下接收中断标志位。
人中狼
2楼-- · 2019-07-15 19:27
这应该是一个单片机复位后如何初始化的问题,以及总中断使能该何时打开的问题
jblbin2008
3楼-- · 2019-07-15 20:52
 精彩回答 2  元偷偷看……
houjue
4楼-- · 2019-07-16 00:47
你换成查询法试试看,我觉得你程序架构有问题。
左天任
5楼-- · 2019-07-16 04:41
本帖最后由 左天任 于 2017-4-11 22:02 编辑
上官梦舞 发表于 2017-4-7 10:36
一般串口中断的使能都在各种配置之后,防止你说的还没配置完成就产生了中断。还有一个在开启中断之前应该先清除一下接收中断标志位。
我试了,加上这两句还是一样  
   TI=0;
   RI=0;
你的观点是:没有配置使能接受可能是为触发中断?但是我加上了接收标志清零RI=0;,还是一样,很奇怪



void init()  
{  
   TMOD=0x20;    //定时器工作方式,选择了定时器1,工作方式2 八位初值自动重装的8位定时器。         
   TH1=0xfd;     //定时器1初值  ,设置波特率为9600 晶振11.0529MHZ?  
   TL1=0xfd;  
   TR1=1;        //开启定时器1  
   TI=0;
   RI=0;
   REN=1;       //允许串行口接收位  
   SM0=0;
   SM1=1;        //10位异步接收,(8位数据)波特率可变   
   EA=1;         //允许中断(总闸)  
   ES=1;         //允许串口中断  
}  

左天任
6楼-- · 2019-07-16 06:09
本帖最后由 左天任 于 2017-4-11 22:34 编辑

所有的代码,我只改变REN,SM0,SM1复制的顺序,运行的结果不同。
一.初始化的时候,这样写,每次复位,RI就自动置1,就,进入串口中断了,和SCON|=0x50赋值不一样
   REN=1;        //允许串行口接收位  
   SM0=0;  
   SM1=1;
二.把串口接受位RI放在工作方式选择SM0,SM1为后面,每次复位,不会进入中断,和SCON|=0x50的效果一样,一切0k
   SM0=0;  
   SM1=1;
   REN=1;        //允许串行口接收位

void init()  
{  
   TMOD=0x20;    //定时器工作方式,选择了定时器1,工作方式2 八位初值自动重装的8位定时器。         
   TH1=0xfd;     //定时器1初值  ,设置波特率为9600 晶振11.0529MHZ?  
   TL1=0xfd;  
   TR1=1;        //开启定时器1  
   REN=1;        //允许串行口接收位  
   SM0=0;  
   SM1=1;        //10位异步接收,(8位数据)波特率可变  
   
   EA=1;         //允许中断(总闸)  
   ES=1;         //允许串口中断  
}  
void main()  
{  
   init();  
   while(1)  
   {  

    }     
}  

  
void ser() interrupt 4  
{  
        if(RI)       //接收数据,手动将RI清0  
        {      
                RI=0;
                readByteCounter++;
         }
        if(TI)     //发送数据  
        {  
        }      
}  


一周热门 更多>