单片机基础(八):单片机串行口结构与工作方式及应用
单片机串行口结构
串行口结构如上图
发送时,SBUF中写入数据后,串行口通过发送控制器,将SBUF中的数据逐个逐位地通过串行输出口TXD引脚逐个发出,当一个字节发送结束后,触发TI中断位,通知单片机发送结束
接收时,先向REN引脚写1,外部引脚RXD会实时检测电平变化,当满足串行接收数据的条件时,会逐位接收数据并保存到SBUF,当一个字节接收结束后,触发RI中断位,通知单片机接收结束
串行口控制寄存器SCON
SCON | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|
98H | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
SM0、SM1用于设定串行口工作方式 fosc :晶振频率
SM0 | SM1 | 方式 | 功能 | 波特率 |
---|---|---|---|---|
0 | 0 | 方式0 | 移位寄存器方式 | fosc/12 |
0 | 1 | 方式1 | 8位异步通信方式 | 可变 |
1 | 0 | 方式2 | 9位异步通信方式 | fosc/32或fosc/64 |
1 | 1 | 方式3 | 9位异步通信方式 | 可变 |
SM2:多机通信控制位
REN:允许接收控制位
TB8/RB:发送/接收的第9位数据
TI:发送中断标志位
RI:接收中断标志位
电源控制寄存器
PCON | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|
87H | SMOD |
当SMOD位为1时,串行口方式1、方式2、方式3的波特率加倍
这里只介绍方式0与方式1的应用
方式0
方式0通常用来外接移位寄存器,用作扩展I/O口,方式0工作时波特率固定为 fsoc/12,工作时,串行数据通过RXD输入、输出,同步时钟通过TXD输出
发送:TI = 0 时,SBUF写入数据后,发送过程启动,发送结束后,TI被置为1,并向CPU申请中断
接收:在 RI = 0 时,将REN置”1″就启动一次接收过程,RXD上的串行数据一次移入移位寄存器,当一个字节发送完成之后,接收中断标志RI被置为”1″,同时向CPU申请中断
方式0波特率固定,也无需编程设定定时器
方式0应用实例:扩展并行I/O口
当外接串入并出的移位寄存器时,即是扩展并行输出口,当外接并入串出的移位寄存器时,相当于扩展并行输入口
原理图如下
4094模块使用方式:
D接RXD,CLK接TXD,STB接P1.0,OE接EA
扩展并行输出口控制流水灯程序如下:
#include<reg52.h>
sbit P1_0 = P1^0;
void main(){
unsigned char i;
unsigned int j;
SCON = 0x00;//设置串行口工作方式
i = 0x01;//00000001b 发送的用于控制LED灯的变量
for(;;){
P1_0 = 0;//将4094接入串口
SBUF = i;//
while(TI==0);
P1_0 = 1;//将STB置1,准备4094发送
TI = 0;//TI归位
for(j = 0;j<0xffff;j++);//适当延时
i = i*2;
if(i==0){
i = 0x01;//循环
}
}
}
方式1
方式1位8位异步通信方式,在方式1下,一帧信息为10位,1位起始位(0),8位数据位(低位在前)和1位停止位(1)
发送:在 TI = 0 时,向SBUF写入数据,启动发送过程,数据有TXD引脚送出,当一帧数据发送完毕后,TI 被置为”1″
接收:当 REN = 1 时,接收控制器开始接收数据,数据依次被移入移位寄存器,当8位数据及停止位全部移入后,进行响应操作
方式1下,TXD数据发送端,RXD为数据接收端,波特率可变,由定时/计数器T1的溢出率和电源控制寄存器PCON中的SMOD位决定,故可编程设定定时器以设定波特率,其中溢出率 = 计数器一秒钟内溢出的次数
波特率 = 2SMOD × (T1的溢出率) / 32
T1溢出率 = fsoc / ( 12 × 计数值 )
所以
T1的初值 = MAX值 – fsoc × 2SMOD / (12 × 波特率 × 32)
分析如下:
甲机发送程序:
#include<reg52.h>
void main(){
unsigned char i;
SCON = 0x40;
TMOD = 0x20;
TL1 = 0xE6;
TH1 = 0xE6;
TR1 = 1;//设定完毕
P1 = 0xff;//为读取准备
while(1){
i = P1;
SBUF = i;
while(TI==0);//等待发送完成
TI = 0;
}
}
乙机接收程序:
#include<reg52.h>
void main(){
SCON = 0x50;
TMOD = 0x20;
TL1 = 0xE6;
TH1 = 0xE6;
TR1 = 1;
EA = 1;
ES = 1;
while(1);
}
void setLED() intrrupt 4{
if(RI){
RI = 0;
P2 = SBUF;
}
}
2019/3/5