【MCS-51】串行I/O接口及其通信

news2025/6/7 23:25:54

我们知道MCS-51中有很多的引脚,这些引脚很多一般都是用作输入或者输出口,其中有两个引脚P3.0和P3.1比较特殊,我们常将其用作串行通信的数据发送和接收端TXD、RXD。

目录

🐱通信方式

🐱串行通信的传输方式和数据通信方式

🍑数据传输方式

🍑数据通信方式

🐱串行口结构

🐱串行通信控制寄存器

🍎控制状态寄存器--SCON

🍎电源控制寄存器--PCON

🐱波特率设计

🐱串行口工作方式

🥝串行方式0

🥝串行方式1

🥝串行方式2、3

🐱通信方式举例

🐟1、同步通信

🐟2、异步通信


🐱通信方式

因为我们单片机的信息或许不只是在自己片内使用,有时候还要将一个单片机的信息发送给另外一个单片机,而发送就需要选择通信方式。所以在学习串口通信方式之前,我们很有必要先来了解一下常见的通信方式。

常见的通信方式有两种:串行通信和并行通信。

串行通信的数据传输方式是一位一位地传递过去,例如我有一个数据11101010,那么其将会被一位一位排队地传过去。而并行通信是一次性发送一个字节,例如刚才的11101010,它的发送方式是一个引脚发送一个位,如果8个引脚那么就可以一次可以发送一个字节。

🍈串行通信:

串行通信一般只需要一对两条传输线,相比较并行通信大大节约了引脚和成本,适合于远距离的通信。但是显而易见,其一位一位地传输,相较于并行通信一次传输一个比特来说其传输速率较低。

🍈并行通信:

并行通信一个最大的优点就是传输的速率快,一次8个比特位一个字节,但是其缺点也很明显,那就是需要大量的引脚,其适合速率需求高并且近距离的传输。

🐱串行通信的传输方式和数据通信方式

既然我们是以串行通信为例子,那么我们就需要注重来看看串行通信的数据传输方式。从前面的图我们可以看到串行通信真正通信的端口只有4个,包括单片机1的RXD、TXD和单片机2的RXD和TXD。接下来我们来看看串行通信的数据传输方式有哪些:

🍑数据传输方式

🍉1、单工:单工就是数据只能由单片机A传输给单片机B而不能反过来。

🍉2、半双工:半双工就是单片机A可以传输数据给单片机B,并且单片机B也可以传输数据给单片机A,但是在一个时刻只能由一个单片机发送,一个单片机接收。也就是说某个时刻里面,单片机A如果在发送数据给单片机B,那么单片机B就不能发送数据给单片机A。

🍉3、全双工:全双工就是在半双工的基础上可以允许同时双向发送数据,它需要发送端和接收端都同时具备发送和接收的能力,也就是两个方向相反的单工的叠加。而我们的AT89C51单片机正是采用全双工的通信方式

🍑数据通信方式

与数据传输方式类似,我们还需要去选择串行通信的数据通信方式,数据传输方式决定的是怎么发送数据,而通信方式决定的是数据之间传输的协议。

🍉异步通信

异步通信就是两个端的时钟不同,也就是说它们没有统一的工作节拍,所以它们之间的数据通信就需要定义协议。在异步通信里面,数据是以一帧的方式传输的,一帧所包含的内容有N个数据位(低位在前,高位在后),1个起始位和1个结束位以及奇偶校验位。所以说一帧的数据结构包含11个位。

起始位占1格,它的数值是0,而电路的等待状态位数也是1。平常状态下电路在不断检测收到的位的状态,一旦在一堆1里面突然接收到0,那么也就代表着一帧数据即将传来,那么接收端会做好接收准备。然后就是紧跟着的N个数据位,前面是低位,后面是高位(D0, D1, D2, D3, D4...),数据位可能是5、6、7、8位等。数据位后面就是奇偶校验位,这一位一般用来检验数据的完整性或者用它来将数据划分用途等(0代表用途A,1代表用途B)。最后是停止位,停止位是1,接收到停止位后,接收端就知道本次接收完毕,然后去做下次接收的准备(检测低电位)

