MCS-51单片机原理及应用

MCS-51单片机原理及应用复习笔记

文章目录

单片机及MCS51的构成

单片微型计算机

单片微型机的基本概念
  • 定义:将微型计算机主机集成在单一IC芯片上
  • 应用特点:体积小、功耗低、应用方便、稳定可靠
  • 发展方向:大容量、高性能、低功耗、外围电路内装化
单片机的基本构成
  1. CPU
  2. 存储器
  3. IO接口
  4. 内部总线
嵌入式系统的基本特点
  • 体积小
  • 功耗低
  • 专用性强

MCS-51单片机的基本构成

硬件配置
  • 128B数据存储器(还有高128B作为SFR区域)
  • 4kB的Flash程序存储器
  • 4个可编程的P口(P0~P3)
  • 两个可编程的定时器/时钟(T0/T1)
  • 一个可编程的UART串口
控制总线CB
  • E A ‾ \overline{\rm \small EA} EA:外部程序存储器访问允许控制端
  • P S E N ‾ \overline{\rm \small PSEN} PSEN:片外程序存储器读选通信号
  • ALE:低8位地址锁存允许信号
  • W R ‾ \overline{\rm \small WR} WR:片外RAM写选通信号
  • R D ‾ \overline{\rm \small RD} RD:片外RAM读选通信号
  • I N T 0 ‾ \overline{\rm \small INT0} INT0
  • I N T 1 ‾ \overline{\rm \small INT1} INT1
  • T 0 ‾ \overline{\rm \small T0} T0
  • T 1 ‾ \overline{\rm \small T1} T1
  • RESET

存储器及其空间配置

数据存储器

00H~1FH, 通用工作寄存器组(4个8B的工作寄存器组合),最常用的运算数据暂存位置;
20H~2FH, 位寻址区, 用于位操作;
30H~7FH, 用户RAM区, 可用于暂存不常用的用户数据;
高128B用于SFR

片内128B RAM的访问使用MOV指令,片外数据存储器/IO的访问使用MOVX指令

程序存储器
特殊单元意义
0000HPC复位值,程序的起始位置
0003HINT0中断入口地址
000BHT0中断入口地址
0013HINT1中断入口地址
001BHT1中断入口地址
0023HUART中断入口地址
002BH(52系列)T2中断入口

内外程序统一用MOVC查表指令进行访问, E A ‾ \overline{EA} EA引脚决定访问内部/外部程序存储器

  • 为低电平时,访问外部程序存储器
  • 为高电平时,先访问内部程序存储器,超出后自动转向外部程序存储器
SFR
  • 高128BRAM中共分布有21个SFR
  • 可位寻址SFR的特点:字节地址末位为0或8

对于可位寻址的SFR,其每一位都可以通过位操作进行访问

重点列表

SFR含义使用特点复位初始值意义
SP堆栈指针先加后压,先弹后减07H指示堆栈顶的位置
PSW程序状态字F0位未定义;P指示累加器A中1个数的奇偶性;RS1/RS0选择R区;Cy为进位位,也是位操作的常客00H
PC程序计数器指向下条语句的存储地址00H
DPTR数据指针16-bit,可分为两个8位寄存器DPL和DPH00H
P0~P34个P口FFH
逻辑地址空间配置(哈佛/普林斯顿结构)
哈佛结构(独立编址)
部件区分方式
外部ROM/RAM共用逻辑地址0000H~FFFFH外部ROM使用MOVC,外部RAM使用MOVX
内外数据存储器内部用MOV,外部用MOVX
接收/发送SBUF接收SBUF只读不写,发送SBUF只写不读
普林斯顿结构(统一编制)
部件区分方式
内/外程序存储器取决于引脚 E A ‾ \rm \overline{EA} EA 的电平
外部数据存储器/IO引脚 I O / M ‾ \rm IO/\overline{M} IO/M 的电平可以区分
高/低128B RAM(52子系列)

