串行通信是将数据字节分成一位一位的形式在一条传输线上逐个地传送。
控制寄存器两个:特殊功能寄存器SCON和PCON。通过对串行口控制寄存器SCON和电源控制寄存器PCON的编程,可以控制串行口的工作方式和波特率。
- TI—发送中断标志位 TI =1,表示一帧数据发送结束。 CPU响应中断后,在中断服务程序中向SBUF写入要发送的下一帧数据。
方式0,串行发送的第8位数据结束时TI由硬件置“1”.
在其他方式中,串行口发送停止位的开始时置TI 为“1”,TI必须由软件清“0”. - RI—接收中断标志位 RI=1,表示一帧数据接收完毕,并申请中断,要求CPU从接收SBUF取走数据。
方式0时,接收完第8位数据时,RI由硬件置“1”。
在其他工作方式中,串行接收到停止位时,该位置“1”。RI必须由软件清“0”。
- 方式0:同步移位寄存器输入/输出方式。该方式并不用于两个AT89S51单片机之间的异步串行通信,而是用于串行口外接移位寄存器,扩展并行I/O口。
- 方式1:串行口设为方式1的双机串行通信。TXD脚和RXD脚分别用于发送和接收数据。
- 方式2\方式3:方式2和方式3,9位异步通信接口。每帧数据为11位,既可以用于双机通信也可用于多机通信。用于双机通信时第九位数据作为奇偶校验位。用于多机通信时第九位数据作为数据帧/地址帧的标识位。
方式0:扩展并行I/O口
在单片机系统中,如果并行口的IO资源不够,那么我们可以使用74LS164来扩展并行IO口,节约单片机IO资源。74LS164是一个串行输入并行输出的移位寄存器,并带有清除端。
程序(工作方式0扩展出8位并行I/O口,驱动共阳LED数码管循环显示0—9,间隔1秒。)
#include<reg52.h>
#define u8 unsigned char
#define u16 unsigned int
u8 code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e
};
u8 i=0;
//延时函数
void delay(u16 x){
u16 i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void main(){
SCON=0x00;//选取工作方式0
EA=1;//全局中断
ES=1;//串口中断
SBUF=table[i];//读缓冲区数据
while(1);
}
void t4() interrupt 4{
if(TI==1){
delay(1000);
i=i+1;
if(i==10)i=0;
SBUF = table[i]; //写缓存区数据
}
TI=0;//为方式0,可不清零。
RI=0;
}
双机串行通信
#include<reg52.h>
#define u8 unsigned char
#define u16 unsigned int
void init(){
PCON=0x00;
SCON=0x90;//串行口方式2
EA=1;
ES=1;
}
void main(){
init();
while(1){
SBUF=P1;//缓冲区存储数值
while(TI==0){
SBUF=P1;
}
TI=0;
P0=SBUF;//P0赋值
while(RI==0){
P0=SBUF;
}
RI=0;
}
}
虚拟串口
COMPIM
方式3
/*------------------------------------------------
串口初始化函数
------------------------------------------------*/
void init_com(unsigned int bps)
{
u8 t;
EA=1; //开总中断
ES=1; //允许串口中断
ET1=1; //允许定时器T1的中断
TMOD=0x20; //定时器T1,在方式2中断产生波特率
PCON=0x00; //SMOD=0
SCON=0x50; // 方式1 由定时器控制 (0101 8位异步收发,定时器控制波特率 REN=1 允许接收)
switch(bps) //波特率的设定选择
{
case 1200:t=0xe8;break;
case 2400:t=0xf4;break;
case 4800:t=0xfa;break;
case 9600:t=0xfd;break;
}
TH1=t;
TL1=t;
TR1=1; //开定时器T1运行控制位
}
/*------------------------------------------------
把读取值转换成一个一个的字符,给串口显示 (两位小数)
------------------------------------------------*/
void To_ascii(unsigned char num)
{
SBUF=num/100+'0';
delay(200);
SBUF=num/10%10+'0';
delay(200);
SBUF=num%10+'0';
delay(200);
}