但是呢一帧和一帧之间未必是紧挨着的,有时候一帧后面再跟几个空闲位再去开始下一帧也不是没有。而空闲位也就是异步通信的特征,它代表着在等待。

 

 🍉同步通信

接下来我们来仔细看一下同步通信,同步通信是指接收端和发送端时钟一致的通信方式,通常情况下同步通信会规定一到两个同步字符(SYNC),同步传输的同步字符一般会选择的是ASCII中规定的16H(00010110),用来确定通信双方是否达到同步可通讯状态,在确定双方均同步后再发送数据。而在数据发送时,字符和字符之间不会像异步通信一样存在空闲位(1),也不会存在起始位和终止位,它们都是紧密相连的。

也得益于同步通信没有过多的标志位,所以其传输速率可以达到很高,但是硬件设计比较复杂。

⭐波特率(Baud rate)

波特率代表每秒钟传送的二进制代码的位数,本质上是衡量数据传输的速率的一个物理量,单位是b/s。假如数据传输的速率是100字符/秒,而每个字符包括1给起始位,1给结束位和5给数据位,那么其波特率就是7 x 100 = 700(b/s)

所以波特率就是代表着每秒传递的二进制代码的位数,即每个代码的传送时间就是1/波特率

异步通信的波特率一般在50b/s~19200b/s之间

🐱串行口结构

这里说的串行口其实就是那P3.0和P3.1这两个全双工的串行通信端,它们可以用作UART(通用异步接收和发送器)实现与另外的系统进行串行通信。

上面就是我们进行串口通信的各部件结构图,首先我们来看发送/接收数据的缓冲器SBUF,发送缓冲器和接收缓冲器本质上是一个寄存器,只是通过软件来判断不同的工作状态然后对应不同的用法而已。当其作为接收缓冲器时只能读出;而作为发送缓冲器时只能被写入。而串行数据发送和接收数据的速率则是与移位时钟同步,而波特率也是代表着数据收发速率,所以移位时钟就是波特率,而这个移位时钟则是通过定时器T1的溢出率经过分频 / 不分频后再通过16分频后得出。

在发送时,SBUF缓冲器就用来存储要发送的数据,所以我们只能对该缓冲器进行写入而不能读,当一帧数据发送完毕后,就会让发送中断标志位Tl置1;

当接收时,SBUF缓冲器用来存储接收的数据,所以我们只能对该缓冲器进行读而不能写入,而当一帧数据被接收完整后就让中断标志位Rl置1。

🐱串行通信控制寄存器

串行通信控制寄存器我们主要学习两个:控制状态寄存器SCON和电源控制寄存器PCON

🍎控制状态寄存器--SCON

SCON是一个8位寄存器,它的地址是98H,可以进行位寻址,其各个位及其意义如下表所示:

D7

D6

D5

D4

D3

D2

D1

D0

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

首先我们来看SM0和SM1,这两个位是用来选择串口的工作方式的:

SM0=0,SM1=0;此时进入工作方式0,工作模式是同步移位寄存器,波特率是晶振频率的12分频,即fosc/12。

SM0=0,SM1=1;此时进入工作方式1,工作模式是10位异步通信接受和发送器,波特率是可以变动设置的

SM0=1,SM1=0;此时进入工作方式2,工作模式是11位异步通信接受和发送器,波特率是晶振频率的64分频或者32分频,即fosc/64、fosc/32。

SM0=1,SM1=1;此时进入工作方式3,工作模式是11位异步通信接受和发送器,波特率是可以变动设置的

我们不介绍SM2,这个位用于进行多机通信(即一台单片机和多台单片机的通信),这里不展开细说。

