单片机串口通信中由晶振频率导致的定时器溢出误差所引发的通信失败

单片机:STC89C52
开发板:普中科技HC6800-ES V2.0
串口调试助手:sscom32
烧录软件:STC


  第一次进行串口通信的时候烧录的程序参照的是买板子时送的资料的例程,虽然最后助手界面显示PC机接收到单片机传来的信号,但是PC机向单片机发送了好几次数据才出现了一次单片机向PC机的通信反馈。
    今天我又重新上机调试,找出了导致通信失败的原因,那就是定时器的溢出误差所导致的波特率误差使得通信失败。
    
    首先,在没有把程序烧录进板子前先不要打开串口调试助手sscom32,这样做调试助手并不能识别出串口号。不过如果打开了也没关系,只要在把程序烧录进板子的操作前把调试助手软件先关闭即可(助手检测到串口后便会占用串口,导致无法烧录)。生成hex文件(由下方的第一段源码生成)并写入板子就可以打开串口助手了(下图是还没有烧录就先打开调试助手所显示的界面)

  如果设置的波特率为9600bps,那么理想的通信速度也是9600bps,但是由于开发板用的是12MHZ的晶振,而并非是11.0592MHZ的晶振,因此计算定时器1的初值时算出的不是一个整数,这样每次累计下来就会导致实际的T1溢出率并非是理想的溢出率,实际上的波特率就不是9600bps,经计算,真实波特率和理想波特率的误差是8.51%(这个误差就是通信失败的原因)   (源程序如下:)
 
 
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="I get ";
uchar a,flag,i;

void Init()
{
    TMOD=0x20;
    TH1=0xfd;TL0=0xfd; //9600bps对应的定时器初值
    SCON=0x50;
    EA=1;                           //总中断打开
    ES=1; //串口中断打开
    TR1=1;                     //开启定时器1
}


void T_R_Serve() interrupt 4 //串口的中断服务程序
{
    RI=0;                           //软件清零串口接收标志位
    a=SBUF;                     //将PC机传入单片机的数据读出
    flag=1;                     //进入中断则产生标志
}

void main()
{
    Init();
    while(1)
    {
        if(flag=1)          //等待PC机发送完数据
        {
            ES=0;            //关闭串口中断,防止进入死循环(不关闭的话单片机每发送完一个数据都要进入中断)
            for(i=0;i<6;i++)         //依次向上位机传送"I get "这6个字符
            {
                SBUF=table[i];
                while(!TI); //每一次都要等待这个字符传送完毕才能开始传送下一个字符,没传送完就一直停留在这里
                TI=0;
            }  
            SBUF=a;                   //把刚才从上位机读取到的数据再作为发送数据传送回去
            while(!TI);
            TI=0;
            flag=0;                     //标志清零,以便可以多次接收上位机传来的数据
            ES=1;                       //重新开启串口中断
        }
    }            
}


接下来用这段源代码所生成的hex文件烧录进板子,并打开调试助手,设置其中的波特率为9600bps,在字符串输入框中输入一个字符(例如b),然后点击发送,就可以看到产生了错误:

发送了10次,每一次发送上位机上接收到的都是乱码,说明通信失败了。

原因在于:调试助手软件选择的通信波特率为9600bps,而实际上单片机的实际波特率并不是9600bps,而是有着8.51%的误差,这样波特率不匹配,就无法成功地通信。

接着可以多调试一些别的波特率,或者改变SMOD的状态来减小误差(串口方式1的波特率=((2^SMOD)/32)×(T1的溢出率) ),下面我再编程用4800bps的波特率和SMOD=1(只需要修改定时器1的初值和在初始化中添加指令PCON=0x80即可),误差降低为0.16%,试试看能否成功通信:

  看到上位机发送了5次数据,每一次都能得到单片机的反馈,说明通信已经成功了。

  再调试一次300bps,SMOD=0的情况,这种情况下波特率误差几乎为0,可以忽略不计。


   效果如下:
  从界面显示看没有任何不同,但实际上300bps的情况下每次由上位机发送数据到单片机传回数据所消耗的时间都比4800bps要长很多。

    如果你的板子出现了通信失败的现象时,可以考虑一下是否是由于晶振频率不同导致的定时器的溢出误差所引发的。

扫描二维码关注公众号,回复: 13101691 查看本文章

   
  

猜你喜欢

转载自blog.csdn.net/chenzz444/article/details/79981688