51单片机的串口通迅
通信的基本方式分为并行通信和串行通信
并行通信
数据的各位同时在多根数据线上发送或接收
特点:
控制简单,传输速度快;由于输线较多,长距离传送时成本高且接收方的各位同时接收存在困难
串行通信
使用一条数据线,将数据一位一位的依次传输,每一位数据占据一个固定的时间长度。只需少数几条线,适用于计算机与外设之间的远距离通信
特点:
传输线少,长距离传送时成本低,但数据的传送控制比并行通信复杂
串行通信可分为三种制式:
单工:单向的(收或发)
半双工:(串行通信)收/发不可同时进行
全双工:(串行通信)收/发可同时进行
传输速率
比特率:每秒钟传输二进制代码的位数
单位:位/秒(bps)
如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位、1个停止位、8个数据位)
这时比特率为:10位×240个/秒 = 2400 bps
串行接口的结构
有两个物理上独立的接收、发送缓冲器SBUF,它们占用同一地址 99H
如果CPU写SBUF,数据就会被送入发送寄存器准备发送;
如果CPU读SBUF,则读入的数据一定来自接收缓冲器。
CPU对SBUF的读写,实际上是分别访问两个不同的寄存器
串行控制寄存器SCON
SCON地址98H用于设置串行口的工作方式、监视串行口的工作状态、控制发送与接收的状态等。它是一个既可以字节寻址又可以位寻址的8位特殊功能寄存器。
TI:发送中断标志位
TI = 1,表示已结束一帧数据发送,可由软件查询TI位标志,也可以向CPU申请中断
★ TI在任何工作方式下都必须由软件清0。
RI:接收中断标志位
RI = 1,表示一帧数据接收结束。可由软件查询RI位标志,也可以向CPU申请中断
★ RI在任何工作方式下也都必须软件清0
串行发送中断TI和接收中断RI的中断入口地址同是0023H,因此在中断程序中必须由软件查询TI和RI的状态才能确定究竟是接收还是发送中断,进而作出相应的处理。单片机复位时,SCON所有位均清0。
SM0和SM1为工作方式选择位,可选择四种工作方式:
SM0 | SM1 | 方式 | 说明 | 波特率 |
---|---|---|---|---|
0 | 0 | 0 | 移位寄存器 | fosc/12 |
0 | 1 | 1 | 10位异步收发器(8位数据) | 可变 |
1 | 0 | 2 | 11位异步收发器(9位数据) | fosc/64或fosc/32 |
1 | 1 | 3 | 11位异步收发器(9位数据) | 可变 |
fosc为晶振频率
当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式(即方式2,且TCON的TR1 = 1,以启动定时器)。这时溢出率取决于TH1中的计数值。
T1溢出率 = fosc/{12×[256-(TH1)]}
常用串口波特率:
300、600、1200、2400、4800、9600、19200…115200;
电源控制寄存器PCON
PCON | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|
位名称 | SMOD | - | - | - | GF1 | GF0 | PD | IDL |
SMOD:在串行口工作方式1、2、3中,是波特率加倍位
(产生高波特率时启动平时不用,比如用11.0592晶振产生57600波特率时就要设置成SMOD = 1)
= 1时,波特率加倍(PCON = 0x80)
= 0时,波特率不加倍(PCON = 0x00)
在PCON中只有这一个位于串口无关
串行口工作之前需要对相关寄存器进行配置,设定其工作模式
1、设置T1的工作方式(编程TMOD寄存器)
2、计算T1的初值,装载TH1、TL1
3、启动T1(编程TCON中的TR1位)
4、确定串行口控制(编程SCON寄存器)
如需串行口在中断方式工作时,要进行中断设置编程IE寄存器
异步通信
定义:通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。
以字符(构成的帧)为单位进行传输,字符与字符之间的时间间隔是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符之内的各位之间的距离均为“位间隔”的整倍数
同步通信
建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留空隙,即保持位同步关系,也保持字符同步关系。
查询法代码示例:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar num;
void delay(uint z)
{
uint x,y;
for(x = z;x > 0; x --)
for(y = 114; y > 0; y --)
}
void UART_init()
{
TMOD = 0x20; //T1工作模式2 8位自动重装
TH1 = 0xfd;
TL1 = 0xfd; //比特率9600
TR1 = 1; //启动T1定时器
SM0 = 0;
SM1 = 1;//串口工作方式1 10位异步
REN = 1;//串口允许接收
}
void main()
{
UART_init();
while(1)
{
SBUF = num;
while(!TI);
TI = 0;
num ++;
delay(500);//500毫秒延时
}
}
中断法
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar num;
void UART_init()
{
TMOD = 0x20; //T1工作模式2 8位自动重装
TH1 = 0xfd;
TL1 = 0xfd; //比特率9600
TR1 = 1; //启动T1定时器
SM0 = 0;
SM1 = 1;//串口工作方式1 10位异步
REN = 1;//串口允许接收
EA = 1; //开总中断
ES = 1; //串口中断打开
}
void main()
{
UART_init();
while(1)
{
while(!RI);
P1 = SBUF;
RI = 0;
}
}
void UART() interrupt 4 //中断函数
{
if(RI) //检测是否接收完成
{
num = SBUF; //num取出接收寄存器的值
P1 = SBUF;
num ++;
RI = 0;
SBUF = num;
while(!TI);
TI = 0;
}
}