接下来来看看REN位,该位是SCON的第四位,它是串行接收的开关,作用是控制开启允许接受控制位。当REN=1的时候才开启中断接收的开关,当REN=0,就关闭中断接收的开关。下一个我们先来看SCON.0的RI位,该位是接收中断标志位,接收到一帧数据后会将该位置为1,然后单片机检测到REN=1和RI=1就会开启中断通知CPU将数据从SBUF(接收缓存器)种拿走,并且手动清除RI位

接下来我们才来看第三位TB8,系统会将发送的一帧数据里面的第9位装载到TB8里面,一般一帧数据的第9位就是D8位(奇偶校验位),因为这个位我们之前说过可以作为设置该帧数据的属性,所以SCON寄存器会开一个位来存储要发送的数据的奇偶校验位。

然后就是RB8位,该位的作用是将接收到的数据的第9位(奇偶校验位)放到RB8里面,然后通过判断RB8的值来确定该接收到的数据的属性。

最后是TI位,该位是发送中断标志位,当一帧数据由SBUF缓冲器发送出去后,此时就会开启中断告诉CPU说SBUF发送缓冲器已经空了(数据发出去了),需要对下一组即将发送的数据进行装填到SBUF发送缓冲器,并且将TI手动清空

⭐SBUF的小问题

SBUF既做发送缓冲器和接收缓冲器,一般来说CPU是必须通过软件来判断当前的SBUF是处于哪种工作状态

🍎电源控制寄存器--PCON

PCON寄存器的字节地址是87H(不能位寻址,所以我们开启需要使用ORL字节或指令)。在这个寄存器中我们只看最高位SMOD,因为只有该位和我们的串行通信有关。

该位是用来控制波特率是否倍增的,只适用于工作模式1、2和3,当SMOD=1时使用的波特率会加倍

🐱波特率设计

上面我们看了一下PCON寄存器的SMOD位置1会让波特率增倍,回过头来看我们可以发现我们的四种工作方式中已经有两种:方式0和方式2是固定了波特率的,而方式1和方式3的波特率是可以改的,所以我们需要选择我们使用的波特率。但是由于振荡来源不同,所以各种工作方式的波特率计算方式又不同!

🍍方式0:

方式0的波特率是等于晶振的12分频,不受PCON中断SMOD位的影响,始终保持是fosc/12

🍍方式1 & 方式3:

方式1和方式3都是可以自选波特率的工作模式,其移位时钟脉冲输入是由T1定时器的溢出率来决定的。所以我们通过设置SMOD和定时器初值X来具体的计算方式如下:

波特率 = \frac{2^{SMOD}}{32} * [\frac{fosc}{12}/(2^{n}-init)],其中init就是初值,最常见的时候定时器T1选用的是模式2,此时n=8,所以X = 256 - \frac{fosc*(SMOD + 1)}{384 * baud}

🍍方式2:

相似地,方式2也是一个固定的波特率工作模式,但是它固定的波特率有两个,而这两个分别为fosc/64和fosc/32,而至于选择哪一种则有PCON的SMOD位来决定,当SMOD=0时,波特率=fosc/64;当SMOD=1时,波特率=fosc/32

但是在通常情况下,常用的波特率以及其对应的定时器需要设计的初值我们可以通过查询下面的表格来进行设计:

🐱串行口工作方式

下面我们来仔细看看如何用串行口来实现几种通信方式。

🥝串行方式0

方式0是需要有同步移位寄存器输入 / 输出的工作方式,即它的数据通信方式是同步通信。该模式不适用于两个单片机之间通信,它的功能是用作拓展IO口,其中以RXD为要发送的数据的输入和输出引脚;而TXD输出移位的时钟。下图即为拓展的串行->并行发送电路和并行->串行拓展接收电路,分别用到了74HC164和74HC165两块芯片。发送时P3.0口一次来一帧数据,然后该数据通过AB口被74HC164接收到后按低位在前的顺序被发送出去,而P3.1口就负责发送同步移位时钟信号;当接收时数据通过RXD口从74HC165传送到单片机,同时单片机的TXD引脚依然负责发送同步移位时钟信号,数据又低位在前被接收进去

