第一章 概述
80C51命名规则
- 80C51/52
- 89C51/52
- 87C51/52
89C51和89C52的区别
- 片内通用RAM:128 bytes / 256 bytes
- 片内Flash Rom容量:4k bytes / 8k bytes
- 定时器:89C52有3个定时器(16位),比89C51(定时器也是16位)多一个T2。
第二章 基本结构
IO口
4个8位口,其中P0,P2可作为扩展数据/地址线。
- P0口:双向I/O口,可用作地址数据总线(低8位地址及数据)
- P1口:准双向I/O口
- P2口:准双向I/O口,可用作总线,高8位地址
- P3口:准双向I/O口,具有第二功能
- P0~3口作I/O输入时,必须先向电路中的锁存器写入“1”,使输出驱动电路的FET截止。
- P1~3口作为通用I/O口使用时,不需要外接上拉电阻。
P0口
作为通用IO口时,(漏极开路)必须加上上拉电阻。
当P0口作为输入口使用时,应区分读引脚和读锁存器两种情况:
凡属于读-修改-写方式的指令从锁存器读入信号,其它指令则从端口引脚线上读入信号。
- 51:灌电流能力强于拉电流能力(允许最大输入大于最大输出),IO口在复位时的状态为1(高电平)。
- Cortex-M(GPIO):灌电流能力与拉电流能力相同,IO口在复位时的状态为高阻态。
P3口第二功能
口线 | 第二功能 | 信号名称 |
P3.0 | RXD | 串行数据接收 |
P3.1 | TXD | 串行数据发送 |
P3.2 | INT0 | 外部中断0申请 |
P3.3 | INT1 | 外部中断1申请 |
P3.4 | T0 | 定时器/计数器0计数输入 |
P3.5 | T1 | 定时器/计数器1计数输入 |
P3.6 | WR | 外部RAM写选通 |
P3.7 | RD | 外部RAM读选通 |
特殊引脚
字母上方有/无横线:低/高电平有效
复位输入信号,高电平有效。
(External Access)
片外程序存储器访问允许,低电平有效。
- EA=1,选择片内;EA=0,选择片外。
锁存,地址锁存允许信号输出。访问外部存储器时,实现低8位数据与地址分开。
取指,片外程序存储器读选通信号,低电平有效。
特殊指针和寄存器
51中的PC不可直接访问,与程序存储器地址相关。
程序计数器PC是一个独立的计数器,不属于内部的特殊功能寄存器。
PC中存放的是下一条将要从程序存储器中取出的指令的地址。
基本的工作过程:读指令时,程序计数器PC将其中的数作为所取指令的地址输出给程序存储器,然后程序存储器按此地址输出指令字节,同时程序计数器PC本身自动加1,指向下一条指令地址。
在执行转移时,PC被系统自动置入目标地址。
规则:后进先出,入栈
PUSH
,出栈 POP
。MCS-51的堆栈只能开辟在芯片内部的数据存储器中。
SP:专用寄存器地址81H,SP的内容是堆栈栈顶的地址,系统复位后SP的内容是07H。

堆栈是为子程序调用和中断操作而服务的,实现保护断点和保护现场。
- 堆栈在子程序调用和中断的时候自动把端点地址进栈和出栈。
LCALL
,RET
,中断都会对堆栈操作。
- 通过
PUSH
,POP
指令,用于保护现场和恢复现场。
51中的DPTR可直接访问,与数据存储器地址相关。
DPTR是一个16位的特殊功能寄存器,也可作为2个8位寄存器(
DPH
& DPL
)。主要功能是作为片外数据存储器或I/O寻址用的地址寄存器(间接寻址)或基址寄存器(变址寻址),故称为数据存储器地址指针。
单片机的大部分数据操作都要通过累加器A
主要功能:累加器A存放操作数,是ALU单元的输入之一,也是ALU运算结果暂存单元。缺点:累加器的“瓶颈”作用改进:寄存器阵列取代累加器
*B寄存器
- 在乘法(输入&高8位结果)和除法(除数&余数)指令中作为ALU的输入之一。
- 在其它情况下,B寄存器可以作为内部RAM中的一个单元来使用(类似ACC,但不完全)。

PSW.7 CY 进位标志
PSW.6 AC 辅助进位标志
PSW.5 F0 用户标志
PSW.4 RS1 寄存器组选择
PSW.3 RS0 寄存器组选择
PSW.2 OV 溢出标志, 带符号数加减运算溢出; 乘法积超过8位;除数为0
PSW.1 未用
PSW.0 P 奇偶标志
机器周期和指令周期

振荡脉冲(晶振)二分频为单片机时钟信号,时钟信号三分频为ALE,时钟信号六分频为机器周期。
- 节拍P:振荡脉冲周期P。
- 状态S:振荡周期的二分频,系统的时钟信号。前半周期对应的节拍叫P1,后半周期对应的节拍叫P2。
- 机器周期:一个机器周期的宽度为6个状态,并依次表示为S1~S6。
- 指令周期:执行一条指令所需要的时间称为指令周期。不同指令可包含有一、二、四个机器周期。
指令时序图

