Posted on  Updated on 

微机原理与接口技术

前言

距离第一次接触51单片机已有两年之久,当时跟着江科大的视频学了两个星期,完成了一些基本操作,随后就不怎么接触了,而关于微机的底层和通讯在之后的时间里,一直都是零散的学习,刚好借助此次课程的机会,记录一下自己的微机的学习。只记录重要知识点,配合教材使用。

课程概述

教材使用王晓萍的微机原理与接口技术
教材分为3个部分进行教学

  • 微控制器原理
  • 微机接口技术
  • 微机系统设计

微机概述

微机两大分支

  • 通用计算机(PC)
  • 嵌入式计算机(MCU)

硬件结构

知识点讲解

基本结构

  • 输入输出设备
  • 存储器
  • 控制器与运算器

存储结构分类

  • 存算一体(哈佛结构)
  • 存算分开(冯诺依曼结构)

0851硬件资源

  • CPU
  • RAM(128B数据存储器)
  • ROM(4K程序存储器)
  • 4个8位IO口
  • 2个16位定时器/计数器
  • 中断系统(5个中断源,2个优先级)
  • 1个全双工串行口
  • SFR(21个特殊功能寄存器)

0851功能特点记忆点

  • 内部RAM,256B(2^8),地址为00H~FFH
  • 外部RAM,最大64KB(2^16),地址0000H~FFFFH
  • 内部ROM,4~64K,以8K为例(2^13)
  • 外部ROM,最大64K,地址0000H~FFFFH
  • 指令系统,复杂指令,CISC,111条。

0851功能引脚

  • RST 需要两个机器周期的高电平
  • EA 内部外部ROM片选,EA=0,只内,EA=1,在ROM大于FFH时转外部
  • ALE 低八位地址锁存允许信号输出端,有效时输出高脉冲
  • PSEN 与外部ROM的OE相连,外部ROM选通输出端

0851引脚功能示意图

0851拓展外部ROM示意图

指令系统

  • PC(程序计数器,16位)
  • IR(指令寄存器,8位,存放当前指令的操作码)
  • ID(指令译码器,)

指令执行过程

  • 取指令
  • 分析指令
  • 执行指令

单片机的周期

  • 时钟周期 $1/f_{osc}$
  • 状态周期 $S = 2/f_{osc}$
  • 机器周期 $T_{M} = 12/f_{osc}$
  • 指令周期 执行一条指令所需要的时间。(单周期,双周期,四周期)

单片机的复位

复位是微控制器的初始化操作

  • 上电复位(冷启动)
  • 按键复位(热启动)

复位后,表现为SFR的复位状态。

  • PC的值为0000H
  • 堆栈指针SP的值为07H
  • 四个IO锁存器输出为FFH,为准双向口模式的输入模式
  • 其舍所有的SFR的有效值均为零。

注意:由于RAM数据在掉电后丢失,上电复位RAM数据为随机数,按键复位,内部RAM数据没有影响

文稿复位:

复位是微控制器的初始化操作。
单片机的复位有两种,上电复位(冷启动)和按键复位(热启动)。
下面是上电和按键复位的电路图。
上电复位时,需要要求高电平维持十毫秒以上,下面是上电复位RTS引脚的波形
按键复位时,在按下按键后,电容放电,然后电源对电容进行充电,充电会形成一个类似于上电复位的波形,需要要求超过24个时钟周期的高电平,也就是两个机器周期的高电平,即可完成复位。
复位后,表现为SFR(特殊功能寄存器)的复位状态。

  • PC的值为0000H
  • 堆栈指针SP的值为07H
  • 四个IO锁存器输出为FFH,为准双向口模式的输入模式
  • 其舍所有的SFR的有效值均为零。

注意:由于RAM数据在掉电后丢失,上电复位RAM数据为随机数,按键复位,内部RAM数据没有影响

微控制器的工作模式

