串行口的工作方式
8051单片机的全双工串行口可编程为4种工作方式,现分述如下:
一.方式0:
方式0为移位寄存器输入/输出方式。可外接移位寄存器以扩展I/O口,也可以外接同步输入/输出设备。8位串行数据者是从RXD输入或输出,TXD用来输出同步脉冲。
- 输出 串行数据从RXD引脚输出,TXD引脚输出移位脉冲。CPU将数据写入发送寄存器时,立即启动发送,将8位数据以fos/12的固定波特率从RXD输出,低位在前,高位在后。发送完一帧数据后,发送中断标志TI由硬件置位。
- 输入 当串行口以方式0接收时,先置位允许接收控制位REN。此时,RXD为串行数据输入端,TXD仍为同步脉冲移位输出端。当(RI)=0和(REN)=1同时满足时,开始接收。当接收到第8位数据时,将数据移入接收寄存器,并由硬件置位RI。
二.方式1
方式1为波特率可变的10位异步通讯接口方式。发送或接收一帧信息,包括1个起始位0,8个数据位和1个停止位1。
- 输出 当CPU执行一条指令将数据写入发送缓冲SBUF时,就启动发送。串行数据从TXD引脚输出,发送完一帧数据后,就由硬件置位TI。
- 输入 在(REN)=1时,串行口采样RXD引脚,当采样到1至0的跳变时,确认是开始位0,就开始接收一帧数据。只有当(RI)=0且停止位为1或者(SM2)=0时,停止位才进入RB8,8位数据才能进入接收寄存器,并由硬件置位中断标志RI;否则信息丢失。所以在方式1接收时,应先用软件清零RI和SM2标志。
三.方式2
方式二为固定波特率的11位UART方式。它比方式1增加了一位可程控位1或0的第9位数据。
- 输出: 发送的串行数据由TXD端输出一帧信息为11位,附加的第9位来自SCON寄存器的TB8位,用软件置位或复位。它可作为多机通讯中地址/数据信息的标志位,也可以作为数据的奇偶校验位。当CPU执行一条数据写入SUBF的指令时,就启动发送器发送。发送一帧信息后,置位中断标志TI。
- 输入: 在(REN)=1时,串行口采样RXD引脚,当采样到1至0的跳变时,确认是开始位0,就开始接收一帧数据。在接收到附加的第9位数据后,当(RI)=0或者(SM2)=0时,第9位数据才进入RB8,8位数据才能进入接收寄存器,并由硬件置位中断标志RI;否则信息丢失。且不置位RI。再过一位时间后,不管上述条件时否满足,接收电路即行复位,并重新检测RXD上从1到0的跳变。
四.方式3
方式3为波特率可变的11位UART方式。除波特率外,其余与方式2相同。
波特率选择
如前所述,在串行通讯中,收发双方的数据传送率(波特率)要有一定的约定。在8051串行口的四种工作方式中,方式0和2的波特率是固定的,而方式1和3的波特率是可变的,由定时器T1的溢出率控制。
- 方式0
方式0的波特率固定为主振频率的1/12。
- 方式2
方式2的波特率由PCON中的选择位SMOD来决定,可由下式表示:
波特率=2的SMOD次方除以64再乘一个fosc,也就是当SMOD=1时,波特率为1/32fosc,当SMOD=0时,波特率为1/64fosc
3.方式1和方式3
定时器T1作为波特率发生器,其公式如下:
波特率= 定时器T1溢出率
T1溢出率= T1计数率/产生溢出所需的周期数
式中T1计数率取决于它工作在定时器状态还是计数器状态。当工作于定时器状态时,T1计数率为fosc/12;当工作于计数器状态时,T1计数率为外部输入频率,此频率应小于fosc/24。产生溢出所需周期与定时器T1的工作方式、T1的预置值有关。
定时器T1工作于方式0:溢出所需周期数=8192-x
定时器T1工作于方式1:溢出所需周期数=65536-x
定时器T1工作于方式2:溢出所需周期数=256-x
因为方式2为自动重装入初值的8位定时器/计数器模式,所以用它来做波特率发生器最恰当。
当时钟频率选用11.0592MHZ时,取易获得标准的波特率,所以很多单片机系统选用这个看起来“怪”的晶振就是这个道理。
下表列出了定时器T1工作于方式2常用波特率及初值。
常用波特率
|
Fosc(MHZ)
|
SMOD
|
TH1初值
|
19200
|
11.0592
|
1
|
FDH
|
9600
|
11.0592
|
0
|
FDH
|
4800
|
11.0592
|
0
|
FAH
|
2400
|
11.0592
|
0
|
F4h
|
1200
|
11.0592
|
0
|
E8h
|
串行口应用编程实例
1. 串口方式0应用编程 8051单片机串行口方式0为移位寄存器方式,外接一个串入并出的移位寄存器,就可以扩展一个并行口。
例:用8051串行口外接CD4094扩展8位并行输出口,如图所示,8位并行口的各位都接一个发光二极管,要求发光管呈流水灯状态。串行口方式0的数据传送可采用中断方式,也可采用查询方式,无论哪种方式,都要借助于TI或RI标志。串行发送时,可以靠TI置位(发完一帧数据后)引起中断申请,在中断服务程序中发送下一帧数据,或者通过查询TI的状态,只要TI为0就继续查询,TI为1就结束查询,发送下一帧数据。在串行接收时,则由RI引起中断或对RI查询来确定何时接收下一帧数据。无论采用什么方式,在开始通讯之前,都要先对控制寄存器SCON进行初始化。在方式0中将,将00H送SCON就可以了。
ORG 2000H
START: MOV SCON,#00H ;置串行口工作方式0
MOV A,#80H ;最高位灯先亮
CLR P1.0 ;关闭并行输出(避象传输过程中,各LED的"暗红"现象)
OUT0: MOV SBUF,A ;开始串行输出
OUT1: JNB TI,OUT1 ;输出完否
CLR TI ;完了,清TI标志,以备下次发送
SETB P1.0 ;打开并行口输出
ACALL DELAY ;延时一段时间
RR A ;循环右移
CLR P1.0 ;关闭并行输出
JMP OUT0 ;循环
说明:DELAY延时子程序可以用前面我们讲P1口流水灯时用的延时子程序,这里就不给出了。
二、异步通讯
org 0000H
AJMP START
ORG 30H
START:
mov SP,#5fh ;
mov TMOD,#20h ;T1: 工作模式2
mov PCON,#80h ;SMOD=1
mov TH1,#0FDH ;初始化波特率(参见表)
mov SCON,#50h ;Standard UART settings
MOV R0,#0AAH ;准备送出的数
SETB REN ;允许接收
SETB TR1 ;T1开始工作
WAIT:
MOV A,R0
CPL A
MOV R0,A
MOV SBUF,A
LCALL DELAY
JBC TI,WAIT1 ;如果TI等于1,则清TI并转WAIT1
AJMP WAIT
WAIT1: JBC RI,READ ;如果RI等于1,则清RI并转READ
AJMP WAIT1
READ:
MOV A,SBUF ;将取得的数送P1口
MOV P1,A
LJMP WAIT
DELAY: ;延时子程序
MOV R7,#0ffH
DJNZ R7,$
RET
END
将程序编译通过,写入芯片,插入实验板,用通读电缆将实验板与主机的串口相连就可以实验了。上面的程序功能很简单,就是每隔一段时间向主机轮流送数55H和AAH,并把主机送去的数送到P1口。可以在PC端用串口精灵来做实验。串口精灵在我主页上有下载。运行串口精灵后,按主界面上的“设置参数”按钮进入“设置参数”对话框,按下面的参数进行设置。注意,我的机器上用的是串口2,如果你不是串口2,请自行更改串口的设置。
设置完后,按确定返回主界面,注意右边有一个下拉列表,应当选中“按16进制”。然后按“开始发送”、“开始接收”就可以了。按此设置,实验板上应当有两只灯亮,6只灯灭。大家可以自行更改设置参数中的发送字符如55,00,FF等等,观察灯的亮灭,并分析原因,也可以在主界面上更改下拉列表中的“按16进制”为“按10进制”或“按ASCII字符”来观察现象,并仔细分析。这对于大家理解16进制、10进制、ASCII字符也是很有好处的。程序本身很简单,又有注释,这里就不详加说明了。
三、上述程序的中断版本
org 0000H
AJMP START
org 0023h
AJMP SERIAL ;
ORG 30H
START:
mov SP,#5fh ;
mov TMOD,#20h ;T1: 工作模式2
mov PCON,#80h ;SMOD=1
mov TH1,#0FDH ;初始化波特率(参见表)
mov SCON,#50h ;Standard UART settings
MOV R0,#0AAH ;准备送出的数
SETB REN ;允许接收
SETB TR1 ;T1开始工作
SETB EA ;开总中断
SETB ES ;开串口中断
SJMP $
SERIAL:
MOV A,SBUF
MOV P1,A
CLR RI
RETI
END
本程序没有写入发送程序,大家可以自行添加。
|