串行通信基础
计算机通信大多是指计算机与外部设备或者是计算机之间进行相关信息或者数据进行互换、交换。
串行通信主要有并行通信和串行通信两种方式。在两个或者多个微系统交换信息中多采用串行通信方式。
并行通信:通常是将数据字节的各位用多条数据线同时进行数据的传输。控制比较简单,传输速度较快;长距离传输成本较高。
串行通信:是将数据字节分成一位一位的方式在一根传输线上逐个传输;传输速度没有并行通信速度快,长距离传输成本较低。
串行通信方式
AT89C52单片机的串口一共有4种工作方式,其中工作方式0为同步通信方式外,其余的3种均为异步通信方式。本文章主要讲的是异步通信方式中的一种,方式一。
串行通信数据传输的方向
数据传输方向可分为三种:单工、半双工、全双工。
单工指的是数据在传输的时候只能一个方向进行传输,不可以实现反向传输。简单的说就是只能 A的数据传输到B,而B的数据不能传输到A。
半双工指的是数据在传输的时候两个方向都可以进行传输,不过要分时进行。也就是说只有 A的数据传输到B完成以后 B的数据才可以进行传到A。
全双工指的是数据可以同时进行双向传输。也就是在A发送数据给B时,B也可以传送数据个A。
本文主要介绍的是单工通信的使用示例,程序编写与相关的仿真电路设计。
仿真电路设计以及单工传输工作原理
仿真电路通过proteus仿真软件进行设计,矩阵键盘输入1~16数字到单片机A,然后单片机A将数据发送到单片机B,通过单片机B连接的数码管显示出相应的数字。具体电路设计如下图所示:
电路工作原理
如图所示,单片机A、B双机进行串行通信,双机的RXD和TXD相互交叉相连,单片机A的P1 IO口连接矩阵按键,单片机B的P0 IO口连接一个2*8的数码管,数码管段选与位选通过74HC573八路输出锁存器进行控制。单片机A只设置为只能发送数据数据但不能接收数据的单工方式。当单片机A读入到P1口有状态变化后(也就是有数距输入),读取到后通过单片机A串行口发送到单片机B;当单片机B接收到数据后将数据送到P0进行输出显示。其中要注意的一点是双方的晶振频率均为11.0592MHz。
程序编写
在编写相关程序之前我们要先弄清楚单片机A、B两者各要做什么事情。单片机A需要做的是发送数据和按键处理,单片机B需要做的是接收数据和显示相关数据。所以我们编写程序可以分开进行编写。先写单片机A后写单片机B。
单片机A程序编写
单片机A程序编写可以分为两个部分来处理,一是数据发送程序。二是按键处理程序。
主程序
//定义头文件
#include <reg52.h>
//定义相关数据类型
typedef unsigned int u16;
typedef unsigned char u8;
#define DPIO_Key P1 //定义按键IO端口
sbit Key1=P2^2; //数码管停止显示按键
u8 num=0; //存储按键值
u8 dat;
//定义相关子程序
void scen(u8 dat);
void UARTint();
void dis_Key();
void dis();
//毫秒级延时函数
void delay(u16 i)
{
while(i--);
}
//主程序
void main()
{
UARTint();
while(1)
{
dis();
dis_Key();
scen(num);
}
}
按处理程序
//8x8矩阵按键
void dis()
{
u8 a;
DPIO_Key=0x0f;
if(DPIO_Key!=0x0f)
{
delay(1000);// 消抖
if(DPIO_Key!=0x0f)
{
DPIO_Key=0x0f; //列扫描
switch(DPIO_Key)
{
case(0x0e) : num=4;break;
case(0x0d) : num=3;break;
case(0x0b) : num=2;break;
case(0x07) : num=1;break;
}
DPIO_Key=0xf0; //行扫描
switch(DPIO_Key)
{
case(0xe0) : num=12+num;break;
case(0xd0) : num=8+num;break;
case(0xb0) : num=4+num;break;
case(0x70) : num=num;break;
}
while((a<50)&&(DPIO_Key!=0xf0)) //判断是否松开
{
delay(1000);
a++;
}
}
}
}
//数码管停止显示
void dis_Key()
{
if(Key1==0)
{
delay(1000); //消抖
if(Key1==0)
{
num=0;
}
while(!Key1); //判断按键是否松开
}
}
串行通信发送数据程序
//串口通信初始化
void UARTint()
{
TMOD=0x20; //设置定时器1的工作方式,8位自动重装
TH1=253;
TL1=253; //设置9600比特率
TR1=1; //启动定时器1
PCON=0x00; //设置比特率不倍增
SCON=0x40; //设置通信方式一,并设置成禁止接收数据
}
//发送数据
void scen(u8 dat)
{
SBUF=dat; //将需要发送的数据赋给SBUF发送寄存器进行发送
while(TI==0); //判断数据是否发送完成,TI是发送标志位
TI=0; //软件清零数据发送完成标志位
}
单片机B程序编写
单片机B程序编写也可以分为两个部分来编写,一是数码管显示程序,二是串行口数据接收程序。
主程序
//定义头文件
#include <reg52.h>
//定义数据类型
typedef unsigned int u16;
typedef unsigned char u8;
#define LED P0 //数码管段码位码输出
sbit duan=P2^0; //段码输出选择
sbit wei=P2^1; //位码选择输出
u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //定义数码管位码
u8 code smgwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义数码管段码0~9
u8 shi,ge; //数据拆分收存储值
u8 dat; //数据接收存储变量
//定义相关子程序
u8 receive();
void UARTint();
void dispaly();
//毫秒级延时函数
void delay(u16 i)
{
while(i--);
}
//主程序
void main()
{
UARTint(); //串行口初始化
while(1)
{
dispaly(); //调用数码管显示程序
receive(); //调用串行口接收程序
}
}
数码管显示程序
void dispaly()
{
if(dat==0) //当dat变量等于0时数码管不显示,否则就显示数值
{
LED=0xff; //消隐
wei=1;
LED=smgwei[0]; //发送位码
wei=0;
duan=1;
LED=0x00; //发送段码
duan=0;
delay(50);
LED=0xff; //消隐
wei=1;
LED=smgwei[1]; //发送位码
wei=0;
duan=1;
LED=0x00; //发送段码
duan=0;
delay(50);
}
else //当dat不等于0数码管显示相应数值
{
LED=0xff; //消隐
wei=1;
LED=smgwei[0];
wei=0;
duan=1;
LED=smgduan[shi]; //显示十位
duan=0;
delay(50);
LED=0xff; //消隐
wei=1;
LED=smgwei[1];
wei=0;
duan=1;
LED=smgduan[ge]; //显示个位
duan=0;
delay(50);
}
}
数据接收程序
void UARTint()
{
wei=0;
duan=0;
TMOD=0x20; //设置定时器1的工作方式,8位自动重装
TH1=253;
TL1=253; //设置9600比特率
TR1=1; //启动定时器1
PCON=0x00; //设置比特率不倍增
SCON=0x50; //设置通信方式一,并且设置成允许接收模式
}
u8 receive() //带返回参数的数据接收程序
{
while(RI==0); //RI接收标志
{
RI=0;
}
dat=SBUF; //接收数据存储到dat
shi=dat/10; //数据拆分出十位
ge=dat%10; //数据拆分出个位
return dat; //将数据返回出去,存储到dat变量
}
以上就是单工串行通信的资料,写的不好,有不懂的和意见都可以留言哦。大家也可以根据这个实力进行修改成半双工的串行通信。