🥝串行方式1

串行方式1是用于单片机间的发送与接收,为了方便我们不考虑多机通信,只考虑单对单的通信方式。从前面了解到工作方式1是10位异步收发,包括1个起始位,8个数据位和一个停止位,无奇偶校验位,并且由于是异步收发所以此时RXD和TXD就负责接收和发送数据,并且波特率可变。

🥝串行方式2、3

串行方式2和3都是适用于两块单片机通信的串口工作模式,其每一帧会发送11位的数据,其与前面的串行方式1的区别是多了一个奇偶校验位,该多出来的第九位数据会在发送时放入TB8,而接收时被放入RB8。

🐱通信方式举例

🐟1、同步通信

我们设计一个串口扩展并口的装置,利用到74LS164芯片,该芯片能够将串行输入改为并行输出,这次我们利用这个并行输出来实现流水灯效果。

该流水灯效果的代码如下:

	ORG 00H
	SJMP MAIN
	ORG 30H
MAIN:
	MOV R1, #08H
	MOV R0, #60H
	MOV 60H, #0FFH
	MOV SCON, #00H
	MOV A, @R0
	CLR C
	AJMP SEND
DELAY:
	MOV R5, #20
D2:
	MOV R6, #20
D1:
	MOV R7, #248
	DJNZ R7, $
	DJNZ R6, D1
	DJNZ R5, D2
	RET
SEND:
	RRC A
	MOV SBUF, A
WAIT_SEND:
	JNB TI, WAIT_SEND
	ACALL DELAY
	CLR TI
	DJNZ R1, SEND
	END


电路设计如下:

最终可以实现流水灯效果,不过我们还是来看看代码把。首先是设计两个寄存器R1和R0用来分别存储要发送的次数以及发送的内容,发送的内容会被存储到R0地址寄存器所对应的地址#60H处。然后我们设计一个初值0FF放到60H处。最后再配置好SCON寄存器即可,我们选择方式0所以设置的内容是00H。

然后我们再来看发送过程,发送过程共分两步:装填和发送。装填就是SEND函数所对应的内容,将累加器A内的内容(要发送的数据)写入SBUF发送缓冲器。然后就会进行自动发送,当发送完成后TI位就会被置1,所以我们通过JNB函数来进行等待发送,当发送完成就跳出死循环。然后清除TI位,最后判断循环次数完成没有来决定是否结束总的程序。

不过这里由于设置了流水灯效果,所以在每次装填数据之前将A内的数据进行移位以实现流水灯效果,例如一开始A是0FFH,由于Cy位被置0,所以移位完装填后就变成7FH,Cy位变为1,而下一次移位就变成20H...以此类推。

🐟2、异步通信

下面我们来看看如何进行异步通信:

例子:单片机A和单片机B的晶振都是11.0592Mhz,将单片机A存储器RAM里面#50H~#51H的内容传输到单片机B#60H~#61H处,使用

首先我们先确定要规划的步骤:

1、设置定时器产生波特率;

2、开启中断

3、设置串行口

首先我们选定要使用到的是定时器1的工作模式2一个波特率:4.8Kbps,则初值为#0FAH

发送端代码:

/*TXD*/

	ORG 00H
	AJMP MAIN
	ORG 30H
MAIN:
	MOV TMOD, #20H
	MOV TL1, #0FAH
	MOV TH1, #0FAH
	SETB TR1
	MOV SCON, #0C0H
	MOV R0, #02H
	MOV R1, #50H
	MOV 50H, #7FH
	MOV 51H, #19H
	MOV P1, 50H
	MOV P0, 51H
SEND:
	MOV A, @R1
	MOV C, PSW.0
	MOV SCON.3, C
	MOV SBUF, A
SEND_WAIT:
	JBC TI, NEXT
	SJMP SEND_WAIT