存储器结构和地址空间
两种基本结构
- 普林斯顿结构
- 统一编码,地址空间重合。
- 采用的将程序和数据合用一个存储器空间的结构(总线统一)。
- 哈佛结构
- 分别编码,地址空间独立。
- 将程序存储器和数据存储器截然分开,分别寻址的结构(总线独立)。
- 如MCS-51系列单片机(非典型哈佛结构,数据总线和程序总线硬件上不分离)。
- 如Cortex-M(改进型哈佛结构,总线硬件分离✅,地址空间重合❌)

三个存储器地址空间(逻辑上)
片内、片外统一的64KB程序存储器地址空间
- 16位的PC以及16位的地址总线,寻址空间:。
- 整个程序存储器可以分为片内(ROM)和片外两部分。
- 由EA引脚所接的电平来确定CPU访问片内和片外存储器。
访问片外存储器时,当PC值超出片内ROM(4K)容量时,会自动转向片外程序存储器空间(1000H~FFFFH)执行。
7个特定保留地址
0000H 复位
0003H 外部中断 (后续的8个字节存放程序)
000BH 计时器T0溢出
0013H 外部中断
001BH 计时器T1溢出
0023H 串行口中断
002BH 计时器T2/T2EX(52子系列)
片内256B(80C52位384B)数据存储器地址空间
- 8位的地址总线,寻址空间:

低128B单元
00H~1FH
:32B,第0~3组通用寄存器区- 通过RS0、RS1选择当前工作寄存器。

20H~2FH
:16B,位寻址区(对应位地址00H~7FH
)- 16个字节单元,共包含128位,既可位寻址又可字节寻址。

30H~7FH
:80B,字节寻址区(用户RAM区)只可直接字节寻址
高128B单元
80H~FFH
:特殊功能寄存器SFR区
专用寄存器只可直接寻址,PC不占据RAM单元,不可寻址。


额外128B RAM(针对52系列)
高128B的RAM区和SFR区的地址空间是重叠的。
通过不同的寻址方式来加以区别:
- 即访问高128B RAM区时,选用间接字节寻址方式;
- 访问SFR区,则应选用直接寻址方式。
片外64KB数据存储器地址空间
- 只能用寄存器间接寻址的方法访问:所用的寄存器为DPTR、R1或R0,指令
MOVX
。
用R0、R1寻址:由于R0、R1为8位寄存器,因此最大寻址范围为256B。用DPTR寻址: 由于DPTR为16位寄存器,因此最大寻址范围为64KB。
区分程序存储器(内/外ROM)和数据存储器(内/外RAM)

第三章 指令系统
- 属于CISC(Complex 复杂)指令集,指令长度不一。
- 指令由操作码和操作数组成:
- 推论(?):指令长度是3字节,执行时间必定是2个机器周期。

7种寻址方式
寄存器寻址
- 指在指令中将指定寄存器的内容作为操作数。
- 用符号名称来表示寄存器。例如:
INC R0
- 寻址范围包括:
- 四个寄存器组,32个字节(通过RS0,RS1选择)。
- 部分专用寄存器:ACC、B、DPTR。
直接寻址
- 指在指令中直接给出操作数单元的地址。例如:
MOV A, 3AH
- 寻址范围(限于片内RAM)包括:
- 低128单元(在指令中直接以单元地址形式给出)。
- 特殊功能寄存器(访问特殊功能寄存器的唯一方法)。
虽然特殊功能寄存器可以使用符号标志,但在指令代码中还是按地址进行编码的
立即寻址
- 指在指令中直接给出操作数。
- 为了与直接寻址指令中的直接地址相区别,在立即数前面必需加上前缀"#"。
寄存器间接寻址
- 指在指令中给出的寄存器内容是操作数的地址,从该地址中取出的才是操作数本身。
- 在寄存器的名称前面加前缀"@"。
- 寻址范围包括:
- 片内RAM的低128B单元(8051),只能采用R0或R1为间址寄存器,其形式为
@Ri(i=0, 1)
。 - 片外RAM的64KB单元,使用DPTR作为间址寄存器,其形式为
@DPTR
。 - 片外RAM的低256B单元,可使用DPTR、R0或R1作为间址寄存器。
- 堆栈操作指令(PUSH和POP)以堆栈指针(SP)作间址寄存器的间接寻址方式,访问片内RAM。(第一种的补充)
变址寻址
- 以DPTR或PC作基址寄存器,累加器A作变址寄存器,以两者内容相加。形成的16位程序存储器地址作为操作数地址。例如:
MOVC A, @A+DPTR
。
- 变址寻址指令一共三条,还有两条是:
MOVC A, @A+PC
。JMP @A+DPTR
。
- 变址寻址方式是专门针对程序存储器。
- 变址寻址指令都是一字节指令。
- 变址寻址一般用于查表操作。
相对寻址
- 指在指令中给出的操作数为程序转移的偏移量。把PC的当前值加上指令中给出的地址偏移量rel,构成了程序转移的目的地址。例如:
JNZ rel
。
- 偏移量rel是一个以补码形式表示的带符号的8位二进制数。
位寻址
- 对数据位进行操作。例如:
ANL C, 30H
,还有CLR
、ADDR
。
- 寻址范围包括:
- 内部RAM中的位寻址区,28位。
- 专用寄存器中的可寻址位:11个SFR,83位。
- 寻址位的表示方法:
直接使用位地址 D5H / 位名称 F0 / 单元地址加位 D0H.5 / 专用寄存器符号加位 PSW.5

上述7种寻址方式针对源操作数。目的操作数寻址方式简单,只有4种方式:直接寻址,寄存器寻址,寄存器间接寻址,位寻址。
指令格式
单字节指令

双字节指令

三字节指令

指令总结
数据传送类
指令 | 主要功能 | 影响标志位 | 示例代码 |
MOV | 数据传送 | 无 | MOV A, #data |
MOVC | 程序存储器数据传送 | 无 | MOVC A, @A+DPTR
MOVC A, @A+PC |
MOVX | 外部RAM数据传送 | 无 | MOVX A, @DPTR |
PUSH | 入栈 | 无 | PUSH ACC |
POP | 出栈 | 无 | POP ACC |
XCH | 交换 | 无 | XCH A, R0 |
XCHD | 低半字节交换 | 无 | XCHD A, @R0 |
SWAP | 累加器高低半字节交换 | 无 | SWAP A |
- 一条指令不出现两个Rn寄存器。
MOV DPTR, #data16
是唯一16位数据传输指令。
MOVX
类外部RAM数据传送,只能通过累加器A进行。
MOVC
类查表指令,DPTR基址称为远程查表,PC基址称为近程查表。
- 源操作数为A的寻址属于寄存器寻址;ACC的属于直接寻址,相当于对地址
E0H
寻址。

算数运算类
指令 | 主要功能 | 影响标志位 | 示例代码 |
ADD | 加法 | CY,AC,OV | ADD A, #34H |
ADDC | 带进位加法 | CY,AC,OV | ADDC A, R0 |
SUBB | 带借位减法 | CY,AC,OV | SUBB A, #56H |
INC | 加1 | 无 | INC A |
DEC | 减1(DPTR不允许减1) | 无 | DEC R0 |
DA | 十进制调整 | CY,AC | DA A |
MUL | 乘法 低0位A,高8位B | CY=0,OV | MUL AB |
DIV | 除法 商A,余数B | CY=0,OV | DIV AB |
- 对于带符号数运算,当和的第7位与第6位中有一位进位而另一位不产生进位时,溢出标志OV置1,否则为0。
OV=1
表示两个正数相加,和为负数;或两个负数相加,而和为正数的错误结果。
- 十进制调整指令是紧接着加法指令:
- 累加器低4位大于9或辅助进位标志位
AC=1
,则进行低4位加6修正; - 累加器高4位大于9或进位标志位
CY=1
,则进行高4位加6修正; - 累加器高4位大于等于9,低4位大于9,则进行高低4位均加6修正。
- 乘积小于等于FFH时,
OV=0
;否则OV=1
。
- 除数为0时,
OV=1
;否则OV=0
。


逻辑运算类
指令 | 主要功能 | 影响标志位 | 示例代码 |
ANL | 与运算 | 无 | ANL A, #0FH |
ORL | 或运算 | 无 | ORL A, R0 |
XRL | 异或运算 | 无 | XRL A, #55H |
CLR | 清零 | 根据位 | CLR A |
CPL | 取反 | 根据位 | CPL A |
RL | 循环左移 | 无 | RL A |
RR | 循环右移 | 无 | RR A |
RLC | 带进位循环左移 | CY | RLC A |
RRC | 带进位循环右移 | CY | RRC A |

控制转移类
指令 | 主要功能 | 影响标志位 | 示例代码 |
AJMP | 绝对转移 2K | 无 | AJMP rel |
LJMP | 长转移 64K | 无 | LJMP rel |
SJMP | 短转移 PC127 | 无 | SJMP rel |
JZ | 为零转移 | 无 | JZ rel |
JNZ | 非零转移 | 无 | JNZ rel |
CJNE | 数值不等转移 | CY(减法有无借位) | CJNE A, #data |
DJNZ | 减1非零转移 | 无 | DJNZ Rn, rel |
LCALL | 长调用 64K | 无 | LCALL rel |
ACALL | 绝对调用 2K | 无 | ACALL rel |
RET | 子程序返回 | 无 | RET |
RETI | 中断服务程序返回 | 无 | RETI |
NOP | 空指令 | 无 | NOP |