R0~R7共有四组,这样看是重叠的,即统一编址;单看每个区的R0~R7又是独立编址


MCS-51的时序和复位

时序概念和关系
  1. 时钟周期
    时钟周期是单片机的基本时间单位。
  2. 机器周期
    • 机器周期是单片机完成一个基本操作所需的时间
    • 一个机器周期包含6个状态周期,每个状态周期分为两拍(即两个时钟周期)
  3. 指令周期
    • 指令周期是取出并执行一条指令所需的时间
    • 一般单/双字节指令为单/双机器周期;三字节指令都是双机器周期
    • 只有乘/除指令为4个机器周期
复位操作

给RST引脚加大于2个机器周期的高电平即可使其复位,复位时PC初始化为0000H


MCS-51的并行IO端口

MCS-51的4个P口均为“准双向口”

每个口对应:

  1. 一个口锁存器
  2. 一个输出控制电路
  3. 一个输出驱动器
  4. 两个输入三态缓冲器

系统访问外部存储器(或IO),由P0给出低8位地址,P2给出高几位地址。
P0分时复用(此时P0为真正的双向口)

准双向口:IO口输出转为输入时,需先向口锁存器写1,使下拉FET截止

P0

功能1:地址/数据总线(分时复用,真正的双向口)

功能2:通用IO口

作为通用IO口时,需外接上拉电阻

P1

普通IO口

P2

功能1:地址总线

功能2:通用IO口

访问外部存储器时,P2口用于输送高8位地址;访问结束后,原先锁存器的内容自动恢复

P3

功能1通用IO口

功能2:第二功能

第二功能见后方

⭐️需注意的问题
P2口的节省问题
  • 当片外已拓展程序存储器时,PC高8位自动从P2口输出,此时P2口不可做为一般IO口

  • 当片外未拓展程序存储器而有数据存储器时,分下面两种情况

    • 当外部RAM <= 256Bytes时,可考虑使用@Ri间址方式访问(而非@DPTR),于是P2口仍作为普通IO口
    • 当外部RAM > 256Bytes但不超过太多时,仍可采用@Ri方式传送低8位地址,然后将高几位地址传送给P2,同时P2口的高位保持不变,从而节省了P2口

P2口节省的实现代码见程序示例

P3口的第二功能
引脚第二功能描述
P3.0RXD串行输入口
P3.1TXD串行输出口
P3.2 I N T 0 ‾ \rm \overline{\small INT0} INT0外部中断0输入
P3.3 I N T 1 ‾ \rm \overline{\small INT1} INT1外部中断1输入
P3.4T0定时器0外部计数输入
P3.5T1定时器1外部计数输入
P3.6 W R ‾ \rm \overline{\small WR} WR外部RAM写选通输出
P3.7 R D ‾ \rm \overline{\small RD} RD外部RAM读选通输出
读引脚和读锁存器
  • 读引脚:读引脚前,需确认为IO口为输入状态,否则应先写1转为输入态
  • 读锁存器:读取锁存器电平(保存着P口的前一状态,而非当前引脚电平)以便修改后送出,对应有“读-修改-写”指令1
设置两种“读方式”的原因

硬件系统设计者考虑到使用者可能错误设计外部电路的引脚电平,导致引脚、锁存器输出电平不同,所以设计了两种方式,保证一定可以通过某种方式得到正确的结果。


MCS-51的定时/计数器

工作方式控制寄存器TMOD(不可位寻址)
GATE C / T ‾ C/\overline{T} C/TM1M0GATE C / T ‾ C/\overline{T} C/TM1M0
控制T1控制T0
  • GATE:门控位
    • GATE=0时, T R x = 1 TR_x=1 TRx=1即开始计数
    • GATE=1时, T R x = 1 TR_x=1 TRx=1 I N T x ‾ = 1 \overline{INT_x}=1 INTx=1才开始计数
  • {M1,M0}工作方式选择
    • 方式0:13位定时/计数器
    • 方式1:16位定时/计数器
    • 方式2:8位自动重装载C/T(常用作UART波特率发生器)
    • 方式3:两个8位C/T(只适用于T0!)
  • C / T ‾ C/\overline{T} C/T:模式选择
    • C / T ‾ C/\overline{T} C/T=0,定时器模式(一个机器周期发生一次跳变)
    • C / T ‾ C/\overline{T} C/T=1,计数器模式,对外部输入引脚T0/T1的跳变进行计数