NEXT:
	INC R1
	DJNZ R0, SEND
	END

接收端代码:

/*RXD*/
	ORG 00H
	AJMP MAIN
	ORG 30H
MAIN:
	MOV TMOD, #20H
	MOV TL1, #0FAH
	MOV TH1, #0FAH
	SETB TR1
	MOV SCON, #0D0H
	MOV R0, #02H
	MOV R1, #60H
RECEIVE:
	JBC RI, CHECK 
	SJMP RECEIVE 
CHECK:
	MOV A, SBUF
	JBC RB8, CHECK_IF_1
	JBC PSW.0, ERROR 
	LJMP SUCCESS
CHECK_IF_1:
	JBC PSW.0, SUCCESS
	LJMP ERROR
SUCCESS:
	MOV @R0, A
	INC A
	DJNZ R0, RECEIVE
	SJMP RESULT	  
ERROR:
	SETB P2.0
	SJMP END_FUNC
RESULT:
	MOV P1, #60H
	MOV P0, #61H
END_FUNC:  
	END
	

最终效果: 


参考内容:

老师上课的课件 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/597181.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python笔记17_实例演练_二手车折旧分析p2

…… 书接上文 4.车辆等级维度 探查车龄为5年的车辆,折旧价值与车辆等级的关系。 # 筛选出车龄为5的数据创建新表 data_age5 data[data[age] 5] data_age5 # 分组聚合计算均值 data_car_level data_age5.groupby(car_level_name)[lowest_price].mean().reset…

16.2:岛屿数量问题

文章目录 岛屿数量问题方法一:采用递归的方法方法二:使用并查集的方法(map)方法三:使用并查集的方法(数组) 岛屿数量问题 测试链接:https://leetcode.com/problems/number-of-islan…

大数据:分布式计算,MapReduce,hadoop的计算组件,hive是sql分布式计算框架,底层就是基于MapReduce的

大数据:分布式计算,MapReduce,hadoop的计算组件,hive是sql分布式计算框架,底层就是基于MapReduce的 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学…

【C++】一文带你入门 STL

一 STL 组成 graph LRA[STL] --- B[容器 container]A --- C[配接器 adapter]A --- D[迭代器 iterator]A --- E[仿函数 function]A --- F[算法 algorithm]A --- G[空间配置器 allocator]二 常用容器 容器简介 下面我们来简单看一下这些容器的常用接口的使用,并分析…

更新中-深度学习实战中遇到的一些概念+少量代码

onnx ONNX 是一种用于机器学习模型的开放式表示格式,它可以让不同的深度学习框架之间共享模型。 import onnxruntime # 加载模型 session onnxruntime.InferenceSession(model.onnx) # 运行模型。第一个参数是输出变量列表,不指定的话返回所有值 outp…

ESP8266使用MicroPython接入ThingsBoard

1、概述 我们老大当初叫我学习microPython,这个可以直接将代码发到板子上,然后就可以跑,就相当于设备业务代码由我们来写,不仅仅是让嵌入式来写,嵌入式做的就是封装函数,我们可以调用.最终这个还是实现了,但是没有推广. 2、设备 我自己购买的设备是ESP8266,某宝上购买的,mic…

智能仓储系统哪家公司做的比较好?求推荐排名不错的智能仓储公司?

什么是仓储服务信息平台?仓储服务信息平台可以为企业提供哪些便利? 随着电商和物流行业的快速发展,仓储服务越来越受到人们的关注。为了更好地管理仓储服务,提高效率,降低成本,仓储服务信息平台也应运而生…

CTF国赛2023 - ukfc(四道逆向已下班)

没啥好说的,惜败已复现:badkey1、国粹、ezbyte、moveAside、ezAndroid Notice:复现时候的一些题解来源于各大战队的wp,比如F61d,侵删 Re ezbyte 首先跟踪很容易分析到前后缀 至于里面的,得知道是dwarf…