布尔操作类
指令 | 主要功能 | 影响标志位 | 示例代码 |
MOV | 位传送 | 根据位 | MOV C, bit |
SETB | 置位 | 根据位 | SETB C |
CLR | 清位 | 根据位 | CLR C |
CPL | 取反 | 根据位 | CPL C |
ANL | 位求与 | 根据位 | ANL C, bit |
ORL | 位求或 | 根据位 | ORL C, bit |
JB | 位为1转移 三字节 | 无 | JB bit, rel |
JNB | 位为0转移 三字节 | 无 | JNB P1.0, rel |
JC | CY为1转移 二字节 | 无 | JC rel |
JNC | CY为0转移 二字节 | 无 | JNC rel |
JBC | 位为1转移并清0 三 | 无 | JBC bit, rel |
- 无法对2个可寻址位直接进行传输
MOV bit, bit
。
第四章 程序设计
伪指令
ORG 汇编起始地址伪指令
[<标号>:] ORG <地址16位>
- 通常在由ORG定位时,其地址应当由小到大,不能重叠。
- 有效范围一直到下一条ORG伪指令出现为止。
- 跟在ORG伪指令后面的程序段或数据段是绝对地址还是浮动地址段,依赖于ORG右边的表达式性质。
END 汇编终止伪指令
[<标号>:] END [<表达式>]
EQU 赋值伪指令
<字符名称> EQU <赋值项>
- 定义的标号,在整个源程序中不能更改。
DL 定义标号值伪指令
<字符名称> DL <表达式>
- 可更改已定义的标号值。
DB 定义数据字节伪指令
[<标号>:] DB <8位数表>
DW 定义数据字伪指令
[<标号>:] DW <16位数表>
- 仅
DW
采用大端模式存储 - 小端模式:一个Word中的低位的Byte放在内存中这个Word区域的低地址处。
- 大端模式:一个Word中的高位的Byte放在内存中这个Word区域的低地址处。
DS 定义存储区伪指令
[<标号>:] DS <8位或16位数>
BIT 位定义伪指令
<字符名称> BIT <位地址>
编程方法
运算
多字节加减,移位,BCD码……
数据传送和交换
将R0←→R7,R4←→20H
- 程序从0000H地址开始
- 使用
XCH
和MOV
指令实现数据交换
- 通过A累加器作为中间变量来实现交换
查表


散转

第五章 中断
中断矢量
中断源 | 中断矢量地址 |
外部中断0 | 0003H |
定时器/计数器0 | 000BH |
外部中断1 | 0013H |
定时器/计数器1 | 001BH |
串行口 | 0023H |
定时器/计数器2 (52) | 002BH |
定时控制寄存器 TCON
地址88H,位地址8FH~88H
位地址 | 8F | 8E | 8D | 8C | 8B | 8A | 89 | 88 |
位符号 |
- :外部中断申请触发方式控制位。
- 1为脉冲方式,负跳变有效;0为电平方式,低电平有效
- :T1计数溢出,由硬件置位,响应中断时 由硬件复位。不用中断时用软件清零。
- :T0计数溢出,由硬件置位,响应中断时 由硬件复位。不用中断时用软件清零。
- :时,外部中断1向CPU申请中断请求。
- :时,外部中断0向CPU申请中断请求。
串行口控制寄存器 SCON
地址98H,位地址9FH~98H
位地址 | 9F | 9E | 9D | 9C | 9B | 9A | 99 | 98 |
位符号 |
- :串行口发送中断请求标志位。
- :串行口接受中断请求标志位。
中断响应后用软件对TI、RI标志清零
中断允许控制寄存器 IE
地址A8H,位地址AFH~A8H
位地址 | AF | AE | AD | AC | AB | AA | A9 | A8 |
位符号 | / | / |
- :中断允许总控制位。
- 1为中断总允许,0为中断总禁止
- :外部中断允许控制位。
- 1为外部中断允许,0为外部中断禁止
- :定时/计数中断允许控制位。
- 1为定时/计数中断允许,0为定时/计数中断禁止
- :串行中断允许控制位。
- 1为串行中断允许,0为串行中断禁止
CPU复位后,,即禁止所有中断。
中断优先级控制寄存器 IP
地址B8H,位地址BFH~B8H
位地址 | BF | BE | BD | BC | BB | BA | B9 | B8 |
位符号 | / | / |
- :外中断优先级设定位。
- :定时中断优先级设定位。
- :串行中断优先级设定位。
0为优先级低,1为优先级高
中断优先级控制原则和控制逻辑
- 低优先级中断请求不能打断高优先级的中断服务。高优先级中断请求可以打断低优先级的中断服务。
- 在中断服务程序运行中,不响应同级的其他中断请求。
- 在主程序运行中,同级的多个中断请求同时出现时,响应次序为:
外中断0 → 定时中断0 → 外中断1 → 定时中断1 → 串行口中断
内部有专门的硬件电路实现优先级逻辑控制
中断响应时间
- 中断请求标志位查询 (1个机器周期)
- 执行
LCALL
指令 (2个机器周期)
中断响应最短时间:3个机器周期
- CPU正在执行的是
RETI
指令或访问IP
、IE
指令 (2个机器周期)
- 乘法指令
MUL
或除法指令DIV
(4个机器周期)
中断响应最长时间:8个机器周期
(不考虑CPU正处在同级或高一级的中断服务中)
中断控制程序的设计
中断服务程序的设计
第六章 定时器/计数器
T0/T1相关特殊功能寄存器
TMOD
工作方式控制寄存器;地址89H,不能位寻址;低4位用来定义T0,高4位用来定义T1。

- GATE 门控位
GATE=0
以运行控制位TR0或TR1启动定时器;GATE=1
以外中断请求信号INT0或INT1启动定时器。
- C/T 定时方式或计数方式选择位
C/T=0
定时工作方式;C/T=1
计数工作方式。
- M1、M0 工作方式选择位