TMOD字节地址为89H,不可位寻址

C/T控制寄存器TCON(可位寻址)
TF1TR1TF0TR0IE1IT1IE0IT0
C/T相关外部中断相关
  • TF:时钟溢出标志
    • 查询方式下,查询有效后应当软件清零
    • 中断方式下,硬件自动清零
  • TR:高电平则开始计数/计时2

TCON字节地址为88H,可位寻址

🔥初装值X的计算

假设晶振频率为Y MHz,需定时的时长为T,定时器的位数为n

定时器跳变一次的时间是一个机器周期,则初装值X满足

T = 12 Y ( 2 n − X ) T = \frac{12}{Y}(2^n-X) T=Y12(2nX)
解得
X = 2 n − T Y 12 X = 2^n -\frac{TY}{12} X=2n12TY

需注意在各种方式下的最大/最小定时时间

最高外部计数频率 & 最小电平维持时间
  1. 由于确认一次负跳变需要两个机器周期,所以外部输入的计数脉冲的最高频率为
    f o s c / 12 2 \frac{f_{osc}/12}{2} 2fosc/12

  2. 为了确保给定电平在变化之前能被采样一次,其至少要保持一个机器周期


MCS-51的通用异步串行口(UART)

UART的结构
  • 支持全双工通信
  • P3.0 RXD | P3.1 TXD
  • 两个SBUF共用一个字节地址99H
串行口控制寄存器SCON(可位寻址)
SM0SM1SM2RENTB8RB8TIRI
位标志作用说明
SM0, SM1工作方式选择位
SM2多机通信控制位方式0必须置为0;方式1时若SM2=1,则只有接收到有效的停止位才能使RI=1;方式2、3中用于指示可程控位的性质,第九位为1则为地址帧,只有SM2=1的从机才能接收,第九位为0则为数据帧,只有SM2=0的从机才能接收
REN接受允许位
TB8发送的第九位数据方式0、1都不用
RB8接收的第九位数据方式0不用;方式1时若SM2=0则RB8就是接收到的停止位;方式2、3中就是接收到的第九数据位
TI/RI串行口(发送、接收完成)中断请求标志位,需要用户清楚
电源控制寄存器PCON(不可位寻址)

SMOD(PCON.7)又称‘波特率倍增位’

❤️工作方式对比
波特率计算

方式0:固定波特率 B A U D = f o s c 12 BAUD = \frac{f_{osc}}{12} BAUD=12fosc

方式2 B A U D = 2 S M O D 64 ⋅ f o s c BAUD = \frac{2^{SMOD}}{64}\cdot f_{osc} BAUD=642SMODfosc

方式1,33
B A U D = 2 S M O D 32 ⋅ f o s c 12 ( 256 − X ) BAUD = \frac{2^{SMOD}}{32}\cdot \frac{f_{osc}}{12(256-X)} BAUD=322SMOD12(256X)fosc

工作方式比较
工作方式功能帧长帧格式
方式0同步移位寄存器(IO拓展)88位数据
方式18位异步收发101位起始位+8位数据+1位停止位
方式29位异步收发111位起始位+8位数据+1位程控位(TB8/RB8)+1位停止位
方式39位异步收发111位起始位+8位数据+1位程控位(TB8/RB8)+1位停止位
收发特点和有效接收条件
工作方式TB8/RB8多机通信产生最后一次移位脉冲时,装载SBUF和RB8并置RI=1的条件
方式0不用不支持RI=0
方式1停止位不支持RI=0; SM2=0或接收到有效停止位1
方式2程控第9位支持RI=0; SM2=0接收到第九数据位1
方式3程控第9位支持同方式2

方式2、3只是波特率不同,其它都是一样的


MCS-51的中断系统

中断请求源
TCON中的中断请求标志位
TF1TF0IE1IT1IE0IT0
TCON.7TCON.5TCON.3TCON.1
  • TF1、TF0分别是时钟T1、T0的计数溢出标志,响应后自动清零4
  • IE1、IE0分别是外部中断INT1、INT0的请求标志,响应后自动清零
  • IT1、IT0分别为外部中断INT1、INT0的标志位置位方式选择位
    • IT=0,表示电平触发
    • IT=1,表示高到低的跳变沿触发
SCON中的中断请求标志位
TIRI
SCON.1SCON.0

TI、RI是串行口中断请求标志位5

  • TI:串行口的发送中断请求标志位
    • 每发送完一帧串行数据,TI被硬件置1,需在中断服务内手动清零
  • RI:串行口的接收中断请求标志位
    • 每接收完一帧串行数据,RI被硬件置1,需在中断服务内手动清零
中断请求标志的自动清零与否

在中断模式下,只有TI、RI不会自动清零

在查询模式下,则在查询有效后必须手动清零

中断允许控制

中断控制寄存器IE(可位寻址)

EAESET1EX1ET0EX0
  • EA——中断允许总开关
  • ES——串行口中断允许
  • ET 0 , 1 _{0,1} 0,1——时钟中断允许
  • EX 0 , 1 _{0,1} 0,1——外部中断允许

可见,MCS-51的中断系统具有两级中断允许控制: 总开关+分开关

中断优先级控制(两级中断优先级)
编程优先级

中断优先级寄存器IP(可位寻址)

PSPT1PX1PT0PX0
  • PS——串行口中断优先级
  • PT 0 , 1 _{0,1} 0,1——时钟中断优先级
  • PX 0 , 1 _{0,1} 0,1——外部中断优先级

注意在进入中断结束后,IP将被清0

查询优先级

在收到同一编程优先级的中断请求时,CPU响应中断请求存在以下的查询优先级

中断源查询优先级
INT0最高
T0 ↑ \uparrow
INT1 ↑ \uparrow
T1 ↑ \uparrow
UART最低
响应中断请求条件

CPU在每个机器周期内对所有中断请求源进行顺序检测,响应中断后,置位中断标志位

基本条件
  1. 总中断允许EA=1
  2. 对应中断请求标志位=1
  3. 对应中断允许位=1
特殊条件
  1. CPU未在处理同级或者更高编程优先级的中断6
  2. 中断请求查询有效的机器周期应为当前执行指令的最后一个机器周期(只有在当前指令执行完毕时才能响应中断请求)
  3. 正在执行的指令不是RETI或者访问IE、IP的指令7
最小响应时间

外部中断的最短响应时间为3个机器周期:

  • 查询中断请求标志位,一个机器周期
  • 查询有效时上条指令恰执行到最后一个机器周期,则执行当前指令后,自动LCALL add16转到中断入口地址,占用两个机器周期
中断响应过程
  1. 将当前PC值压入堆栈进行保护(自动完成)
  2. 将中断服务程序入口地址装入PC寄存器(LCALL add16,自动)
  3. 保护现场(PUSH 寄存器/存储器单元)
  4. 执行中断服务程序:此时可响应更高级的中断
  5. 恢复现场(POP 寄存器/存储器单元)
  6. 中断返回RETI:从堆栈中弹出保存的断点地址给PC寄存器(自动完成),继续中断前的程序执行

中断响应时,PC自动入栈,但PSW则需手动入栈

中断响应时,自动LCALL,所以在中断入口处设置跳转指令,而非调用指令

堆栈作用:保护断点和现场保护

汇编语言

指令系统

数据传送类

一般传送指令MOV

访问外部RAM指令MOVX
  • MOVX A, @DPTR
  • MOVX @DPTR, A
  • MOVX A, @R i _i i
  • MOVX @R i _i i, A

一旦使用MOVX指令,P0口的输出就自动作为低8位地址,P2口的输出就自动作为高8位地址

DPTR的间址方式可以访问64KB的片外RAM
R i _i i间址则只能正确访问256B的片外RAM

可见寄存器A的特殊性,此外R i _i i只能是R 0 _0 0或R 1 _1 1

查表指令MOVC
指令代码注意
近程查表指令MOVC A, @A+PC由于PC的值不能自己确定,而A为8-bit的寄存器,所以表格只能在该查表指令后面的256个单元之内
远程查表指令MOVC A, @A+DPTR
堆栈操作指令
  • PUSH:先加后压 sp+1–>sp
  • POP: 先弹后减 sp-1–>sp
算术运算类
加减运算
指令操作码注意
加法指令ADD目的操作数只能是寄存器A
自增指令INC允许INC DPTR
自减指令DEC不可以DEC DPTR
乘除运算
指令代码注意
乘法指令MUL AB乘积结果低8位在A中,高8位在B中
除法指令DIV AB商在A中,余数在B中

只有乘除指令占用4个机器周期

逻辑操作类

CLR(清零)

CPL:按位逻辑取反(不影响标志位)

ANL

ORL

XOR

控制转移类
跳转指令
  1. 无条件转移AJMP(2KB范围内)

  2. 相对转移SJMP(-128B~127B范围内)

  3. 长跳转LJMP(64KB范围内)

  4. 间接跳转JMP @A+DPTR8

条件跳转指令
  • 比较不等转移CJNE
    compare–> Not Equal? Yes–> Jump
  • 减不为零转移DJNZ
    decrease–> Not Zero? Yes–> Jump
调用子程序指令
  • 短调用ACALL(2KB内)

  • 长调用LCALL(64KB内)

调用子程序时,PC将被压入堆栈

子程序返回指令
  • 子程序返回RET

  • 中断返回RETI(返回时还将中断优先级控制寄存器IP清零)

子程序返回时,PC将被弹出堆栈

注意在中断入口设置中 应用AJMP INT_XX,而不是调用子程序。因为中断响应时已经LCALL一次了,此LCALL应与中断返回RETI匹配,否则中断程序实际并不会结束!

空操作

NOP
不进行任何实际操作,只消耗一个机器周期的时间,且执行PC+1–> PC

位操作(与进位标志C关系密切)

合法位操作区域:

  1. RAM可位寻址区20H~2FH
  2. 以0H或者8H结尾的SFR

除此之外的单元直接进行位操作都是非法的!

条件转移类
指令含义
JBbit? Yes --> Jump
JCcarry? Yes --> Jump
JNCnot carry? Yes --> Jump
JNBnot bit? Yes --> Jump
JBCbit? Yes --> Jump and Clear
✨偏移量rel的计算

rel = 目的地址 - 转移指令所在地址 - 转移指令长度

偏移量rel是一个带符号的8位二进制数补码(-128~+127)

程序设计

小知识
操作数的表示
  • 后缀缺省时表示十进制,一般以十六进制H作为后缀
  • 数值不能以字符开头,需加前缀0。例如不能写为A3H,而应写为0A3H
美元符号$

美元符号$表示当前指令所在地址,下面是示例

JNB F0, \$   ; 若F0=0恒成立,则反复执行该语句

SJMP \$      ; '原地踏步'
伪指令

伪指令是为汇编服务的,在汇编时没有机器代码与之对应

指令代码示例代码含义
汇编起始地址命令 ORGORG 100H表示下面的程序段从0100H开始
字节定义 DBDB 0A6H, 0B1H定义TAB中第一个字节单元为A6H,第二个字节单元为B1H
字定义 DWDW 00A6H, 00B1H定义TAB中第一个字单元为00A6H,第二个字单元为00B1H
位定义 BITEN BIT P1.0EN就表示端口位P1.0
字节定义 DATACOUNTER DATA 30HCOUNTER就表示字节地址为30H的单元
赋值 EQUNUM EQU 1000H标号NUM就是数值1000H
汇编终止命令 ENDEND汇编结束

MCS-51系统拓展技术

系统拓展原理

✅片外三总线结构
总线构成
地址总线ABP0(输出低8位地址,需要地址锁存器)P2(输出高8位地址)
数据总线DBP0(分时复用)
控制总线CB P S E N ‾ , W R ‾ , R D ‾ \rm \overline{\small PSEN}, \overline{\small WR}, \overline{\small RD} PSEN,WR,RD
程序存储器拓展原理
  • 单片机的 P S E N ‾ \rm \overline{\small PSEN} PSEN引脚连接EPROM的 O E ‾ \rm \overline{\small OE} OE引脚
  • 单片拓展时,EPROM的 C E ‾ \rm \overline{\small CE} CE引脚可直接接地
  • 拓展多片时,各ROM芯片的 C E ‾ \rm \overline{\small CE} CE应根据地址分配进行连接
数据存储器拓展原理
  • 单片机的 W R ‾ \rm \overline{\small WR} WR连接SRAM的 O E ‾ \rm \overline{\small OE} OE引脚
  • 单片机的 R D ‾ \rm \overline{\small RD} RD连接SRAM的 W E ‾ \rm \overline{\small WE} WE引脚
  • SRAM片选引脚 C E ‾ \rm \overline{\small CE} CE同程序存储器

ROM/RAM综合扩展

地址空间分配
分配方法说明
线选法将未用的高位地址线作为存储器芯片的“片选”信号
译码法使用译码器对未用的高位地址线进行译码后作为存储器芯片的“片选”信号
片选问题、总线冲突问题
  1. 同类存储器之间地址不可重叠(即 C E ‾ \rm \overline{CE} CE不可同时有效)
  2. 程序存储器和数据存储器之间地址可以重叠
  3. 不冲突的原因: P S E N ‾ \rm \overline{PSEN} PSEN / W R ‾ \rm \overline{WR} WR / R D ‾ \rm \overline{RD} RD三个信号是在执行指令时产生的,而同一时刻只会执行一条指令,使得其中一个信号有效,这样就不会发送数据冲突

IO接口扩展

一般IO口拓展
P0口用于拓展

原则:输入缓冲,输出锁存

串口方式0用于拓展

当MCS-51单片机串行口工作在方式0时,使用移位寄存器芯片可以拓展一个或多个8位并行IO口

优点:不占用片外RAM地址,节省单片机的硬件开销

缺点:操作速度较慢(拓展芯片越多,速度越慢)

可编程IO口拓展芯片81C55
81C55芯片介绍
  • 并行方式
  • 256B的SRAM
  • 7个端口
    • 8-bit PA
    • 8-bit PB
    • 6-bit PC
    • 计数器低8位
    • 计数器高6位
    • 命令/状态寄存器(共用一个端口地址)
  • 内部有地址锁存器
👉典型硬件连接和地址分配
C E ‾ \rm \overline{CE} CEIO/ M ‾ \rm \small \overline{M} MA7~A3A2A1A0选中端口
00********256B RAM
01000命令/状态寄存器
01001PA
01010PB
01011PC
01100计数器低8位
01101计数器高6位

程序示例

查表指令应用

ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
  MOV DPTR, #TAB 
  MOVC A, @A+DPTR
  SJMP $

ORG 1000H
TAB:
  DB 01H, 21H, 0F1H 
END

P2口节省

设定属于<外部RAM > 256Bytes但不超过太多,需要11位地址>的情况

MOV R0, #add_L      ; add_L是低8位地址
MOV A, #00000XXXB   ; XXX是高3位地址
ANL P2, #11111000B  ; 低3位清0,其余位保持不变
ORL P2, A           ; 低3位地址写入P2低3位,其余位不变
MOVX A, @R0         ; @R0间址方式传送,低8位从P0口输出,高3位自动从P2口传输

外部中断拓展(基于定时器中断)

使用定时器中断,外部引脚输入一个负跳变即进入中断

ORG 0000H
LJMP MAIN
ORG 001BH
AJMP INT_T1
ORG 0030H
MAIN:
  MOV SP, #5FH            ; 抬高堆栈
  MOV TMOD, #01100000B    ; 计数器模式/方式2,引脚P3.5用于计数器1的外部输入
  MOV TH1, #FFH
  MOV TL1, #FFH           ; 外部负跳变一次,即进入计数器中断
  SETB TR1
  SJMP $

INT_T1:                   ; 拓展的外部中断处理程序
  ...
  RETI
END

矩形脉冲输出

从P1.0输出高低电平为10:1、周期为400 μ s \mu s μs的矩形脉冲,系统振荡频率为6MHz

粗略计算,高电平应为364 μ s \mu s μs,低电平为36 μ s \mu s μs

使用T1的方式1

时钟中断方式
ORG 0000H
LJMP MAIN
ORG 000BH
AJMP INT_T0
ORG 0030H
MAIN:
  MOV TMOD, #00010000B    ; Timer1方式1
  MOV TL0, #4AH
  MOV TH0, #0FFH          ; 赋初值0FF4AH
  SETB TR1
  SETB ET0
  SETB EA
  SETB P1.0               ; 输出高电平
  SJMP $

INT_T0:
  CLR EA
  CLR P1.0                ; 输出低电平
  MOV R0, #9              
OUTPUT_VL:
  DJNZ R0, OUTPUT_VL      ; 双机器周期指令,执行9次耗时18个机器周期即36μs
  MOV TL0, #4AH
  MOV TH0, #0FFH          ; 手动重载
  SETB P1.0
  SETB EA
  RETI
END
时钟查询方式
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
  MOV TMOD, #00010000B    ; Timer1方式1
HIGH:
  MOV TL0, #4AH
  MOV TH0, #0FFH          ; 赋初值0FF4AH
  SETB TR1
  SETB P1.0               ; 输出高电平
  JNB TF1, $              ; 等待溢出
  CLR P1.0                ; 输出高时溢出,则转输出低电平
  MOV R0, #9              
LOW:
  DJNZ R0, LOW            ; 双机器周期指令,执行9次耗时18个机器周期即36μs
  AJMP HIGH               ; 转输出高电平
END

串口通信

数据位于1000H开头的20个单元中,波特率为2400 bits/s,系统振荡频率为11.0592MHz

使用方式1进行发送

UART查询方式

发送程序

ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
  MOV SP, #5FH          ; 抬高堆栈
  MOV DPTR, #1000H
  MOV R0, #20
  ACALL INIT_UART
  SETB TR1
LOOP:
  MOVC A, @A+DPTR
  ACALL SEND
  INC DPTR
  DJNZ R0, LOOP
  SJMP $

INIT_UART:
  MOV TMOD, #0010000B   ; T1方式2
  MOV TH1, #0F4H
  MOV TL1, #0F4H
  MOV SCON, #01000000B  ; 串口方式1
  RET

SEND:
  MOV SBUF, A           ; 传送数据
  JNB TI, $             ; 传送完毕后退出
  RET
END
UART中断方式

发送程序

ORG 0000H
LJMP MAIN
ORG 0023H               ; 串口中断入口
AJMP INT_TRANS
ORG 0030H
MAIN:
  MOV SP, #5FH          ; 抬高堆栈
  MOV R0, #21
  ACALL INIT_UART
  SETB TR1
  SETB ES
  SETB EA
  MOV SBUF, A           ; 传送数据
  SJMP $

