一.写在前面
随着计算机系统的应用和微机网络的发展,通信功能越来越显得重要.这里所说的通信是指计算机与外界的信息交换.因此,通信既包括计算机与外部设备之间,也包括计算机和计算机之间的信息交换.由于串行通信是在一根传输线上一位一位的传送信息,所用的传输线少,并且可以借助现成的电话网进行信息传送,因此,特别适合于远距离传输.对于那些与计算机相距不远的人-机交换设备和串行存储的外部设备如终端、打印机、逻辑分析仪、磁盘等,采用串行方式交换数据也很普遍.在实时控制和管理方面,采用多台微机处理机组成分级分布控制系统中,各 CPU 之间的通信一般都是串行方式.所以串行接口是微机应用系统常用的接口。许多外设和计算机按串行方式进行通信,这里所说的串行方式,是指外设与接口电路之间的信息传送方式,实际上,CPU 与接口之间仍按并行方式工作.
所以本次测试主要是围绕着两个C51单片机之间的串口通讯。
C51有一个可编程全双工异步串行通信接口(UART),管脚TXD(P3.1)RXD(P3.0);可以同时发送和接受数据,有四种工作方式,帧格式有8,10,11位。
1、89c51串行口特点
※全双工串口,能同时发送和接收数据
※可编程:其帧格式可以是8位,10位,11位,并能设置各种波特率
※发送完一个数据TI标志置1,接受完一个数据RI标志置1,可以工作在中断或查询方式
※波特率可以是固定的,也可以是由定时器1的溢出率来决定
※有一个地址相同的接受(发送)缓冲器SBUF(地址99H)
2.SCON—-串行通信控制寄存器
它是一个可寻址的专用寄存器,用于串行数据的通信控制,单元地址是98H,其结构格式如下:
SCON 串行通信控制寄存器 | ||||||||
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
(1)SM0、SM1:串行口工作方式控制位。
SM0,SM1 工作方式
00 方式0-波特率由振荡器频率所定:振荡器频率/12
01 方式1-波特率由定时器T1或T2的溢出率和SMOD所定:2SMOD ×(T1溢出率)/32
10 方式2-波特率由振荡器频率和SMOD所定:2SMOD ×振荡器频率/64
11 方式3-波特率由定时器T1或T2的溢出率和SMOD所定:2SMOD ×(T1溢出率)/32
(2)SM2:多机通信控制位。< br> 多机通信是工作于方式2和方式3,SM2位主要用于方式2和方式3。接收状态,当串行口工作于方式2或3,以及SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接收到的前8位数据送入SBUF,且置位RI发出中断申请,否则会将接受到的数据放弃。当SM2=0时,就不管第位数据是0还是1,都难得数据送入SBUF,并发出中断申请。
工作于方式0时,SM2必须为0。
(3)REN:允许接收位。< br> REN用于控制数据接收的允许和禁止,REN=1时,允许接收,REN=0时,禁止接收。
(4)TB8:发送接收数据位8。< br> 在方式2和方式3中,TB8是要发送的——即第9位数据位。在多机通信中同样亦要传输这一位,并且它代表传输的地址还是数据,TB8=0为数据,TB8=1时为地址。
(5)RB8:接收数据位8。
在方式2和方式3中,RB8存放接收到的第9位数据,用以识别接收到的数据特征。
(6)TI:发送中断标志位。
可寻址标志位。方式0时,发送完第8位数据后,由硬件置位,其它方式下,在发送或停止位之前由硬件置位,因此,TI=1表示帧发送结束,TI可由软件清“0”。
(7)RI:接收中断标志位。
可寻址标志位。接收完第8位数据后,该位由硬件置位,在其他工作方式下,该位由硬件置位,RI=1表示帧接收完成。
3.PCON—–电源管理寄存器
PCON主要是为CHMOS型单片机的电源控制而设置的专用寄存器,单元地址是87H,其结构格式如下:
PCON电源管理寄存器结构 | ||||||||
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
SMOD | – | – | – | GF1 | GF0 | PD | IDL |
在CHMOS型单片机中,除SMOD位外,其他位均为虚设的,SMOD是串行口波特率倍增位,当SMOD=1时,串行口波特率加倍。系统复位默认为SMOD=0。
二.代码
/* Main.c file generated by New Project wizard
*
* Created: 周日 6月 9 2019
* Processor: 80C31
* Compiler: Keil for 8051
*/
#include <reg51.h>
#include <stdio.h>
#define SEG P1
typedef unsigned char uint8_t;
// 0~F 数字字模
const uint8_t n[4][4] = {
{0x40, 0x79, 0x24, 0x30},
{0x19, 0x12, 0x02, 0x78},
{0x00, 0x10, 0x08, 0x03},
{0x46, 0x21, 0x06, 0x0E}
};
uint8_t col;
uint8_t row;
//把数据从串行口推出
void tx(uint8_t dat){
SBUF=dat;
while(TI==0); //若发送中断标志位没有置"1",就等待
TI=0;
}
//从串口读取数据
void rx() interrupt 4{
if(RI==1){
RI = 0;
SEG = SBUF;//把收到的数据通过SEG显示出来
}
}
void main(){
TMOD = 0x20; //定时器工作在方式2
SCON = 0x50; //串口工作方式1,允许接受数据
PCON = 0x00; //设置波特率不倍增
TH1 = 0xfd; //设置波特率为9600b/s
TL1 = 0xfd;
TR1 = 1;
EA = 1; //打开中断总开关
ES = 1; //串行口中断打开
while(1){
//行选,列选归位
row = 0xFF;
col = 0xFF;
//置P0低四位高电平读行数
P0 = 0x0F;
switch(P0){
case 0x0E:row = 0;break;
case 0x0D:row = 1;break;
case 0x0B:row = 2;break;
case 0x07:row = 3;break;
}
//置P0高四位高电平读列数
P0 = 0xF0;
switch(P0){
case 0xE0:col = 0;break;
case 0xD0:col = 1;break;
case 0xB0:col = 2;break;
case 0x70:col = 3;break;
}
//判断读到的数字并由SEG显示
if(col != 0xFF && row != 0xFF){
tx(n[row][col]);//发送按下的数字
}
}
}
通讯双方共用一份代码,在A机键盘输入0-A数据,然后通过串行口发送到B,B机接受到后将收的数据显示到SEG上。以此类推B机也可以发送数据,由A机接收并显示、
效果图如下: