最近闲的蛋疼开始琢磨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还请大神赐教思路。此问题琢磨我已经快一个星期了,还请高手解救思路。谢谢!!!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>