TCON
逐位定义的8位寄存器,字节地址为88H,位寻址的地址为88H~8FH
位地址 | 8F | 8E | 8D | 8C | 8B | 8A | 89 | 88 |
位符号 |
- TR0,TR1:定时器控制位,0为停止工作,1为启动定时器/计数器。
T0/T1定时器工作方式
方式0
- 13位定时器/计数器
M1=0
M0=0
- 定时时间:个机器周期。
- 计数寄存器由THx高八位(作计数器)和TLx的低5位构成。TLx的高3位未用。
方式1
- 16位定时器/计数器
M1=0
M0=1
- 定时时间:个机器周期。
- 计数寄存器由THx高八位(作计数器)和TLx的低八位十六位组成。
方式2
- 定时常数自动重装载的8位定时器/计数器
M1=1
M0=0
- TLx作为8位计数寄存器,THx作为8位计数常数寄存器。
- TLx计数溢出后申请中断,同时THx的内容重新装入TLx,继续计数。重新装入不影响THx的内容。
- 适用于作为串行口波特发生器使用。
方式3
M1=1
M0=1
T0
TL0用于8位定时器/计数器,TH0用于8位定时器。
- 8位计数/定时器TL0占用了T0的GATE、INT0、启动/停止控制位TR0、T0引脚(P3.4) 以及计数溢出标志位TF 0和T0的中断矢量(地址000BH);
- TH0所构成的定时器只能作为定时器用,因为此时的外部引脚T0已为定时器/计数器TL0所占用。这时它占用了T1的启动/停止控制位TR1、计数溢出标志位TF1及T1中断矢量(地址为001BH)。
T1
由于此时计数溢出标志位TF1及T1中断矢量(地址为001BH)已被TH0所占用,所以T1仅能作为波特率发生器或其它不用中断的地方。
作串行口波特率发生器时,T1的计数输出直接去串行口,只需设置好工作方式,串行口波特率发生器自动开始运行,如要停止工作,只需向T1送一个设为工作方式3的控制字即可。
举例
要求在P1.0引脚上产生周期为2ms的方波输出。(已知晶体振荡器的频率为fosc=6MHz。用T0作定时器,设为方式0,设定1ms的定时,每隔1ms使P1.0引脚上的电平变反。)
- 计算定时常数
,
取低13位,高8位TCH=F0H,低5位TCL=0CH。
- 设定TMOD

- 编写程序
使用T1的方式1,设定1ms的定时。同样,在P1.0引脚上产生周期为2ms的方波输出。晶体振荡器的频率为fosc=6MHz。
- 计算定时常数
高8位TCH=FEH,低8位TCL=0CH
- 设定TMOD

- 编写程序
欲用80C51产生两个方波,一个周期为200μs,另一个周期为400μs,该80C51同时使用串行口,用定时器/计数器作为波特率发生器。
- 计算定时常数
- TL0产生100μs定时,每隔100μs取反,由P1.0输出方波(T=200μs)
- TCL0=2^8-100μs/1.3021μs=179.2,取TCL0=179=03BH
- TH0产生200μs定时,每隔200μs取反,由P1.1输出方伯
- TCH0=2^8-200μs/1.3021μs=102.4,取TCH0=102=66H
- TH1的波特率
- 波特率2400,定时常数TC2=F6H
需要三个定时器,T0采用方式3,分解成2个8为定时器,T1设置为方式2作波特率发生器用。
设晶振频率,周期
- 设定TMOD

- 编写程序
第七章 串口通信
基本概念
单工方式
信号(不包括联络信号)在信道中只能沿一个方向传送

半双工方式
双方均具有发送和接受信息的能力,信道也具有双向传输性能;
通信的任何一方都不能同时既发送信息又接受信息,即在指定的时刻,只能沿一个方向传送信息。

全双工方式
信号沿两个方向同时传送,任何一方在同一时刻既能发送又能接收信息。

异步串行通信的同步技术
- 通信双方约定一个通信速率;
- 采用相同的数据传输格式;
- 将要传送的数据由一个0电平的“起始位”引导,中间为8位(9位)的数据位,后面有一个高电平的“停止位”——数据帧格式;

- 异步通信的字符帧格式由于添加了“起始位”和“停止位”,占用了传输时间,降低了传输效率,因此仅适用于远距离的数据通信。
波特率
- 定义:串行通讯时每秒钟信号变化次数,单位“BAUD”;
- 比特率:数据传输速率bps(bit per second);
- 在二进制通讯中,比特率等于波特率;
1秒钟传送1位,就是1波特,即1bps(位/秒)
串行状态控制寄存器 SCON

- SM0、SM1:串行口工作方式选择位

- SM2:多机通道控制位
- 用于串行口工作方式2、3
- 若
SM2=1
,当接收到第9数据位RB8为1,则数据有效,并使RI=1
,产生串行口接受中断。当接受到第9数据位RB8为0,则数据无效,不产生中断。 - 若
SM2=0
,则无论接收到的第9数据位RB8为1或为0,数据均有效,并使RI=1
,产生串行口接收中断。 - 用于串行口工作方式0,SM2必须设置为0。
- 用于串行口工作方式1,若
SM2=1
,则停止位(第9数据位RB8)必须为1。
- REN:允许接收位,用软件置位或清零
REN=0
禁止接收REN=1
允许接收
- TB8:发送数据位8,用软件置位或清零
- 在方式2和方式3时,TB8要发送的是第9位数据;
- 方式1下:
TB8=0
表示主机发送的是数据;TB8=1
表示主机发送的是地址。
- RB8:接受数据位8
- 方式1中接收到的是停止位,方式0中不使用这一位。
- TI:发送中断标志
TI=1
表示串行口一帧数据发送结束,TI由软件清零。
- RI:接受中断标志
RI=1
表示串行口一帧数据接受结束,RI由软件清零。
电源控制寄存器 PCON

