“串口”你已经不陌生了,在前面的章节中,你经常需要在调试终端上显示数据,这些 数据就是机器人的大脑——单片机AT89S52 通过串口向你的电脑传送的。
串口通讯UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一 种能够把二进制数据按位(bit)传送的通信方式。单片机 AT89S52 拥有 1 个串行通信接口。
该串口可在很宽频率范围内以多种模式工作,其主要功能如下:在输出数据时,把数据进行 并-串转换,即单片机将8位并行数据送到串口输出;在输入数据时,把数据进行串-并转换,
即从串口读入外部串行数据并将其转换为8位并行数据送到单片机。
第2 章的图 2-1 展示了 AT89S52 的各个引脚定义,大部分端口都有第 2 功能,串口就 用到了端口的第2 功能。端口 P3.0(RXD,第 10 号引脚)用来串口接收,端口 P3.1(TXD,
第11 号引脚)用来串口发送。
AT89S52 串口支持双全工模式(同时收发),并具有接收缓冲功能,即在接收第 2 个字 符时,将先前接收到的第1 个字符保存在缓冲区中,只要 CPU 在第 2 个字符接收完成之前 读取了第1 个字符,数据就不会丢失。
AT89S52 提供了两个特殊功能寄存器 SBUF 和 SCON 供软件访问和控制串口。
串口缓冲寄存器SBUF 实际上是 2 个寄存器。写 SBUF 的操作把待发送的数据送入,读 SBUF 的操作把接收到的数据取出。两个操作分别对应于两个不同的寄存器,见图 7-1。
CLK SBUF Q
波特率时钟
(发送)
D
移位寄存器 CLK
SBUF
波特率时钟
(接收)
TXD
(P3.1)
RXD
(P3.0)
AT89S52内部总线 图7-1 AT89S52 串口结构简图
串口控制寄存器 SCON 包含串口的状态位和控制位,可进行位操作。控制位决定串口 的工作模式,状态位代表数据发送和接收结束后的状态。可用软件来查询状态位,也可编程 使其触发中断。
串口的工作频率,即波特率,可以是固定的,也可以是变化的。如果使用可变的波特率,
波特率的时钟信号由定时器1 提供,而且必须对其作相应的编程。
串口控制寄存器SCON
AT89S52 串口的工作模式通过设置串口控制寄存器 SCON 来选择,见表 7-1。
表7-1 SCON 寄存器简表
位 符号 描述
SCON.7 SM0 串口模式位0(见表 7-2)
SCON.6 SM1 串口模式位1(见表 7-2)
SCON.5 SM2 串口模式位2。允许在模式 2 和模式 3 下进行多机通信;如果 接收到的第9 位数据为 0,则 RI(接收中断标志)不会被置 1 SCON.4 REN 接收使能位。必须置REN 为 1 才能接收数据
SCON.3 TB8 发送数据的第9 位。在模式 2 和 3 下,此位存放发送数据的第 9 位,利用软件置位或清除
SCON.2 RB8 接收数据的第9 位
SCON.1 TI 发送中断标志。字符发送结束时被置1,由软件清除 SCON.0 RI 接收中断标志。字符接收结束时被置1,由软件清除
表7-2 串口工作模式选择
SM0 SM1 模式 描述 波特率
0 0 0 移位寄存器 1/12 fosc 0 1 1 8 位 UART 可变(由定时器1 决定)
1 0 2 9 位 UART 1/64(1/32) fosc 1 1 3 9 位 UART 可变(由定时器1 决定)
什么是波特率?
这是一个衡量通信速度的参数。它表示每秒钟传送的 bit 的个数。例如波特率 9600 表 示每秒钟发送9600 个 bit。
波特率的计算
在模式0 下,波特率是固定的,它的值为单片机的晶振频率(fosc)的 1/12。
在模式2 下,SMOD=0 时,波特率为 1/64 fosc;SMOD=1 时,波特率为 1/32 fosc。其 中,SMOD 是电源控制寄存器 PCON 的第 7 位——波特率倍增位。
在模式1 和模式 3 下,波特率按如下公式计算:
波特率= (2SMOD/32)·(fOSC/12)·[1/(2K-初值)]
在模式1 下,K=8;在模式 3 下,K=9。初值的计算见上章定时/计数器初值计算。
本章使用的是模式1 下的 8 位 UART 串口通信机制。
RS232电平与TTL电平转换
在数字电路中,只存在“1”和“0”两种逻辑状态,也就是“高电平”和“低电平”。
那么,多高的电压为高,多低的电压又是低呢?于是人们分了许多的电平标准,这里向你介 绍的是TTL 和 RS232 这两种标准。
TTL(Tansistor-Transistor Logic),是指三极管-三极管逻辑电路。很多单片机,包括你 所使用的AT89S52 都是用的这种标准。它的逻辑“1”电平是 5V,逻辑“0”电平是 0V。
RS232 标准是 1969 年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及 计算机终端生产厂家共同制定的用于串行通讯的标准。它的逻辑“1”电平是-5V--15V,
逻辑“0”电平是+5V-+15V。
RS232的全称是EIA-RS-232C,其中EIA(Electronic Industry Association)代表美国电子 工业协会;RS(Recommend Standard)代表推荐标准;232是标识号;C代表RS232的最新 一次修改(1969),在这之前有RS232B、RS232A。
为了让单片机与PC 机能相互通信,必须让这两种电平相互转换,如图 7-2 所示。
图7-2 PC 机与单片机电平转换示意
图中的转换电路部分可采用机器人教学板所使用的电路,或者用专用转换芯片(如 MAX232)来进行,教材并不讲解该转换电路的具体工作原理。但不论是哪种方式,它们要 完成的工作是一致的:PC 机的 RS232 电平进入单片机之前变成 TTL 电平;单片机的 TTL 电平进入PC 机之前变成 RS232 电平。
串口总共由九个信号口组成,但要完成信号的收发,只需用RXD、TXD 和 GND 即可。
连接时需要注意:PC 机的接收端(RXD)与单片机的发送端(TXD)相连;PC 机的发送 端(TXD)与单片机的接收端(RXD)相连;两者的地端(GND)相连。
任务一 编写串口通信程序
本例程是在模式1 方式下进行通讯,设计成一个 uart.h 的头文件,以便机器人在前面章 节中的程序可以方便地调用。串口通讯程序要和串口调试窗口(如图7-3)配合适用。
注意
串口调试窗口的设置,如“串口选择”、“打开串口”等,是针对PC机串口而言,并不
是对单片机串口的设置。
图7-3 串口调试界面 例程:uart.h
z 确保 RS232 接口连接好 z 输入、保存程序 uart.h #include <AT89X52.h>
#include <stdio.h>
#define XTAL 11059200
#define baudrate 9600
#define OLEN 8 //串行发送缓冲区大小
unsigned char ostart; //发送缓冲区起始索引 unsigned char oend; //发送缓冲区结束索引 char idata outbuf[OLEN]; //发送缓冲区存储数组
#define ILEN 8 //串行接收缓冲区大小
unsigned char istart; //接收缓冲区起始索引 unsigned char iend; //接收缓冲区结束索引 char idata inbuf[ILEN]; //接收缓冲区存储数组
bit bdata sendfull; //发送缓冲区满标志 bit bdata sendactive; //发送有效标志
/*串行中断服务程序*/
static void com_isr(void) interrupt 4 using 1 {
//---接收数据--- char c;
if(RI) //接收中断置位
{ void putbuf(char c)
{
//printf函数使用putchar输出一个字符 char putchar (char c)
{
if (c=='\n') //增加新的行
{ //getchar和gets函数使用_getkey char _getkey(void)
{
void com_initialize(void) {
void uart_Init() {
com_initialize();
EA=1; //开总中断,见表6-2
}
uart.h 是如何工作的?
#define XTAL 11059200
#define baudrate 9600
声明你所使用的晶振频率为11.0592MHz 及串口使用的波特率为 9600。
#define OLEN 8
#define ILEN 8
输出和输入的位数均是8 位。
存储器结构
AT89S52 内部存储器由片上ROM 和片上 RAM 组成。片上 RAM 空间由各种用途的存 储器空间组成,包括通用 RAM、可位寻址 RAM(BDATA 区)、寄存器组以及特殊功能寄 存器(SFR)。
另外,AT89S52 有附加的 128 字节的内部 RAM,称为 IDATA 区,地址与 SFR 是重叠 的。这个空间通常用于存放使用频繁的数据。如:
char idata outbuf[OLEN]; //发送缓冲区存储数组 char idata inbuf[ILEN]; //接收缓冲区存储数组
BDATA 区允许软件以“位”为单位访问存储器,这是一项非常有用的功能,仅以一条 指令就可以实现对位进行置位、清除、与、或等操作,简化了设计。
bit bdata sendfull; //发送缓冲区满标志 bit bdata sendactive; //发送有效标志
函数 void com_initialize(void)对串口进行了初始化并设置了波特率 9600,串口将工作在 模式1 下;函数 void uart_Init( )调用了 com_initialize( )并打开了总中断。
参考前一章可知,TMOD |=0x20;让定时/计数器 1 工作在方式 2 下;SCON=0x50;设置 串口工作在模式1;根据波特率公式反推出初值为:
初值=2K-[(2SMOD/32)·(fOSC/12)/波特率]= 28-[(20/32)·(11.0592*106/12)/9600]=253=0XFD 使用函数 void putbuf(char c)写字符到 SBUF 或发送缓冲区;函数 char _getkey(void)从 AT89S52 的串口中读入一个字符,然后等待字符输入;而 char putchar(char c)则是通过调用 putbuf( )输出字符。注意,putchar( )只能输出一个字符,而你用到的 printf 则是通过调用 putchar( )可输出字符串。
函数 static void com_isr(void) interrupt 4 using 1 你不会陌生,它的样子和我们以前讲过 的定时/计数器 0 中断函数相似,它的作用就是进行串口中断服务,接收和发送数据。“4”
你可以在“C:\Program Files\Keil\C51\LIB”目录下找到这两个函数的定义。其中 getkey( ) 函数前面加了下划线“_”,表示该函数并不是标准的 C 库函数。uart.h 头文件修改了这两个 函数用来满足自己的需求。
例程 HelloRoBot.c——printf(“Hello,this is a message from your Robot\n”);
printf( )函数调用 putchar( )函数将第一个字符(字符‘H’)发送到寄存器 SBUF 中;SBUF 满,TI 置位,进入中断处理函数发送该字符;之后,字符‘H’通过串口线到达 PC 机串口,
串口调试窗口进行接收处理,并将字符‘H’在接收区内显示。
如此往复,直到 printf( )函数发送最后一个字符‘\n’——回车命令,将光标置位在下 一行,发送工作才结束。整个发射流程如示意图7-4。
图7-4 串口发射流程示意
例程 ControlServoWithComputer.c——scanf("%d",&PulseDuration);
当你在串口调试窗口“发送区”内写入整数1700 并点击“发送”按钮时,调试窗口会 将字符‘6’(整数 1700 在十六进制的表示下为 6A4,转换过程由调试窗口程序完成)通过 串口线发送到单片机的串口。
scanf( )函数通过调用 getkey( )函数从单片机串口处接收字符‘6’,接收缓冲寄存器 SBUF 满,RI 置位,进入中断处理函数,取出字符‘6’;如此循环,直到全部数据接收完。
最后,scanf( )函数再将接收到的数据,即 1700 赋给变量 PulseDuration。
串口接收流程如示意图7-5。
图7-5 串口接收流程示意
工程素质和技能归纳
1.51 单片机串口的概念和使用 2.波特率的简介及计算
3.单片机存储器结构 4.串口的工作流程
科学精神的培养
1.查找相关资料,学习串口控制寄存器 SCON 及特殊寄存器 PCON 的功能及用法 2.芯片 MAX232 也具有进行 RS232 与 TTL 电平转换功能,查阅相关资料,掌握它的 用法
3.在头文件 STDIO.H 中包含了我们常用的许多函数,了解这些函数的用法