利用PC机串口实现对单片机发送数据控制流水灯显示
作者:贵州民族学院物电学院04级电子班 侯静
指导老师:聂思敏副教授
摘要:介绍如何扩展单片机的片外存储器,如何利用89C51的串行口进行数据的发送和接收,怎样利用P0口扩展输入输出端口。
关键词:2764(8KB/8的非易失性可编程存储器)使用,74HC373地址锁存器的使用,74LS02(8D或非门),RS232的使用。
引言:利用计算机实现对数据的发送和采集,能够及时更新数据,如点阵显示屏,
它能为用户提供了很大的方便。并且利用计算机的串口通讯,技术难度不是很高,
成本也低,因此在不需要长距离、高速传输的情况下,利用串口采集数据是一个很好的选择。
工作原理简单介绍如下:
当89C51的PSEN脚有效时(负脉冲有效),访问片外程序存储器2764,并将2764里面的指令或数据通过P0口线读入单片机中,单片机按照程序指令从PC机接收的数据,并将数据存入反冲区中,然后从反冲区中读取数据写入74HC373的端口,通过改变终端的输入数据而改变流水灯的显示效果,从而达到了灵活控制控制流水灯。系统中的三个74HC373功用不全是一样,一个做为地址所存器,用来扩展片外存储器,另外两个用来扩展输入输出端口。现在来分别介绍:
2764和74HC373的使用:
89C51的P0口在访问片外存储器的时,它分时提供低8位的地址和8位双向数据。因此当74373用作单片机低8位地址线/数据线地址锁存器时,将OE端置低使能,锁存允许信号G受控于单片机的地址有效锁存信号ALE。这样,当外部地址锁存有效信号ALE使G变为高电平时,74373处于直通转态;ALE下降为低电平时,立即将锁存器的输入D0~D7及总线上的低8位地址锁入内部寄存器中。2764的程序存储器有8K(2的13次方=8x1024B及8K),因此地址线有13根,将地址锁存器373的Q0~Q7接2764的A0~A7,P2口的P2.0~P2.4接A8~A12,作为访问2764的地址线,使能端OE与单片机的PSEN端相连,当PSEN端位低电平时,作为访问片外存储器的读选通信号。片选端CE接低,表示选中该2764。
拿P2.n (n=0,1,…7)与 或非来作为另外两个74373的锁存控制信号。当WR写信号端有效时,单片机将数据写入373,并从端口Q0~Q7输出。因此我这里所确定的373的地址非别是7FFFH和BFFFH,这里可参照课后174页的I/O扩展这一节。
电路原理图如下:
单片机与PC机的串行通信
单片机与PC机的串行通信采用RS232标准,使用9脚串行口接头,但是为了简化设计,这里只使用数据线TXD和RXD,其它线为握手信号和控制信号,但在这里没有必要使用。如果想了解RS232标准的更多的相关内容,请查阅相关资料。下面对串行的接线进行讲解。
为了能使PC机和单片机正确的通信,必须要使波特率设置一致,否则将不能正确接收数据。通常选用晶振为11.0592M,因为将波特率为9600时误差较小。
由于我们只使用两根数据线进行连接,所以串行接头与单片机的串行口的连接就非常简单,只要把单片机的TXD引脚与串行接头的3脚相连,RXD引脚与串行接头的2脚相连,串行接头的5脚接地就可以了。其它引脚悬空不管。但单片机串行口输出和输入的是TTL/COMS电平,而PC机串行口输出和输入的是RS232电平,RS-232使用-3到-25V表示数字“1”,使用3V到25V表示数字“0”,所以在单片机与PC机串行口之间必须进行电平转换。MAX232是常用的电平转换器,本系统就是使用MAX232进行电平转换的。如果想了解MAX232的更多内容,请查阅它的数据手册,这里只给出它的连接方法。下面是单片机与串行口的连接图:
上位机PC机的发送\接收程序是用的串口调试软件。
下位机的接收和发送程序如下:
ORG 0000H
SJMP START
ORG 0023H ;串行口中断入口地址
SJMP RECEIVE ;串行口中断接收程序
ORG 0030H
START:MOV R0,#0 ;接收数据计数初值
MOV R1,#30H ;接收数据反冲区的起始地址
MOV R2,#96 ;预设数据反冲区的长度
;波特率设置:波特率位9600 一个起始位,8个数据位和一个结束位
MOV TMOD,#20H
MOV TH1,#0F3H
MOV TL1,#0F3H
MOV SCON,#50H
MOV PCON,#80H
SETB TR1 ;启动定时器1
SETB EA ;中断总允许位
SETB ES ;串行口中断允许位
HERE: SJMP HERE ;等待串行口接收中断
;串行口接收中断子程序
RECEIVE:CLR C
WAIT_R:MOV A,SBUF
MOV @R1,A
INC R1
INC R0
MOV A,R0
SUBB A,R2
JNC LOOP_SEND
RETI
;串行口循环发送子程序
LOOP_SEND:CLR EA ;清除中断
MOV R1,#30H
;循环一次发送两个字节,所以循环次数初值设位R2=R2/2=96/2=48
MOV R2,#48 LOOP_T:MOV A,@R1
MOV DPTR,#7FFFH
MOVX @DPTR,A
MOV SBUF,A
WAIT1_T:JNB TI,WAIT1_T
CLR TI
INC R1
MOV A,@R1
MOV DPTR,#0BFFFH
MOVX @DPTR,A
MOV SBUF,A
WAIT2_T:JNB TI,WAIT2_T
CLR TI
LCALL DELAY
INC R1
DJNZ R2,LOOP_T
MOV R2,#48 ;恢复发送数据反冲区的长度
MOV R1,#30H ;恢复发送数据反冲区的起始位置
AJMP LOOP_T
DELAY: MOV R5,#50
DELAY_2:MOV R6,#50
DELAY_1:MOV R7,#50
DJNZ R7,$
DJNZ R6,DELAY_1
DJNZ R5,DELAY_2
RET
对于上述程序,经过测试有2处疑问:
1:由于AT89C51片内只有128个字节可供用户使用,加上工作寄存器和堆栈的占用,真正的可用空间要低于128个字节,所以接收缓冲区最大长度=128-R1,当大于最大缓冲区长度的时候,存储器溢出,接受的数据有误。
2:如果发送数据的长度很长且不是8的整数倍时,也会出现1中的结果。
总结:
通过这个系统的设计,使我对PC机的串行通信和单片机的串行通信有了进一步的了解,特别是,对波特率的设置有了更清楚的了解。并清楚了怎样编写PC机的串行通信程序及驱动程序。更了解了51单片机外围器件的扩展和使用。
参考文献:单片机初级教程 出版社:北京航天航空大学出版社