哪个牌子的电容笔好用?Apple Pencil平替

随着时代的进步,数码产品在人们日常生活中的使用频率越来越高,一个iPad和一支电容笔似乎已然成为人们主要的学习工具了。电容笔的发展速度很快,在众多的电容笔牌子中,什么牌子好用又便宜?下面,我来给大家推…

深度学习进阶篇[8]:对抗神经网络GAN基本概念简介、纳什均衡、生成器判别器、解码编码器详解以及GAN应用场景

【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍:【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化…

FastReport Business Graphics .NET 2023.1 Crack

FastReport 商业图形 .NET .NET WinForms 的数据可视化库 使用 FastReport 业务图形库,您可以可视化不同层次的数据,构建业务图表以供进一步分析和决策。 所有这些都可以直接在您的应用程序中工作! 利用 .NET 7、.NET Core、Blazor、ASP.NE…

数据采集学习心得

数据采集是指从互联网或其他数据源中收集数据的过程。在当今信息时代,数据采集已经成为了一项非常重要的技能。无论是在商业领域还是学术领域,数据采集都是非常必要的。本文将分享我在学习数据采集过程中的心得体会。 一、数据采集的重要性 在当今信息…

高考即将到来,如何选择大学和专业?(2023版本)

同学们,高考又快到了,怎么选择大学和专业一直是同学们心烦的事情,正所谓“选择大于努力”,选择错了,努力方向自然就错了,事倍功半,甚至南辕北辙,所以对此我们必需慎之又慎&#xff0…

Mybatis自定义分页插件及PageHelper源码分析

文章目录 前言一、自定义一个简单的mybatis分页插件?1.判断当前传参是不是一个Page,如果是page就进行转换。2.分页查询总条数3.修改原有sql4.执行原有方法5.存在问题: 二、PageHelper分析1.PageHelper简介2.PageHelper源码分析 三&#xff1a…

概率论:假设检验

参考书目:《行为科学统计精要》(第八版)——弗雷德里克J格雷维特 1、假设检验预备知识 Z分位数样本均值的分布标准误 参考: 概率论:样本与总体分布,Z分数与概率_格勒王的博客-CSDN博客如何理解样本和整体…

Linux入门到进阶

文章目录 前言一、第一章-初识Linux1.初识Linux2.虚拟机介绍3.VMware Workstation安装4.在VMware上安装Linux5.远程连接Linux系统6.扩展:WSL(Windows Subsystem for Linux)7.扩展:虚拟机快照 二、第二章-Linux基础命令1.Linux的目…

AMEYA360:纳芯微推出车规级耐高压、三线霍尔开关及锁存器NSM101x系列

纳芯微推出全新三线制车规霍尔效应开关/锁存器NSM101x系列,为数字位置检测提供高精度的解决方案,可被广泛应用于汽车执行器等的位置检测。 NSM101x产品系列包含了3个产品型号,即NSM1011(单极霍尔开关)、NSM1012(全极霍尔开关)、NSM1013(霍尔锁…

oracle19c介绍和windows上安装

目录 一、版本 (1)历史 (2)11g和12c管理方式区别 11g 12C (3)各个版本对操作系统要求 二、分类 (1)分为桌面类和服务器类 (2)分为企业版和标准版 三…

后端(一):Tomcat

我们之前的前端是被我们一笔带过的,那不是我们要讲的重点,而这里的后端则是重点。本章先来认识认识后端的基础。 Tomcat 是什么 我们先来聊聊什么叫做tomcat,我们熟悉的那个是汤姆猫: 这和我们Java世界中的Tomcat 不是同一只猫&…

包含合并单元格的表格快速排序

实例需求:现需要将原料配方成分表按照“原料含量”从高到低排序,如下图所示。由于表格中包含合并单元格,因此Excel的排序功能无法正常。 示例代码如下。 Sub demo()Dim data(), i, idx, k, slstRow Cells(Rows.Count, 2).End(xlUp).RowReDi…