单片机串行口结构

在这里插入图片描述
  串行口结构如上图
  发送时,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

版权声明:本文为kafm原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/kafm/p/12721821.html