- SMOD:波特率倍增位
SMOD=1
表示串行口波特率加倍。
编程和应用
方式0的编程和应用
80C51的串行口方式0是同步移位寄存器方式。应用方式0可以扩展并行I/O口。
例1.使用74LS164的并行输出瑞接8只发光二极管,利用它的串入并出功能,把发光二极管从左向右依次点亮,并不断循环之。

方式1的编程和应用
例2. 试编写双机通信程序。甲、乙双机均为串行口方式1并以定时器T1的方式2为波特率发生器,波特率为2400。(使用6MHz的晶振)
- 波特率的计算

- 甲机发送:将以片内RAM的78H及77H的内容为首地址、以76H及75H的内容减1为末地址数据块内容,通过串行口传至乙机。

- 乙机接收:通过RXD引脚接收甲机发来的数据,接收波特率与甲机一样。接收的第一、二字节是数据块的首地址,第三、四字节是数据块的末地址加1,第五字节开始是数据,接收到的数据依次存入数据块首地址开始的存储器中。
例3. 通过串行口发送带奇偶校验位的数据块ASCII码由7位组成,因此其最高位可作为奇偶校验位用。 数据块通过串行口发送和接收,采用8位异步通信,波特率为1200,已知。 从内部RAM单元20H~3FH中取出ASCII码加上奇偶校验位之后发出。设串行口为方式1,定时器/计数器 T1为方式2作为串行口的波特率发生器。
波特率的计算

例4. 通过串行口接收带奇偶校验位的数据块。把接收到的32个字节数据存放到20H~3FH中,波特率仍为1200,若奇校验出错,将进位标志C置“1”。

方式2、3的编程和应用
- 串行工作方式3与方式2的区别只是波特率是可以由用户设置的。方式3的波特率设置与方式1相同。
- 串行工作方式2、3用于多机通信。
- 第9数据位TB8也可以用于校验位。
例5. 利用第8位作为奇偶校验位编写发送中断程序。
第八章-1 系统并行扩展
外部并行扩展相关引脚
- 地址总线 AB
- P2:高8位
- P0:低8位(与数据总线复用)
- 数据总线 DB
- P0(与地址总线复用)
- 控制总线 CB
- 、
相关芯片
74LS373

- :三态控制
- 低电平:允许数据输出,三态门通;
- 高电平:三态门关闭,输出高阻态。
- :数据锁存控制
- 高电平:输出随输入变化;
- 低电平:Q端将被锁存(低电平锁存)。
74LS138

- :选择输入。作为与输出对应的二进制编码输入;
- :使能输入,作为片选控制输入;
- :译码器输出,低电平有效。
27系列EPROM


62系列RAM

- 6264:8k byte / 62128: 16k byte / 62256:32k byte
74LS244


74LS377


程序、数据扩展特点
- 程序、数据都通过P2、P0口扩展;
- 程序扩展用
PSEN
引脚;
- 数据扩展用
/WR
和/RD
引脚;
- 程序空间和数据空间完全独立(符合哈佛结构的特点),但不是真正的哈佛结构。
扩展连接图
第八章-2 系统串行扩展
SPI总线扩展系统

- SCK:同步移位脉冲;
- MOSI:主机输出,从机输入;
- MISO:主机输入,从机输出;
- /CS:从机片选线;
- 典型芯片:93C46。
I2C总线

- I2C总线采用两线制:数据线SDA、时钟线SCL;
- I2C总线为同步总线,数据的传送与时钟信号完全同步;
- I2C总线采用主从方式,由主控器寻址从器件,启动总线,产生时钟脉冲;
- 所有与SDA、SCL总线相连的器件(单片机和外围器件)都应当具备I2C总线接口;
- I2C总线接口器件在出厂时按照芯片的型号都具有唯一的8位地址(4位内部硬件地址、3位引脚定义的外部地址和1位方向地址)。
- 典型芯片:24C0X,DS1307。
I2C总线时序

根据I2C时序Start和Stop定义可知:
在传输数据时,当SCL高电平,SDA不能变化
因SCL由主机控制,所以:
- 主机在SCL低电平时输出数据至SDA;
- 主机在SCL高电平时读取SDA数据。
扩展连接图
第九章 ARM基础
Cortex-M3/M4 处理器数据宽度
- ARM Cortex-M为32位RISC处理器
- 32位寄存器;
- 32位内部数据;
- 32位总线接口。
- ARM Cortex-M采用32位寻址,地址空间4GB(以字节为基础)。
- 除了32位数据,还可以处理:
- 字节/Byte(8bits);
- 半字/Halfword(16bits=2bytes);
- 字/Word(32bits=4bytes);
- 双字/Doubleword(64bits=8bytes)。
Cortex-M3/M4 数据存贮顺序



