C51 新手编程 串行口
扫描二维码
随时随地手机看文章
C51 新手编程(第五课)
串行口
今天介绍单片机怎样通过串行口与计算机通信。
1. 概述
通信实质就是以计算机为中心,通过某些通信线路与设备,对二进制编码的字母、数字、符号化及数字化声音、图像信息进行的传输、交换和处理。由于计算机的信息是以字节(8位)或字(1个或几个字节)为单位进行处理,所以以字或字节为传输单位比较合适,今天重点介绍使用串行口进行通信。
所谓串行通信就是所传送数据的各位按顺序一位一位地发送或接收。在串行通信系统中,传输数据的各位只在一条传输线上传送,因此在长距离传送数据时,比较经济,缺点是传输速度较慢。
2. 串行通信种类
串行通信分为同步通信和异步通信两种方式。
(1) 同步串行通信:要求在发送设备的时钟频率与接收设备的时钟频率一致的条件下,发送设备先发出一个(或几个)同步字符,随之发送一组数据。接收设备一旦检测到符合规定的同步字符,便连续按顺序接收所有数据。优点:速度较快。缺点:对设备的硬件结构要求较高。
(2) 异步串行通信:发送设备和接收设备的时钟是不一致的。数据以一个字符一个字符地顺序按帧传送。帧格式示意图如图2-1:
0 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1 1
起始位 D0 D1 D2 D3 D4 D5 D6 奇偶校
验位 停止位
七位数据
图2-1异步通信信号传输格式
解释一下:开头一个起始位“0”,接着是5~8位数据位,规定低位在前,高位在后(图上是7位数据位),然后是一个奇偶校偶位(可以省略),最后加上一个停止位“1”表示字符的结束。
由于在技术实现上使用发送设备与接收设备的时钟频率长期严格保持一致有一定的困难,目前实际使用较多的还是串行异步通信方式。
3. 串行口中数据的双工传送
在串行通信中,机器的通信接口只能发送或接收,这种是单向传输的,称为单工传送,如果两机之间能够进行双向传送,这种方式就称为双工传送。
在双工传送中,如果接收和发送不能同时进行,只能分时接收和发送,这种传送就叫半双工传送,若两机的发送和接收均可同时进行,则为全双工传送。
4. 串行通信速率
波特率是在单片机异步通信中对数据传送速率的规定,即每秒钟传送信息的二进制位数。
5. 串行接口
从本质上讲,所有的串行接口都是以并行数据形式与CPU接口,而以串行数据形式与外部逻辑单元接口。它们的基本功能是从外部逻辑单元接收串行数据,转换成并行数据后传送给CPU;或者从CPU发出并行数据,转换成串行数据后输出给外部逻辑单元。
串行接口至少包含一个接收器和一个发送器。
6. 51串行接口
51单片机内部有一个功能很强的全双工的串行接口电路单元UART(即通用异步接收器/发送器,Universal Asynchronous Receiver/Transmitter),发送时数据由TXD端送出,接收时数据由RXD端输入,有两个缓冲器SBUF,一个作发送缓冲器,另一个作嫌收缓冲器。该串行口有4种工作方式,波特率可用软件设置,由片内的定时/计数器产生。串行口接收或发送数据均可触发中断系统,使用十分方便。
6.1. 串行口的组成
6.1.1. 串行口控制寄存器SCON,其格式如下:
D7 D6 D5 D4 D3 D2 D1 D0
SM0 SM1 SM2 REN TB8 RB8 TI RI
(1) SM0,SM1:串行口工作方式控制位,具体工作方式见表6-1:
表6-1 串行口工作方式控制
SM0 SM1 工作方式 说明 波特率
0 0 方式0 同步移位寄存器 fOSC/12
0 1 方式1 10位异步收发 由定时器控制
1 0 方式2 11位异步收发 fOSC/32或fOSC/64
1 1 方式3 11位异步收发 由定时器控制
(2) SM2:多机通信控制位(方式2,3)
1->只有接收到第9位(RB8)为1,RI才置位;
0->接收到字符,RI就置位。
(3) REN:串行口接收允许位
1->允许串行口接收;
0->禁止串行口接收。
(4) TB8:方式2和方式3时,为发送的第9位数据,也可以作奇偶校验位。
(5) RB8:方式2和方式3时,为接收到的第9位数据;方式1时,为接收到的停止位。
(6) TI:发送中断标志
由硬件置位,必须由软件清零
(7) RI:接收中断标志
由硬件置位,必须由软件清零
6.1.2. 电源控制寄存器PCON:
PCON的第7位SMOD是与串行口的波特率设置有关的选择位。
D7 D6 D5 D4 D3 D2 D1 D0
SMOD
(1) SMOD:串行口波特率加倍位
1->方式1和方式3时,波特率=定时器1溢出率/16;方式2波特率= fOSC/32;
0->方式1和方式3时,波特率=定时器1溢出率/32;方式2波特率= fOSC/64;
通常情况下,使用单片机的串行口时,选用的晶振比较固定,一般为6MHz,12MHz和11.0592MHz,常用于与微机的通信;选用的波特率也相对固定。串行口常用的波特率及相应的设置见表6-2:
表6-2 串行口常用波特率
串行口工作方式 波特率 fOSC = 6 MHz fOSC = 12 MHz fOSC = 11.0592 MHz
SMOD TMOD TH1 SMOD TMOD TH1 SMOD TMOD TH1
方式0 1M × × ×
方式2 375K 1 × ×
187.5K 1 × × 0 × ×
方式1
或
方式3 62.5K 1 20 FFH
19.2K 1 20 FDH
9.6K 0 20 FDH
4.8K 1 20 F3H 0 20 FAH
2.4K 1 20 F3H 0 20 F3H 0 20 F4H
1.2K 1 20 E6H 0 20 E6H 0 20 E8H
600 1 20 CCH 0 20 CCH 0 20 D0H
300 0 20 CCH 0 20 98H 0 20 A0H
137.5 1 20 1DH 0 20 1DH 0 20 2EH
110 0 20 72H 0 20 FEEBH 0 10 FEFFH
7. 实例
单片机串行口发送/接收程序,每接收到字节即刻发送出去;和微机相接后微机键入的字符回显在屏幕上。代码如下:
/******************************************************
* Title: 串口接收发送程序(字母)
* Description:
* Copyright:
* Company:
* @author Enron
*******************************************************/
#include
#define uchar unsigned char
/******************************************************
主函数
*******************************************************/
void main()
{
uchar a;
TMOD=0x20;
TL1=0xfd; // 采用11.0592MHz的晶振,波特率9600bps
TH1=0xfd;
SCON=0xd8;
PCON=0x00;
TR1=1;
while(1)
{
while(RI==0);
RI=0;
a=SBUF;
SBUF=a;
while(TI==0);
TI=0;
}
}
解释一下:TMOD = 0x20 即
D7 D6 D5 D4 D3 D2 D1 D0
GATE T/C 1 M1 M0 GATE T/C 0 M1 M0
0 0 1 0 0 0 0 0
看出来,我们使用定时器 1 的工作方式1,即定时器 1 为自动重设初值的8位定时/计数器。
TH1 = 0xFd; //在11.0592MHz下,设置串行口波特率为9600,方式3
TL1 = 0xFd;
串行口工作方式 波特率 fOSC = 6 MHz fOSC = 12 MHz fOSC = 11.0592 MHz
SMOD TMOD TH1 SMOD TMOD TH1 SMOD TMOD TH1
方式0 1M × × ×
方式2 375K 1 × ×
187.5K 1 × × 0 × ×
方式1
或
方式3 62.5K 1 20 FFH
19.2K 1 20 FDH
9.6K 0 20 FDH
4.8K 1 20 F3H 0 20 FAH
2.4K 1 20 F3H 0 20 F3H 0 20 F4H
1.2K 1 20 E6H 0 20 E6H 0 20 E8H
600 1 20 CCH 0 20 CCH 0 20 D0H
300 0 20 CCH 0 20 98H 0 20 A0H
137.5 1 20 1DH 0 20 1DH 0 20 2EH
110 0 20 72H 0 20 FEEBH 0 10 FEFFH
按照表来看我们的在11.0592MHZ下,串口的波特率为9.6K也就是9600,那么TH1 TL1设置为0xFD
SCON = 0xd8; //串口控制
D7 D6 D5 D4 D3 D2 D1 D0
SM0 SM1 SM2 REN TB8 RB8 TI RI
1 1 0 1 1 0 0 0
表6-1 串行口工作方式控制
SM0 SM1 工作方式 说明 波特率
0 0 方式0 同步移位寄存器 fOSC/12
0 1 方式1 10位异步收发 由定时器控制
1 0 方式2 11位异步收发 fOSC/32或fOSC/64
1 1 方式3 11位异步收发 由定时器控制
也就是说串行口的工作方式3,11位异步收发波特率由定时器控制的。REN:1->允许串行口接收。TB8:方式2和方式3时,为发送的第9位数据,也可以作奇偶校验位。RB8:方式2和方式3时,为接收到的第9位数据;方式1时。TI:发送中断标志,由硬件置位,必须由软件清零。RI:接收中断标志,由硬件置位,必须由软件清零。
PCON = 0x00;
D7 D6 D5 D4 D3 D2 D1 D0
SMOD
0 0 0 0 0 0 0 0
1->方式1和方式3时,波特率=定时器1溢出率/16;方式2波特率= fOSC/32;
0->方式1和方式3时,波特率=定时器1溢出率/32;方式2波特率= fOSC/64
TR1 = 1; //启动定时器T1
也就是启动定时器
while (1)
while(RI==0); //串口接收
RI = 0;
c = SBUF;
SBUF = c;
while(TI==0); //串口发送
TI=0;
while(RI==0); RI为0则等待(不为0就执行下一句)
RI = 0; 执行这句说明RI不再为0(接收结束),这里强制RI为0
c = SBUF; 接收字符
SBUF = c; 发送字符
while(TI==0); TI为0则等待,否则执行下一句
TI=0; 执行到这句说明TI不为0(即发送结束),强制令TI为0
这里的意思是说判断RI是否为0当RI==0时就一直循环判断,当RI不等与0时就执行下面的语句。RI=0是重置。然后就接收数据SBUF就是串口数据寄存地方。当C=SBUF时就收到了串口数据然后在吧原来的数据在发到出去SBUF=C,while(TI==0)是说当TI为0是就一直等待。不为0时就执行TI=0重置TI。
将前面的程序编译后写入单片机,并连好串口线。通过串口调试助手向单片机发送字符,会发现发送的内容被原样发送回来。