单片机串口中断控制流水灯c语言,利用PC机串口实现对单片机发送数据控制流水灯显示...

利用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的更多内容,请查阅它的数据手册,这里只给出它的连接方法。下面是单片机与串行口的连接图:

070507145100.jpg

上位机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单片机外围器件的扩展和使用。

参考文献:单片机初级教程 出版社:北京航天航空大学出版社

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、一盏一盏:第一盏灯先亮--延时--熄灭--延时--下一盏灯; 2、利用数组方法点亮:定义一个数组(即0xfe,0xfd,0xfb,0xf7,0xef,oxdf,0xbf,0x7f:依次代表只有第一盏灯,第二盏灯....亮),再利总线,按顺序点亮八盏灯; 3、利用移位方法点亮:(1)、利用移位运算和按位或运算,依次点亮八盏灯; (2)、包含intrins头文件(里面含有移位函数),使用相应的左移或右移函数进行移位, 下面是代码和注释,详细解释了点亮流水灯的思路,附件含有源代码和仿真文件,有需要的可以下载 //方式0控制流水灯循环点亮 #include //包含51单片机寄存器定义的头文件 #include //包含函数_nop_()定义的头文件 unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码,该数组被定义为全局变量 sbit P17=P1^7; /************************************************************** 函数功能:延时约150ms **************************************************************/ void delay(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<250;n++) ; } /************************************************************** 函数功能:发送一个字节的数据 **************************************************************/ void Send(unsigned char dat) { P17=0; //P1.7引脚输出清0信号,对74LS164清0 _nop_(); //延时一个机器周期 _nop_(); //延时一个机器周期,保证清0完成 P17=1; //结束对74LS164的清0 SBUF=dat; //将数据写入发送缓冲器,启动发送 while(TI==0) //若没有发送完毕,等待 ; TI=0; //发送完毕,TI被“1”,需将其清0 } /******************************************* 函数功能:主函数 ******************************************/ void main(void) { unsigned char i; SCON=0x00; //SCON=0000 0000B,使串行口工作于方式0 while(1) { for(i=0;i<8;i++) { Send(Tab[i]); //发送数据 delay(); //延时 } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值