51单片机RS232串口多字节收发问题

2020-01-20 19:05发布

最近闲的蛋疼开始琢磨RS232通信的问题,于是陷进去了。我用的是STC12C5A60S2的片子,写了一段最简单的串口通信汇编程序,波特率9600,晶振11.0592M。本来想设计的程序目标程序是在不知情的情况下接收电脑发送的数据字节,然后再接收的数据字节再反发会电脑;就是说随机发送那个字节数据(不事先安排字节收发的个数),然后转发回电脑。程序如下:


;//rs232收发,晶振11.0592,波特率9600,奇偶校验
                       ORG     0000H
                                           AJMP    MAIN
                                           ORG     0023H
                                           AJMP    UART1
;/////////////////////////////////////////////////////////////////////////////////////////
                                           LED0    BIT    P3.0
                                           LED1    BIT    P3.1
;////////////////////////////////////////////////////////////////////////////////////////                                          
                       ORG     0050H
;/////////////////////////////////////////////////////////////////////////////////////////////////////
MAIN:
                                           MOV     IE,     #00H                //禁止所有中断
                       MOV     SCON,   #0D0H    //设置成串口3方式,允许接收数据
                       MOV     TMOD,   #20H     //波特率发生器T1工作在模式2上
                       MOV     PCON,   #80H     //波特率翻倍为4800BPSx2=9600BPS
                       MOV     TH1,    #0FAH    //预置初值(按照波特率4800BPS预置初值)
                       MOV     TL1,    #0FAH    //预置初值(按照波特率4800BPS预置初值)
                       SETB    EA                    //开启总中断
                               SETB    TR1              //启动定时器T1
                        //                   SETB    ES               //允许串口中断
LOOP0:
                                           CPL           LED0                                 //测试通信管脚是否正常
                                           ACALL   DELAY_S
                                           CPL           LED0                                 //测试通信管脚是否正常
                                           ACALL   DELAY_S
                                           CPL     LED1                                 //测试通信管脚是否正常
                                           ACALL   DELAY_S
                                           CPL           LED1                                 //测试通信管脚是否正常
                                           ACALL   DELAY_S
                                           SETB    ES               //允许串口中断
                                           AJMP    $
;/////////////////////////////////////////////////////////////////////////////////////////////////////
UART1:
                                           JNB     RI,    QCBZ
                                           CLR     RI                                  //此处RI的清除必须在这个位置,否则就无法多字节收发
                       MOV     A,     SBUF                  //接收字节到A                                                      
                                           MOV     C,     P
                               MOV     TB8,   C
                                           MOV     SBUF,  A                          //发送字节A
                        //                   ACALL   DELAY_US                                             
QCBZ:                                  
                               CLR     TI
                                           RETI
;/////////////////////////////////////////////////////////////////////////////////////////////////////
;//        延时范围34us--66849786us(66.849786s)                                                                                                                   //
;//        计算公式:S=6+4X+4Y+4XY+8Z+4XYZ+4YZ                                                                                                                           //
;/////////////////////////////////////////////////////////////////////////////////////////////////////
DELAY_S:                MOV    R7,   #10                    //2个机周 Z
DEL1_S:                 MOV    R6,   #200                        //2个机周 Y
DEL2_S:                 MOV    R5,   #250                        //2个机周 X
                        DJNZ   R5,   $                                //4个机周
                        DJNZ   R6,   DEL2_S                        //4个机周
                                DJNZ   R7,   DEL1_S                    //4个机周
                                RET                                                        //4个机周
;/////////////////////////////////////////////////////////////////////////////////////////////////////
;//        延时范围18us--262654us(262.654ms)                                                                                                                           //
;//        计算公式:S=4+4X+6Y+4XY                                                                                                                                                   //
;/////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////18US--262654US(262.654MS)/////////////////////////////////////////////////////////
DELAY_MS:               MOV    R7,   #50                    //2个机周 Y
DEL_MS:                 MOV    R6,   #150                        //2个机周 X
                        DJNZ   R6,   $                           //4个机周
                                DJNZ   R7,   DEL_MS                    //4个机周
                                RET                                                        //4个机周
;/////////////////////////////////////////////////////////////////////////////////////////////////////
;//        延时范围8us--1024us(1.24ms)当X=249时为延时1ms                                                                                                   //
;//        计算公式:S=4+4X                                                                                                                                                       //
;/////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////18US--262654US(262.654MS)/////////////////////////////////////////////////////////
DELAY_US:               MOV    R7,   #249                    //2个机周 X
                        DJNZ   R7,   $                           //4个机周
                                RET
                        END

用串口通信软件发现,单字节收发基本没问题,而且也不会丢包乱码。但是多字节收发就乱码丢包了。


现在问题来了,51单片机是单字节收发数据字节的中断,程序如下:

UART1:
                                           JNB     RI,    QCBZ
                                           CLR     RI                                  //此处RI的清除必须在这个位置,否则就无法多字节收发
                       MOV     A,     SBUF                  //接收字节到A                                                      
                                           MOV     C,     P
                               MOV     TB8,   C
                                           MOV     SBUF,  A                          //发送字节A
                        //                   ACALL   DELAY_US                                             
QCBZ:                                  
                               CLR     TI
                                           RETI

用示波器测试发现,字符串发送的发送是一个字节一个字节的发送的;而发送数据的发送是字节挨着字节的方式发送的,之间没有停顿和间隔(还发现俩者字节都是1MS一个发送的)。在接收到第一个字节的时候中断发生,并处理中断程序,但是第二个字节脉冲紧跟第一个字节脉冲后面,会不会是在第一个中断处理没有结束的时候把第二个脉冲已经错过了或错位检测脉冲了才导致后面数据字节丢包和乱码的?
如果是,那么是不是意思是说51单片机单字节接收的中断不适合做多字节数据的收发?又或者我的程序本身就是BUG?如果是BUG还请大神赐教思路。此问题琢磨我已经快一个星期了,还请高手解救思路。谢谢!!!

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。