关于51单片机串口通信的问题

2019-07-15 09:27发布

    最近在学校用单片机做一个小项目,在涉及到串口通信这部分是遇到了一些问题,希望论坛的前辈们可以给我一些指点。    单片机串口通信分为接收与发送两种情况,其数据单位都是1个字节。也就是说,每接收/发送一个字节,单片机的RI/ti位会置1从而选择是否进入中断。以最基本的使用“串口助手”实现PC与单片机的串口通信为例:
1.jpeg
如图是PC从串口助手发送一个字符到单片机,再由单片机返回该字符的例程结果。该字符'1'的数据流图应该是从PC端进入到单片机的SBUF寄存器中去,当单片机接收到该字符的结束位时,单片机将RI置1,表示接收完毕。同理,在发送到该字符的结束位时,单片机将TI置1,表示发送完毕。
但当发送多个字符的情况时,我对串口通信的数据传输过程有了疑惑:
22.jpeg
如图,当从PC发送多个字符时(问题1:这里是否可以理解为字符串的串口通信),仍然可以完美的实现PC与单片机之间的数据互通。而程序仍然与之前一样没有改动(总程序见下)。这时我产生了疑惑,就单片机而言,无论接收还是发送,都是以一个字符为单位进行操作,当面对多个字符的传输时,它是先将所有字符依次接收到SBUF中去,然后将接收到的多个字符再依次发送出去?还是每接收一个字符,就立马发送一个字符?(问题2:是实时传输单个字符还是缓存所有数据后再进行处理),比如在处理“1a!”时,当单片机SBUF接收到'1',立刻就将'1'从SBUF中发送出去,然后再对'a'进行接收......
    我认为是后者的情况,因此我想利用LCD1602进行验证。我的思路是:既然单片机是每接收一个字符,就发送一个字符,那我可以定义一个数组,在单片机的接收中断中(由RI==1触发的中断)存储每次SBUF接收的数据,为了验证方便,我假设每次传输的都是3个字符。中断程序如下:
#define DATA_LENGTH 3
uchar Receivedata[];
uchar ReData,Flag1,Flag2;
uint i,j;

void ser_int (void) interrupt 4
{
if(RI == 1)        
{
         RI = 0;                    
        ReData = SBUF;  
        Receivedata=ReData;
        i++;
        if(i==DATA_LENGTH)
        {
        i=0;
        Flag1=1;       //代表3个字符接收完毕
        }
        Flag2=1;       //代表当前字符接收完毕
}
}

如果说单片机是每接收到一个字符就发送它,按照这个中断,最后Receivedata[]应该是一个存储了“1a!”长度为3的字符类型的数组。
接下来我们只要将数组中的字符元素依次显示在LCD1602上就可以证明猜想,以下为主程序:
void main (void)
{
init_time();                //初始化定时器中断
init_1602();               //初始化LCD1602
write_com(0x80);     //选定开始显示的位置是第一行第一列
           while(1)
        {
        if(Flag2==1)
        {
        SBUF = ReData;                     
        while(TI==0);
        TI=0;               
        Flag2=0;
        if(Flag1==1)
        {
        for(j=0;j<3;j++)
       {
       write_dat(Receivedata[j]);
        }
       Flag1=0;
        }
        }
        }                                                                              
}


但最后程序烧录后结果并不理想,当从PC送入三个字符时,LCD并不能正常显示这三个字符,而且串口助手接收也出现了问题。
4.jpeg
3.jpeg
验证行动就此夭折,出现这种情况,首先说明数组Receivedata中并没有正确的存储SBUF中的字符。另外在增加LCD显示模块的过程中,影响了串口通信的准确度。

在此,我希望仔细看过该问答的前辈们指出我的错误,或者回答上面红字标出的问题。另外,新的问题也从验证的过程中产生(问题3,如何将多个字符或者字符串完整的存储下来或进一步显示在1602上?

在我编程的过程中一定忽视了一些致命的问题,恳请赐教!

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
8条回答
人中狼
2019-07-15 18:38
这里有两个概念,一个是发送数据的帧结构,一个是发送数据的数据包结构,串行通讯是按帧发送和接收的,也就是每次发送和接收都是一个字节。数据包的结构是有一定约束的,比如数据包的包头字符,代表数据包的开始,数据包的结束字符,代笔数据包的接收结束。
对于数据包的结构,可以参考modbus-rtu的报文格式来理解。

评分

参与人数 1积分 +10 收起 理由 ElecFans王岑 + 10

查看全部评分

一周热门 更多>