51单片机的串行口主要由两个独立的串行数据缓冲寄存器SBUF(发送缓冲寄存器和接收缓冲寄存器)和发送控制器、接收控制器、输入移位寄存器及若干控制门电路组成。
51 单片机可以通过特殊功能寄存器SBUF队串行接收或串行发送寄存器进行访问,两个寄存器共用一个地址99H,但在物理上是两个独立的寄存器,由指令操作决定访问哪一个寄存器。执行写指令时访问串行发送寄存器;执行读指令时,访问串行接收寄存器。(接收器具有双缓冲结构,即在接收寄存器中读出前一个已接收到的字节之前,便能接收第二个字节,如果第二个字节已接收完毕,而第一个字节还没有读出,则将丢失其中一个字节,编程时应引起注意。对于发送器,因为是由 cpu控制的,所以不需要考虑。
与串行口紧密相关的一个特殊功能寄存器是串行口控制寄存器SCON,它用来设定串行口的工作方式、接收/发送控制以及状态标志等。
串行口控制寄存器SCON
串行口控制寄存器SCON在特殊功能寄存器中,字节地址为98H,可位寻址,单片机复位时SCON全部被清零。
位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号 SM0 SM1 SM2 REN TB8 RB8 T1 R1
SM0,SM1为工作方式选择位。串行口有四种工作方式,它们由SM0、SM1设定。其中方式一最为常用。
SM2为多机通信控制位。
REN为允许串行接收位。
TB8为方式2、3中方式数据的第九位。
RB8为方式2、2中接收数据的第九位。
TI为发送中断标志位,在方式0时,当串行发送第8位数据结束时,或在其他方式,串行发送停止位的开始时,由内部硬件使TI置一,向CPU发出中断申请。在中断服务程序中,必须使用软件将其清零,取消此中断申请。
RI为接收中断标志位。在方式0时,当串行接收第8位数据结束时,或在其他方式,串行接收停止位的中间时,由内部硬件使RI置一,向CPU发出中断申请。在中断服务程序中,必须使用软件将其清零,取消此中断申请。
串口工作方式1简介(0、2、3以后再说),串行口方式传送1帧数据共10位,其中一位起始位(0),八位数据位(最低位在前,高位在后),一位停止位(1)。帧与帧之间可以有空闲,也可以无空闲。TXD(P3.1)位数据发送引脚,RXD(P3.0)为数据接收引脚。其传输波特率是可变的,对于51单片机,波特率由定时器1的溢出率决定。
串行口方式1编程与实现
当数据被写入SBUF寄存器后,单片机自动开始从起始位发送数据,发送到停止位的开始时,由内部硬件使TI置1,向CPU申请中断,接下来可在中断服务程序中做相应的处理,也可选择不进入中断。
用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当 RI=0,且SM2=0(或接收到的停止位为1时),将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向 CPU请求中断。
在具体操作串口之前需要对单片机的一些与串口有关的特殊功能寄存器进行初始化设置,主要是设置产生波特率的定时器1、串行口控制和中断控制。具体步骤如下:
1. 确定T1的工作方式(编程TMOD寄存器)
2. 计算T1的初值,载入TH1、TL1
3. 启动T1(编程TCON中的TR1位)
4. 确定串行口工作方式(编程SCON寄存器)
5. 串行口工作在中断方式时,要进行中断设置(编程IE,IP)
/**********************
实现功能:
RS232通信(串口通信)
**********************/
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar flag;
uchar date;
void init()
{
TMOD=0X20;//定时器1工作方式2
TH1=0xfd;//9600
TH0=0xfd;//9600
TR1=1;//启动定时器1
REN=1;//允许串口接收
SM0=0;//设定串口工作方式1
SM1=1;//设定串口工作方式1
EA=1; //开总中断
ES=1;//开串口中断
}
void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0; //关闭串口中断
P1=date;
SBUF=date;
while(!TI);//等待串行发送停止位的开始,TI=1,并向CPU发送中断请求
TI=0;//取消此次中断
ES=1; //开串口中断
flag=0;
}
}
}
void time1() interrupt 4
{
RI=0;//取消中断申请
date=SBUF;
flag=1;
}