单片机原理及应用笔记:串行口的通信方式与项目实践
单片机原理及应用笔记:串行口的通信方式与项目实践
本篇文章是关于80C51单片机串行口通信的详细笔记,内容包括串行接口结构、控制寄存器、工作方式及波特率、初始化设置以及两个单片机之间的通信项目实践。文章结构清晰,内容详实,包含了理论讲解和具体代码实现,适合有一定基础的电子工程或计算机科学学生学习参考。
1. 80C51的串行接口的结构
80C51 单片机通过串行数据接收引脚RXD (P3.0)和串行数据发送引脚TXD(P3.1)与外界进行通信。串行口内有一个可直接寻址的专用寄存器----串行口缓冲寄存器SBUF ,SBUF 由两个寄存器组成;一个发送寄存器、一个接收寄存器,两者共用一个物理地址99H,可同时发送、接收数据,CPU 写SBUF,就是修改发送寄存器,读SBUF 就是读接收寄存器。其内部结构功能如图5-12所示。
2. PCON——电源及波特率选择寄存器
PCON寄存器主要是为CHMOS型单片机的电源控制设置的专用寄存器,单元地址为87H,不能位寻址。各位的功能如下:
3. 80C51串行口的工作方式及波特率
方式0
在方式0下,串行口作同步移位寄存器用,其波特率固定为fosc/12。串行数据从RXD(P3.0)端输入或输出,同步移位脉冲由TXD(P3.1) 送 出。这种方式常用于扩展I/O 口 。
移位输出:方式0发送数据的原理图和工作时序如图5-13
移位输入:方式0接收数据的原理图和工作时序如图6-11
所示采用74LS165并入串出移位寄存器实现。
RI
REH=1
R x D ( 激 据 )
T z D ( 移 位 脉 冲 )
D0 D1 D2 D3 D4 DS5 D6 D7
方式1
方式1是10位数据的异步通信,多用于双机通信。TXD 为数据发 送 端,RXD 为数据接收端,传送的每一帧数据中包括:
1位起始位,8位数据位,1位停止位。波特率可变,PCON 寄 存器的SMOD 位和T1的溢出率共同决定。
波特率=(2smod)×T1的溢出率/32
当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式。T1的溢出率=fosc/(12*(256-N)),N为定时器T1的计数初值
所以:方式1下的波特率=
或者 :
或者
例:方式1下,若波特率为9600bit/s,fosc=11.0592MHz,SMOD= 0, 求T1的计数初值。
方式1发送:
方式1数据发送是从数据写入发送缓冲器(SBUF)开始
的,随后在串行口由硬件自动加入起始位和停止位,构成一 个完整的帧格式,然后在移位脉冲的作用下,由TXD端串行
输出。一个字符帧发送完后,使TXD输出线维持在“1”状态下 并将SCON寄存器的TI位置“1”,该位的状态可供查询或请求
中 断 ,在再次发送数据之前,必须用软件将TI清零。方式1发 送的时序如图6-12所示。
方 式 1 接 收 :
在 REN=1 时 , 接 收 器 以 所 选 择 波 特 率 的 1 6 倍 速 率 采 样 R X D引 脚 电 平 , 当 检 测 到 R X D 引 脚 输 入 电 平 产 生 负 跳 变 时 , 说 明 起始 位 有 效 , 将 其 移 入 移 位 寄 存 器 ,并 开 始 接 收 这 一 帧 信 息 的 其余 位 。 接 收 过 程 中 , 数 据 的 D 0 位 在 前 , D 7 位 在 最 后 。 当 R I = 0 ,且 S M 2 = 0 ( 或 接 收 到 的 停 止 位 为 1 ) 时 , 将 接 收 到 的 9 位 数 据 的前 8 位 数 据 装 入 接 收 S B U F , 第 9 位 ( 停 止 位 ) 进 入 R B 8 , 并 将SC ON寄存器的RI位“1”,表 示 一 帧 数 据 接 收 完 成 ,该 位 的 状态 可 供 查 询 或 请 求 中 断 ,在 再 次 发 送 数 据 之 前 ,必 须 用 软 件 将RI清零。 方 式 1 接 收 的 时 序 如 图 6 - 1 3 所 示 。
方式2和方式3
方 工 2和方式3 051单片机的两种吕串行丁通信模式 ,携位数据专输,并常用于多机通信。
起始位:1位,用于标识数据帧的开始。
数据位:9位数据,其中包括8位有效数据和1位附加的 第9位。此第9位由TB8 (发送时)和RB8 (接收时)控制。
停 止 位 :1位,用于标识数据帧的结束
方式2和方式3发送:
发送数据由TxD端输出,一帧信息中的9位数据包括8位数据位(先低位后高位)、一位附加可控位(1或0)。附加的第9位数据为SCON 中的TB8 的状态,它由软件置位或复位,可作为多机通信中地址/数据信息的标志位,也可作为数据的奇偶校验位。一个字符帧发送完毕后,自动将TI位置“1”,供查询向CPU请求中断。方式2、3发送的时序如图6-15所示。
4. 串行口的初始化
采用80C51进行串行通信之前必须对其进行初始化。初始化 的主要内容是:设置产生波特率的定时器1的初始值、设置串 行口的工作方式和控制方式、设置中断控制。具体步骤如下:
1)确定T1的工作方式 (TMOD 寄存器编程);
2)计算T1的初值,装载TH1、TL1;
3)确定SMOD值 (PCON寄存器编程);
4)启动T1(TCON 中的TR1位置位);
- 确定串行口 通信方式(SCON 寄存器编程);
6)若串行口在中断方式工作时,进行中断设置 (IE、IP寄存 器编程)。
6.2.2 任务24-2:单片机U1与单片机U2进行通信
任务实现
(1)分析
本任务用到了单片机U1和单片机U2,因此需要对单片机U1 和单片机U2 分别设计两个程序:单片机U1负责完成数据发送任务;单 片机U2 负责完成数据接收任务。对单片机U1 编程时,由于使用方式1,需要设置行控制寄存器SCO N, 使SM0=0,SM1=1 ,选波特率为9600b/s, SMOD=0 ,计算出TH1=FAH; 对单片机U2编程时,需要设置SMO=0,SM1=1和REN=1 (允许接收 ) 。
(2)程序设计
- 单片机U1 数据发送程序
#include<reg51.h> //包含单片机寄存器的头文件
unsigned char code Tab[
]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xaa,0x0f,0xf0, 0x55}; // 流水灯控制码,该数组被定义为全局变量
/*****************************************************
函数功能:发送一个字节数据
***************************************************/
void Send(unsigned char dat)
{
SBUF=dat; // 将数据写入发送缓冲器,启动发送
while(TI==0) // 若没有发送完毕,等待
;
TI=0; //发送完毕,TI被置“1”,需将其清0
}
/**************************************************************
函数功能:延时约150ms
**************************************************************/
void delay(void)
{
unsigned int j;
for(j=0;j<50000;j++)
;
}
/***********************************************************
函数功能:主函数
*************************************************************/
void main(void)
{
unsigned char i;
TMOD=0x20; //*TMOD=00100000B,
SCON=0x40; //SCON=01000000B,
PCON=0x00; //PCON=00000000B,
TH1=0xfd; //给定时器T1 高8位赋初值
TL1=0xfd; //给定时器T1 低8位赋初值
TR1=1; //启动定时器T1
while(1)
{
for(i=0;i<12;i++) // 检测数据
{
Send(Tab[i]);
delay(); //150ms
}
}
- 单片机U2 数据接收程序
#include<reg51.h> //包含单片机寄存器的头文件
/***************************************************
函数功能:接收一个字节数据
***************************************************/
unsigned char Receive(void)
{
unsigned char dat;
while(Rl==0) //只要接收中断标志位 RI没有被置“1”
; //等待,直至接收完毕( RI=1
RI=0; //为了接收下一帧数据,需 用软件将RI清0
dat=SBUF; //将接收缓冲器中的数 据存于dat
return dat; //将接收到的数据返回
}
/*************************************************************************
函数功能:主函数
****************************************************************************/
void main(void)
{
TMOD=0x20; // 定时器T1工作于方式2
SCON=0x50; //SCON=01010000B,串口工作方式1,允许接收(REN=1)
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfa; //根据规定给定时器T1高8位赋初值
TL1=0xfa; // 根据规定给定时器T1低8位赋初值
TR1=1; //启动定时器T1
REN=1; //允许接收
while(1)
{
P2=Receive(); //将接收到的数据送P2口显示
}
}
(3) 用Proteus软件仿真