每个字节对应一个地址:
- 小端模式 (Little endian):(一般常用)一个Word中的最低Byte存贮在 bit0 to bit7
- 大端模式 (Big endian):一个Word中的最低Byte存贮在 bit24 to bit31
- Cortex-M4采用little endian小端模式
数据地址的对齐
存贮器系统32位(4字节),地址按字节定义
访问方式包括字(32位),半字(16位),字节(8位)
- 对齐传输方式
- 字变量的地址必须是4的整数倍
- 半字变量的地址必须是2的整数倍
- 非对齐传输方式
- 对字和半字的地址无限制
Cortex-M3/M4 指令流水线
- Cortex支持Thumb2
- 同时支持ARM指令(32位)和Thumb指令(16位)
- 兼顾了指令密度和指令速度
- 具有三级流水线
- 取指→译码→执行


- 某些指令执行多个周期,此情况下流水线停止
- 跳转到分支后,流水线清空
- 可一次读取两条指令(16-bit指令)
通用寄存器
- :低寄存器
- 一些16位指令只能访问低寄存器。
- :高寄存器
- 可用于32位和16位指令。
- :栈指针(SP)
- 用于
PUSH
和POP
操作,物理上实际存在两个栈指针:主栈指针MSP和进程栈指针PSP; - 不使用操作系统时仅用MSP。
- :链接寄存器(LR)
- 用于函数或子程序调用时返回地址的保存。当执行了函数或子程序调用时,LR的数值会自动更新。
- :程序计数器(PC)(可访问,是与51的明显区别之一)
- 可读可写,读操作返回当前指令地址加4;写PC引起跳转操作。
xPSR 程序状态寄存器

