串行通信:将数据字节分为一位一位的形式在一条数据线上逐个传送
串行通信特点:传输线少,长距离传送时成本低,且可以利用电话网等现成设备,但数据的传送控制比并行通信复杂
并行通信:通常是将数据字节的各位用多条数据线同时进行传送
串行工作方式
方式1:是一帧10位的异步串行通信方式,包括1个起始位,8个数据位和一个停止位。
其帧格式为:
(1)数据发送
发送时只要将数据写入SBUF,在串行口由硬件自动加入起始位和停止位,构成一个完整的帧格式。然后在移位脉冲的作用下,由TXD端串行输出。一帧数据发送完毕,将SCON中的TI置1。
(2)数据接收
接收时,在REN=1前提下,当采样到RXD从1向0跳变状态时,就认定为已接收到起始位。随后在移位脉冲的控制下,将串行接收数据移入SBUF中。一帧数据接收完毕,将SCON中的RI置1,表示可以从SBUF取走接收到的一个字符。
串行工作方式2、方式3
方式2、3是一帧11位的串行通信方式,即1个起始位,8个数据位,1个可编程位TB8/RB8和1个停止位。
其帧格式为:
起始
数据发送和接收:
数据发送和接收与方式1基本相同,区别在于方式2把发送/接收到的第9位内容送入TB8/RB8。
波特率:方式2波特率固定,即fosc/32和fosc/64。 如用公式表示则为:
波特率=2^SMOD ╳ fosc/64
通过串口进行实验:
发送机:
#include<reg51.h>
unsigned char code str1[]="15000101"; //设置需要发送的协议代码
unsigned char code str2[]="15000102";
unsigned char code str3[]="15000103";
sbit P1_0=P1^0; //给相应端口一个编号
sbit P1_1=P1^1;
sbit P1_2=P1^2;
//函数的功能是:向PC端发送一个字节数据
void send(unsigned char dat)
{
SBUF=dat;
while(TI==0);
TI=0;
}
void delay(unsigned int n) //延时函数的设置
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=249;j>0;j--)
;
}
void main(void)
{
unsigned int i;
TMOD=0x20; //TMOD=0010 0000,设置定时器T1工作于方式二
SCON=0x60; //SCON=0100 0000,设置串口的工作方式为方式1
PCON=0x00; //PCON=0000 0000,波特率为9600 晶振为11.0592
TH1=0xfd; //设置定时器T1的初值
TL1=0xfd; //定时器T1自动填充的值
TR1=1; //启动定时器T1
while(1)
{
if(P1_0==0) //判断P1_0口的开关状态
{
i=0;
while(str1[i]!='\0') //循环发送相应数组中的数据
{
send(str1[i]);
i++;
delay(1);
}
send('\0'); //最后一位补上\0作为接收机判断结束的标准
delay(1000);
}
else if(P1_1==0) //判断P1_1口的开关状态
{
i=0;
while(str2[i]!='\0') //循环发送相应数组中的数据
{
send(str2[i]);
i++;
delay(1);
}
send('\0'); //最后一位补上\0作为接收机判断结束的标准
delay(1000);
}
else if(P1_2==0) //判断P1_2口的开关状态
{
i=0;
while(str3[i]!='\0') //循环发送相应数组中的数据
{
send(str3[i]);
i++;
delay(1);
}
send('\0'); //最后一位补上\0作为接收机判断结束的标准
delay(1000);
}
}
}
接收机:
#include<reg51.h>
#define uchar unsigned char
uchar temp,flag;
uchar a[10];
uchar count=0;
void main()
{
TMOD=0x20; //定时器T1工作于方式2
SCON=0x40; //SCON=0100 0000B,串口工作方式1
PCON=0x00; //PCON=0000 0000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
REN=1; //允许接收
EA=1; //开起总中断开关
ES=1; //需要用到串行口的中断所以ES=1就是把串行口的中断打开了
while(1) //进入循环
{
if(flag==1) //等待中断的来临,然后flag就会被赋值为1
{
if(a[7]==0x31) //如果发送的数据最后一位为1的话(“15000101”最后一位1
P1=0xFE; //对应的就是十六进制的0x31) 0xfe对应1111 1110 就第
//一盏灯亮
else if(a[7]==0x32) //以此类推
P1=0xFD;
else if(a[7]==0x33) //以此类推
P1=0xFC;
else
P1=0x00; //发送为其他数据时灯全亮
flag=0;
}
}
}
void serial() interrupt 4 //设置中断函数
{
temp=SBUF; //当有中断时把传过来的数据暂存到temp中
RI=0; //把设置中断的标志初始化,等待下一中断
if(temp==0x00) //当到达最后一位
{
a[count]=temp;
count=0; //计数器初始化为下一次中断准备
flag=1; //标志置1进入主函数,进行端口的赋值
}
else
{
a[count]=temp;
count=count+1;
}
}
如上代码段为网上教学所提供,有错误请指出