微控制器的工作方式文稿:
微控制器共有三种工作方式,低功耗工作方式,程序执行方式和复位方式。其中,低功耗工作方式(省电方式)又分为休闲方式和掉电方式。
程序执行方式是微控制器的基本工作方式。
复位方式,复位是微控制器的初始化操作,复位后,SFR内容恢复初始值,CPU重新开始运行
低功耗方式又分为休闲方式和掉电方式。
低功耗方式有电源控制寄存器PCON的IDL位和PD位控制。
默认该两位为零,当pd为一的时候,进入掉电方式, Idl为一的时候,进入休闲方式,两者都为一的时候,进入掉电方式。

休闲方式(ID)时,内部时钟电路正常工作,CPU停止工作,中断,串行口定时器继续工作。可通过复位或者中断终止休闲方式。在休闲期间,中端触发后,IDL请0,退出休闲方式
掉电方式(PD)时,内部时钟不工作,所有功能单元停止工作。只能通过复位退出。

指令

111条指令

寻址方式

  • 立即寻址(MOV A, #68H)
  • 直接寻址(MOV A,68H ;将68H单元格的数据传送到A)
  • 寄存器寻址(MOV A,Rn)
  • 寄存器间接寻址(MOV A,@Rn)
  • 变址寻址
  • 相对寻址
  • 位寻址

伪指令

用于帮助开发者更好地管理程序的结构和数据。这些指令本身并不会直接转换为机器代码,而是为汇编器提供信息或执行某些特定功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
1. ORG (起始地址)
用于指定代码或数据的起始地址。
例如:

asm
复制代码
ORG 0000H ; 从地址 0x0000 开始存储程序

2. DB (定义字节数据)
用于定义字节数据,常用于存储常量或初始化数据。
例如:

asm
复制代码
DATA1: DB 0AH ; 定义一个常量 0x0A


3. DW (定义字数据)
用于定义双字节数据(16 位)。
例如:

asm
复制代码
DATA2: DW 1234H ; 定义一个 16 位的常量 0x1234
4. EQU (定义符号常量)
为某个值分配一个符号名称,类似于 C 中的宏定义。
例如:

asm
复制代码
MYCONST EQU 05H ; 定义一个常量 MYCONST,其值为 0x05
MOV A, MYCONST ; 将 0x05 加载到 A 寄存器
5. END (程序结束)
用于指示汇编器程序的结束。
例如:

asm
复制代码
END ; 汇编结束
6. BIT (位地址赋值)
位寻址区在 8051 的 RAM 中占用地址范围 20H ~ 2FH,共 16 字节

name BIT address
name:符号名称,用于标识位变量。
address:位地址(范围是 00H 到 7FH)

7. DS (定义存储空间)
分配一段未初始化的内存,用于数据存储。
例如:

asm
复制代码
BUFFER: DS 10 ; 分配 10 个字节的存储空间

寻址方式

  • 立即数寻址:
    操作数是指令中直接给出的常数值。
    例:MOV A, #10(将 10 直接送入 A 寄存器)。

  • 直接寻址:
    操作数是内存地址,通过该地址访问数据。
    例:MOV A, 30H(将 0x30 地址的数据送入 A 寄存器)。

  • 寄存器寻址:
    操作数是寄存器的内容。
    例:MOV A, R0(将 R0 寄存器的值送入 A 寄存器)。

  • 寄存器间接寻址:
    操作数的地址由寄存器指向。
    例:MOV A, @R0(R0 寄存器的内容作为地址,从该地址读取数据送入 A 寄存器)。

8051 单片机中有 4 组工作寄存器组,每组包含 8 个寄存器 (R0 至 R7)。因此,8051 单片机总共有 32 个工作寄存器。

  • 变址寻址:
    地址由基地址和偏移量(即变址)计算得到。
    例:MOV A, @R0+DPTR(DPTR 和 R0 的内容相加作为地址,从该地址读取数据)。

  • 相对寻址:
    地址是相对于当前指令地址的偏移量。
    例:SJMP LABEL(跳转到当前地址偏移 LABEL 的位置)。

  • 位寻址:
    操作数是内存中单个位,直接操作某一位。
    例:SETB 30H.0(将 0x30 地址的第 0 位设为 1)。

寻址方式和寻址空间

中断

通信

传输方式分类

  • 串行通信

    数据传输速度快。
    需要更多的传输线。
    适合短距离通信。
    距离增长时,位数增多时,会提高硬件成本,降低通信成功率

  • 并行通信

    线路简单,成本低
    适合长距离通信
    传输速度慢

按时钟线分类

  • 异步通信
  • 同步通信

按传送方向分类

  • 单工
  • 半双工
  • 双工

异步串行通信

例:UART、RS-232、RS-485

帧格式

  • 起始位

  • 数据位
    低位在前,高位在后

  • 奇偶校验位

    这是一个用于错误检测的位,可以是无校验(None)、奇校验(Odd)、偶校验(Even)、标记校验(Mark)或空位校验(Space)。

    确保数据帧与校验位的1个数为奇数为奇校验,为偶数,偶校验

  • 停止位

常用的帧格式为:1位起始位+8位数据位(一个字节)+无校验位+1位停止位 即一帧10个bit

波特率

对于串口通信,波特率代表每秒传输的bit的数量。
如常用的9600波特率代表了一秒钟可以传输9600个bit的信息。即信号宽度为0.104ms

校验方式

  • 字节的奇偶校验
  • 数据块的累加和校验
  • 数据块的循环冗余校验CRC
    把数据块看成二进制数,用特定数除以它,取余数

UART

键盘

工作方式

  • 编程扫描方式
  • 定时扫描方式
  • 中断扫描方式

独立键盘

矩阵式键盘

  • 行扫描式
  • 线路反转法

代码分析

点亮LED

1
2
3
4
5
6
7
8
9
10
11
12
; 点亮 LED 的汇编程序
; 假设 LED 连接到 P1.0,低电平点亮

ORG 0000H ; 程序起始地址为 0
START:
MOV P1, #0FEH ; 初始化 P1,P1.0 输出低电平,其他引脚输出高电平
; P1 = 1111 1110 (FEH),即 P1.0 = 0 (点亮 LED)
HERE:
SJMP HERE ; 无限循环,保持 LED 点亮

END ; 程序结束

延时

单循环

注意:当X为0时,实际是256,R0是8位寄存器(同R1,R2,R3);0<=R0<=256

双重循环

亮灯,一闪一闪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	ORG 10H            ; 程序起始地址
MOV P1, #00H ; 将 P1 端口的所有位设置为 0

START: ; 主程序开始

SETB P1.0 ; 置P1.0高电平,LED点亮
LCALL DELAY ; 调用延时程序
CLR P1.0 ; 置P1.0低电平,LED熄灭
LCALL DELAY ; 调用延时程序
AJMP START ; 跳转到START,实现循环

DELAY: ; 延时子程序
MOV R7, #250 ; 外层循环计数器初始化,R7 = 250
D1: MOV R6, #250 ; 内层循环计数器初始化,R6 = 250
D2: DJNZ R6, D2 ; 内层循环:R6倒数,直到为0
DJNZ R7, D1 ; 外层循环:R7倒数,直到为0
RET ; 延时完成,返回主程序

END ; 程序结束


DJNZ 指令:递减寄存器 R7 的值,如果不为0,跳转到标号 D1
RET 返回调用 LCALL DELAY 的位置
AJMP 无条件跳转 短跳转指令,适用于小程序。

按键控制LED亮灭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ORG 0000H              ; 程序起始地址

CLR P1.0 ; 清除 P1.0,设置 P1.0 为低电平(LED熄灭)

START: ; 主程序开始
SETB P0.0 ; 设置 P0.0 为高电平(使能触发条件)
JB P0.0, LIG ; 如果 P0.0 为高电平(1),跳转到 LIG 标签处(LED熄灭)
SETB P1.0 ; 否则设置 P1.0 为高电平(LED点亮)
SJMP START ; 跳回 START,形成循环

LIG: ; LIG 标签,LED 熄灭部分
CLR P1.0 ; 清除 P1.0,设置 P1.0 为低电平(LED熄灭)
SJMP START ; 跳回 START,形成循环

END ; 程序结束

;JB P0.0, LIG:检查 P0.0 引脚的电平。如果 P0.0 为高电平(1),则跳转到 LIG 标签,否则继续执行下一条指令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

ORG 0000H ; 程序起始地址

CLR P1.0 ; 清除 P1.0,设置 P1.0 为低电平(LED熄灭)
CLR P1.1 ; 清除 P1.1,设置 P1.1 为低电平(LED熄灭)
CLR P1.2 ; 清除 P1.2,设置 P1.2 为低电平(LED熄灭)

START: ; 主程序开始
SETB P0.0 ; 设置 P0.0 为高电平(开关启用)
SETB P0.1 ; 设置 P0.1 为高电平(开关启用)
SETB P0.2 ; 设置 P0.2 为高电平(开关启用)

; 控制 P1.0 LED
JB P0.0, LIGO ; 如果 P0.0 为高电平(1),跳转到 LIGO(LED熄灭)
SETB P1.0 ; 否则设置 P1.0 为高电平(LED亮)
SJMP START ; 跳回 START,形成循环
LIGO:
CLR P1.0 ; 清除 P1.0,设置 P1.0 为低电平(LED熄灭)

next1: ; 检查 P0.1 控制 P1.1 LED
JB P0.1, LIG1 ; 如果 P0.1 为高电平(1),跳转到 LIG1(LED熄灭)
SETB P1.1 ; 否则设置 P1.1 为高电平(LED亮)
SJMP next2 ; 跳到 next2,继续下一步
LIG1:
CLR P1.1 ; 清除 P1.1,设置 P1.1 为低电平(LED熄灭)

next2: ; 检查 P0.2 控制 P1.2 LED
JB P0.2, LIG2 ; 如果 P0.2 为高电平(1),跳转到 LIG2(LED熄灭)
SETB P1.2 ; 否则设置 P1.2 为高电平(LED亮)
SJMP next3 ; 跳到 next3,继续下一步
LIG2:
CLR P1.2 ; 清除 P1.2,设置 P1.2 为低电平(LED熄灭)

next3: ; 检查 P0.3 控制 P1.3 LED
JB P0.3, LIG3 ; 如果 P0.3 为高电平(1),跳转到 LIG3(LED熄灭)
SETB P1.3 ; 否则设置 P1.3 为高电平(LED亮)
SJMP next4 ; 跳到 next4,继续下一步

next4: ; 检查 P0.4 控制 P1.4 LED
JB P0.4, LIG4 ; 如果 P0.4 为高电平(1),跳转到 LIG4(LED熄灭)
SETB P1.4 ; 否则设置 P1.4 为高电平(LED亮)
SJMP START ; 跳回 START,形成循环

LIG3:
CLR P1.3 ; 清除 P1.3,设置 P1.3 为低电平(LED熄灭)

LIG4:
CLR P1.4 ; 清除 P1.4,设置 P1.4 为低电平(LED熄灭)

SJMP START ; 跳回 START,形成循环

END ; 程序结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
;1. 仔细体会本段仿真效果,再删除延时脚本程序编译之后,你看看会有什么效果?
;2. 你将会深刻理解LED产生闪烁的原因,分析为什么会闪烁?
;3. 延时脚本程序的延时长短效果比较。
;4. 本例为软件防抖,硬件防抖可参见李群芳编的《单片机原理、接口及应用--嵌入式系统技术基础》中的P87页。

ORG 0000H
ABC: MOV P0, #0FFH ;高四位的LED全灭,低四位开关输入线送1
MOV A, P0 ;读P0口引脚开关状态并送A
SWAP A ;低四位开关状态转换到高四位
ANL A, #0F0H ;保留高四位
MOV P0, A ;从P0口输出
LCALL DELAY
SJMP ABC ;循环

DELAY:
MOV R6, #20 ;原始代码中R6,R7的值若太小,则会有余辉鬼辉效果
DL2: MOV R7, #7DH
DL1: NOP
NOP
DJNZ R7, DL1
DJNZ R6, DL2
RET
END