APSR中的5个标志位:
- N:负数标志(Negative);
- Z:零结果标志(Zero);
- C:进位/借位标志(Carry);
- V:溢出标志(oVerflow);
- S:饱和标志(Saturation),它不作为条件转移的依据。
存贮器
可访问多达4GB(的存贮器空间;存贮器保护单元MPU,定义各存贮区域的访问权限,防止越界访问
根据典型用法,分为:
- 程序代码访问区(如CODE区);
- 数据访问区(如RAM区);
- 外设;
- 处理器的内部控制和调试部件。

堆栈区
Cortex-M4使用的是“向下生长的满栈”模型。堆栈指针SP指向最后一个被压入堆栈的32位数值。在下一次压栈时,SP先自减4,再存入新的数值。
对32位操作,对齐到4字节边界,SP的最低两位总是为0。


嵌套向量中断控制器(NVIC)
- NVIC 处理异常和中断配置、优先级以及中断屏蔽,位于存贮器映像的系统控制空间(SCS)。
- 中断等一些异常具有可编程的优先级。
- 中断可嵌套,即抢占式,高优先级可打断低优先级中断过程。
- 向量化的异常/中断入口。
向量表

- 该向量表实际上是一个32位整数数组,每个元素都是一个32位数,对应异常服务例程的入口地址。
- 异常服务例程的地址最低位必须为1,以指示Thumb状态。
复位流程

1. 处理器复位:多手段触发复位信号,处理器停止当前所有操作,进入复位状态;
- 读取MSP初值:从
0x00000000
地址处读取32位数据,加载到主堆栈指针寄存器MSP;
- 读取复位向量:从
0x00000004
地址处读取32位复位向量,即复位服务程序入口地址;
- 跳转并执行启动代码:跳转到复位服务程序入口,开始取指;
- ……
指令集
- 32位或16位的RISC指令集
- 指令丰富,功能强大
指令后缀
- ~S:要求更新APSR中的相关标志。
- ~EQ:Equal
- ~NE:NotEqual
- ~LT:LessThan
- ~GT:GreatThan
- ……
处理器内部数据转移指令
指令 | 功能 | 示例 |
MOV | 在两个寄存器/寄存器与特殊寄存器间传输数据 | MOV Rn, Rm |
MOV | 把一个立即数加载到寄存器 | MOV Rn, #data |
MOVW(Move Wide) | 修改低16位,清零高16位 | MOVW Rn, #data32 |
MOVT(Move Top) | 修改高16位,不影响低16位 | MOVT Rn, #data32 |
MVN | 寄存器内容取2进制补码传输 | MVN Rn, Rm |
- 在两个寄存器间传送数据(32允许✅,51禁止❌);
- 可在指令后加入后缀
~S
,在数据转移的同时更新ASPR标志;
MOVW
和MOVT
的配合使用,可以方便修改寄存器的内容(32位)。
存贮器访问指令
数据类型 | 位角度 | LOAD | STORE |
unsigned_int_8 | Byte | LDRB | STRB |
signed_int_8 | Signed Byte | LDRSB | STRSB |
unsigned_int_16 | Halfword | LDRH | STRH |
signed_int_16 | Signed Halfword | LDRSH | STRSH |
int_32 | Word | LDR | STR |
int_64 | Double Word | LDRD | STRD |
int_n*32 | Multiple Word | LDRM | STRM |
类型 | 功能 | 示例 |
立即数偏移(前序) | 从地址Rn+offset处读取低位内容送到Rd | LDR Rd, [Rn, #offset] |
ㅤ | 往地址Rn+offset处存储Rd中的低位内容 | STR Rd, [Rn, #offset] |
寄存器偏移(前序) | 从存贮器位置Rn+(Rm<<n)处读取低位内容送到Rd | LDR Rd, [Rn, Rm{, LSL, #offfset}] |
ㅤ | 往存贮器位置Rn+(Rm<<n)处存储Rd中的低位内容 | STR Rd, [Rn, Rm{, LSL, #offfset}] |
立即数偏移(后序) | 读存储器Rn处内容至Rd并更新Rn+offset | LDR Rd, [Rn], #offset |
ㅤ | 读存储器Rn处内容至Rd并更新Rn+offset | STR Rd, [Rn], #offset |
多重存贮器访问 | 从Rd指定的存贮器地址读取多个字到寄存器列表,地址在每次读取后加4(Increase After) | LDMIA Rd!, {寄存器列表} |
ㅤ | 依次将寄存器列表的值写入Rd指定的地址,地址在每次读取后加4 | STMIA Rd!, {寄存器列表} |
ㅤ | 从Rd指定的存贮器地址读取多个字到寄存器列表,地址在每次读取前减4(Decrease Before) | LDMDB Rd!, {寄存器列表} |
ㅤ | 依次将寄存器列表的值写入Rd指定的地址,地址在每次读取前减4 | STMDB Rd!, {寄存器列表} |
- 立即数偏移(前序):以一个寄存器作为存贮器的基准地址(指针),与一个立即数相加,其和作为访问存贮器的地址。(偏移量后可加后缀!表示指令执行完成后更新存放地址的寄存器)
- 寄存器偏移(前序):以一个寄存器作为存贮器的基准地址(指针),与另一个从索引寄存器值相加,其和作为访问存贮器的地址。从索引寄存器值在相加前,可左移位。
- 立即数偏移(后序):该方式也有一个立即数偏移值,但是在存贮器访问期间不用偏移值,仅在数据结束后更新地址寄存器(指针)。指令无需后缀!。
跳转指令
类型 | 功能 | 示例 |
跳转 | 跳转到 label ,范围2KB | B label |
ㅤ | 长跳转,跳转到[R1]中的地址,最低位应为1,保持Thumb状态 | BX R1 |
条件跳转 | 基于APSR的当前条件值执行 | B<cond> label |
条件执行
IT <cond>
: IF-THEN
ITE <cond>
: IF-THEN-ELSE
ITTEE <cond>
: IF-THEN*2-ELSE*2(最多)
位段操作

- 位段区(Bit-band Region):操作单字节的实际内存区域。SRAM和外设区中各有一块大小1MB的位段区。
- 位段别名区(Bit-band Alias):32MB的内存区域。对这块区域中某个字地址的访问,会被硬件自动映射为对位段区中对应字节的对应位的访问。
- 位操作是一种“原子操作(不可中断的一个或一系列操作)”,不会被其他指令打断。
第十章 ARM编程
结构体变量的地址及对应关系
共9个16位GPIO口:GPIOA~GPIOI

注意:结构体成员在内存中的地址按顺序排列!
用结构体定义外设的优点:
- 相关的设置参数放置在一个结构体中;
- 对外设操作时,将相关寄存器地址映射到结构体的成员;
- 结构体变量地址对应该结构体的首地址。
通用IO口

- MODER0[1:0]~MODER15[1:0]
- 端口x配置位,软件修改位值,配置I/O方向模式:
00
输入(复位状态);01
通用输出模式;10
复用功能模式;11
模拟模式。

- BR0~BR15(BSRH)
- 端口x复位位
0
不会对相应ODRx
位执行操作;1
对相应ODRx
位进行复位。
- BS0~BS15(BSRL)
- 端口x置位位
0
不会对相应ODRx
位执行操作;1
对相应ODRx
位进行置位。
中断系统
- STM32F407包含10个内核中断和82个可屏蔽中断通道。
中断/异常响应过程
- 压栈:把8个寄存器值压入栈(未使用浮点功能);
- 取向量:从向量表中找出对应的服务程序入口地址;
- 中断处理:选择堆栈指针MSP/PSP,更新堆栈指针SP,更新连接寄存器LR,更新程序计数器PC;
- 出栈:把8个寄存器值出栈。
NVIC中断优先级
优先级包括抢占优先级和响应优先级:
- 共占4bit,哪几个bit表示抢占优先级或响应优先级可设置;
- 编号越小,优先级越高;
- 抢占优先级高的中断可以打断优先级低的中断;
- 抢占优先级相同时,两个中断同时到达,则先处理响应优先级高的中断。
定时器
- 定时器1和8:高级控制定时器,16位自动重装载;
- 定时器2和5:通用定时器,32位自动重装载;
- 定时器3和4:通用定时器,16位自动重装载;
- 定时器6和7:基本定时器,16位自动重装载;
- 定时器9-14:通用定时器,16位自动重装载
定时器相互完全独立,不共享任何资源;功能强大,可用于定时、计数、PWM控制等;
PWM模式占空比设置
- 预分频设置(Prescaler):
TIM1->PSC = P-1;
- 定时器周期和计数方式设置(自动重装载 Auto-Reload Register):
TIM1->ARR = N-1;
- PWM占空比设置(捕获/比较1 Capture/Compare Register 1):
TIM1—>CCR1 = PWM;
直接内存访问DMA
- 无需CPU直接控制传输,通过硬件为RAM与I/O设备开辟直接传输数据的通道,提高系统的效率。
- STM32F4具有2个DMA控制器(DMA1和DMA2),共16个数据流(每个控制器8路),每个数据流有8个通道,大部分外设均可通过DMA控制。