INIT_UART:
  MOV DPTR, #1000H
  MOVC A, @A+DPTR
  MOV TMOD, #0010000B   ; T1方式2
  MOV TH1, #0F4H
  MOV TL1, #0F4H
  MOV SCON, #01000000B  ; 串口方式1
  RET

INT_TRANS:
  CLR TI
  DJNZ R0, NEXT   
  AJMP FINISHED         ; 完成所有数据的传送,跳转FINISHED语句
NEXT:
  INC DPTR
  MOVC A, @A+DPTR
  MOV SBUF, A
  RETI
FINISHED:
  ...
  RETI
END

接收程序

ORG 0000H
LJMP MAIN
ORG 0023H               ; 串口中断入口
AJMP INT_RECEIVE
ORG 0030H
MAIN:
  MOV SP, #5FH          ; 抬高堆栈
  MOV R0, #30H
  ACALL INIT_UART
  SETB TR1
  SETB ES
  SETB EA
  SETB REN              ; 允许接收
  MOV A, SBUF           ; 接收数据
  SJMP $

INIT_UART:
  MOV TMOD, #0010000B   ; T1方式2
  MOV TH1, #0F4H
  MOV TL1, #0F4H
  MOV SCON, #01000000B  ; 串口方式1
  RET

INT_RECEIVE:
  CLR RI
  MOVX @R0, A
  CJNE R0, #43H, NEXT
  AJMP FINISHED         ; 接收完毕
NEXT:
  INC R0
  MOV A, SBUF
  RETI
FINISHED:
...
  RETI
END
(带奇校验)的串口通信

甲机发送:从内部RAM 20H-25H依次取6个ASCII码字符,在最高位加上奇校验位后发送给乙机
乙机接收:对接收的8位数据先进行奇校验,校验正确后存入本机内部RAM 20-25H,校验错则将FFH存入对应单元

由串口方式1进行发送,1200bits/s,系统时钟频率为11.0592MHz

ASCII码只有7位有效,最高位为0

发送端关键代码

  MOV R0, #20H
LOOP:
  MOV A, @R0
  MOV P, C
  CPL C             
  MOV ACC.7, C      ; 最高位加上奇校验位,此时正确的发送数据若送A,P应为1
  ACALL SEND
  JNB TI, $         ; 等待发送完毕
  CLR TI
  INC R0
  CJNE R0, #26H, LOOP

接收端关键代码

  MOV R0, #20H
LOOP:
  JNB RI, $         ; 等待接收完毕
  CLR RI
  MOV SBUF, A
  MOV C, P
  JNC ERROR         ; 接收的数据不是奇数个1,则数据有误
  MOV @R0, A
NEXT:  
  INC R0
  CJNE R0, #26H, LOOP
  AJMP FINISHED     ; 接收完毕
ERROR:
  MOV @R0, #0FFH
  AJMP NEXT

  1. 读修改写指令示例
    INC P1
    XOR P3, A
    ORL P2, A
    ANL P1, A
    CPL P3.0 ↩︎

  2. 在MCS-51中,计时的本质是计数 ↩︎

  3. 前面提到定时器的方式2常用作波特率发生器,其实256就是 2 8 2^8 28 ↩︎

  4. 在查询模式下,查询有效后需手动清零 ↩︎

  5. 它们共用同一个中断入口0023H,所以在进入中断后,应当判断中断源到底是接收中断RI还是发送中断TI ↩︎

  6. 注意,若为同一编程优先级,则不可被打断(即便其查询优先级可能更高) ↩︎

  7. 中断系统规定,在执行完上述指令后,需要再执行一条指令,才能响应新的中断请求(即当前不是请求中断的时机) ↩︎

  8. DPTR为定义的表位置,比如说第一个单元跳转A1处理,第二个单元跳转A2处理,这样就实现了程序的多分支转移 ↩︎

  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值