跳转至

80C51

7830 个字 218 行代码 预计阅读时间 33 分钟

学习路线

上课不要听,花两到三次课或者整块的空闲时间把这一套课程听完。讲的简洁易懂特别好。 看完视频之后直接把作业做掉,实验做了,可以结合实验对所学知识有一个更深的了解。 期末的时候再结合课件做补充。

重点理解

  • C51 资源分布:CPU 里边有哪些东西,代码放在哪里?变量放在哪里?怎么取出来
  • PC 指针及其作用
  • 存储器的分布,各个部分都是放什么的。SFR 中的各个寄存器可以控制单片机的各种资源
  • 最后了解汇编

思维导图

简介

  • 什么是单片机

一台能够工作的计算机要有这样几个部份构成:CPU(进行运算、控制、RAM(数据存储、ROM(程序存储、输入 / 输出设备(例如:串行口、并行输出口等)

而在单片机中 , 这些部份全部被做到一块集成电路芯片中了 , 所以就称为单片机(单芯片)

image-20240620231200675

  • 8 CPU
  • 4K ROM 存放程序
  • 128B RAM 存放数据
  • IO 接口
  • 2 16 位定时计数器
  • 1 个全双工可编程串行口

数据总线、地址总线、控制总线

结构

单片机应用原理篇之 80C51 CPU_ 哔哩哔哩 _bilibili

引脚

image-20240620231616616

缺口左侧是 1 号口

单片机的 40 个引脚大致可分为 4 类:

电源、时钟、控制和 I/O 引脚。

51单片机引脚图

电源引脚Vcc 40 :5VVss 20 GND

控制引脚RST 9 高电平复位;ALE

80C51 共有 4 8 位并行 I/O 端口:P0,P1,P2,P3 , 32 个引脚。

CPU

CPU 的位数8

CPU 的作用:取指令,译码,执行

CPU 的构成

image-20240620232832045

  • 运算器

image-20240620232944582

寄存器 B:乘除法

累加器 A:最繁忙的寄存器

PSW 程序状态字寄存器

  • 控制器

image-20240620233446761

  • 程序计数器 PC16 位,24K,控制读取的代码;一开始指向 0000H,跳转到 30H 开始执行
;30H开始放代码
MOV A,20H
MOV B,20H
MOV C,20H
  • 数据指针寄存器 DPTR(data pointer);16 位,可寻址范围 64KB; 指向外部 ROM RAM 的地址指针

存储器构造

看总线区分哈佛和冯诺依曼:数据总线和地址总线

  • 哈佛结构 RAM ROM 是分开的;独立结构;可以同时获得数据和代码

image-20240620235824661

  • 冯诺依曼结构 RAM ROM 是相邻的,统一编址(分时)

image-20240620235816288

51 单片机是改进哈佛结构,分时复用,一套数据地址总线,通过指令的方式区分

image-20240621000834024

4 个物理存储空间,实际是 3 个逻辑存储空间; 地址总线是16位的,最大不可以超过64K

image-20240621002809377

程序存储器 ROM |READ ONLY MEMORY

89C51 中的 ROM 是一种电可擦除的 ROM, 称为 FLASH ROM

存放程序、表格常数;

在运行过程中只读不可写,掉电不丢失数据。

EA 引脚,EA=1 方案 1EA=0 方案 2 - 方案1:4K以内地址在片内ROM,大于4K的在片外ROM - 方案2:片内ROM禁用,全部存放在片外

0023H RI/TI 中断跳转
001BH T1 中断跳转
0013H INT1 中断跳转
000BH T0 跳转
0003H INT0 中断跳转
0000H 主程序跳转指令 ( 只有三个 Byte)

数据存储器 RAM |READ RANDOM MEMORY

所谓随机存取存储器 , 即随时能改写 , 也能读出里面的数据 , 它类似于我们的黑板 , 我能随时写东西上去 , 也能用黑板擦擦掉重写。

空间分配

128 字节 real RAM 00H-7FH

  • 1 工作寄存器区:4x8bytes 每个区域都是 R0-R7; 只能选一组

  • 2 可位寻址区:对 00H-7FH 进行位编址,通过指令区分

  • 3 用户 RAM

1 3 只能字节寻址,只有 2 可以位寻址

image-20240621002147037

image-20240621001638481

128 字节 SFR 特殊功能寄存器 80H-FFH

SFR寄存器

0 8 结尾的可以容许位寻址

复位

复位——使单片机回复原始默认状态的操作

image-20240621190646898

复位 RES

  • A = 0
  • PSW = 0
  • PC = 0
  • DPTR = 0
  • SP = 07H

RST(9pin:出现 2 个机器时间的高电平状态

I/O

先易后难,所以 P1-P3-P0-P2

可能的作用

  • 外部设备连接:存储器扩展
    • 并行 IO 输入
    • 串行通信

80C51 共有 4 8 位并行 I/O 端口:P0,P1,P2,P3 , 32 个引脚。

  1. P0 口既可以作为普通 I/O 口,又可以作为外部扩展时的数据总线和地址总线的低 8 位,分时复用;作为普通 I/O 口时,外部要接上拉电阻。
  2. P1 口可以作为普通 I/O 口使用,内部带上拉电阻。
  3. P2 口可以作为普通 I/O 口使用,又可作为外部扩展时地址总线的高 8 位,作为普通 I/O 时,内部带上拉电阻。
  4. P3 口作为普通 I/O 时,内部带上拉电阻。第二功能 , 用于特殊信号输入输出和控制信号(属控制总线)

P1

具有通用 IO 口的方式,可实现输出,读引脚、读锁存器三种功能

image-20240621192857719

外部电平跟随内部总线上的电平

image-20240621193410016

  • 读取外部操作的时候,读引脚(最下边)高电平,可以读入
  • 读内部的锁存器:如对总线进行取反等操作的时候,

注意: - 内部总线先写1,使得场效应管先处于截止的状态,不然可能中间有回路导通,一直读取的是0 - 最高带4个LSTTL - 拉电流与灌电流区别

P3

  • 通用 IO 口:可实现输出、读引脚、读锁存器三种功能
  • 准双向通用口,作为通用输入口之前应显示 P3.n 1,通用输出口应该使第二输出端置 1
  • 普通 IO 第二输出为 1,完全由锁存器 Q 端决定,即由内部总线决定

image-20240619111616506

输入功能的时候,内部引脚也要置 1

image-20240621195519916

P0,P2

中断

流程

中断系统是为使 CPU 具有对外界紧急事件的实时处理能力而设置的, 当中央处理机 CPU 正在处理某件事的时候外界发生了紧急事件请求 , 要求 CPU 暂停当前的工作 , 转而去处理这个紧急事件 , 处理完以后 , 再回到原来被中断的地方 , 继续原来的工作 , 这样的过程称为中断。

CPU 执行程序过程中 , 在每个机器周期的S5P2期间 , 中断系统对各个中断源进行采样。

可能会有一些滞后

当前指令执行完之后 , 双周期
正在执行的指令为RET、RETI或任何访问IE或IP寄存器的指令。即只有在这些指令后面至少再执行一条指令时才能接受中断请求。
执行一条硬件LCALL指令

image-20240327115545079image-20240508113216330

RETI中断函数返回 , 清除中断状态的标志位 , 否则如果来了一个小于等于当前中断优先级的中断事件不会响应

具体流程可以看这个视频,很清楚。

核心逻辑 通过程序代码和中断机制控制程序计数器PC,让PC来回在不同代码段之间切换。 在0000H-0030H中有很多个中断地址,每个有8个字节,保存中断函数的位置地址

环节 作用
①中断源 申请中断的来源
②中断申请 中断源发出信号提出申请
③中断控制 中断系统判断是否要响应申请
④保护现场 安排好当前的工作)b=a,a=c, 保护当前 PC 指针的位置
⑤中断服务 响应中断源的申请
⑥恢复现场 完事后 , 回去……
⑦中断返回 继续做打断前的工作

中断响应与子程序调用的区别

  • 函数的执行是由程序员事先安排好的(由一条调用函数指令来转入), 而中断服务程序是由随机的中断事件引起的 ;

  • 函数的调用受到主调函数控制
    而中断服务程序一般与被中断的程序毫无关系 ( 没有从属关系 );

  • 有可能发生多个中断事件同时请求 CPU 服务的情况。

  • 地址中断响应程序的入口地址固定 , 而函数或者子程序调用中的子函数可以放在程序空间的任意位置。

  • 中断返回指令RETI , 子程序返回指令RET

  • 有两种保护方式:外部保护再进子程序 ; 进入子程序后再保护。中断事件保护现场只能放在中断服务当中 , 不能提前保护现场

结构

中断源、中断标志位、中断开关、中断优先级、中断入口地址

EA 虚线代表几个开关是联动的

image-20240508114105761

中断源

中断源 TCON 中断向量(入口地址) 中断号 优先级
\(\overline{INT0}\) 外部中断 IE0 0003H-000AH 0
T0 定时计数器 0 TF0 000BH-0012H 1
\(\overline{INT1}\) 外部中断 1 IE1 0013H-001AH 2
T1 定时计数器 1 TF1 001BH-0022H 3
TX/RX 串行口 RI TI 0023H-002AH 4

5+1 = 6 个中断源:两个外部中断 , 两个定时中断 , 两个串行中断

  • \(\overline{INT0}\)(P3.2。可由IT0(TCON.0)选择其为低电平有效还是下降沿有效。当 CPU 检测到P3.2引脚上出现有效的中断信号时 , 中断标志IE0(TCON.1) 1, CPU 申请中断。
  • \(\overline{INT1}\)(P3.3。可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当 CPU 检测到P3.3引脚上出现有效的中断信号时 , 中断标志IE1(TCON.3) 1, CPU 申请中断。
  • TF0TCON.5, 片内定时 / 计数器T0溢出中断请求标志。当定时 / 计数器T0发生溢出时 , 置位TF0 , 并向 CPU 申请中断。
  • TF1TCON.7, 片内定时 / 计数器T1溢出中断请求标志。当定时 / 计数器 T1 发生溢出时 , 置位TF1 , 并向 CPU 申请中断。
  • RISCON.0)或TISCON.1, 串行发送 / 接受
    串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI , CPU 申请中断。

起始地址开始的 8 个地址

在第 2 章中已经讲过 , 地址为 0003H-002AH 的共 40 个单元是单片机 5 个中断源的中断服务程序存放地址区 , 它被分为 5 , 每段 8 个单元 , 分别分配给 5 个中断源 , 具体分配如下:

开关(都在 SFR

TCON(定时 / 计数器控制寄存器)

触发:低电平 or 下降沿

image-20240508115812183

  • IT0(TCON.0), 外部中断 0 触发方式控制位。
    IT0=0 , 为电平触发方式。
    IT0=1 , 为边沿触发方式(下降沿有效

  • IE0(TCON.1), 外部中断 0 中断请求标志位。

  • IT1(TCON.2), 外部中断 1 触发方式控制位。

  • IE1(TCON.3), 外部中断 1 中断请求标志位。

  • TF0(TCON.5), 定时 / 计数器T0溢出中断请求标志位。

  • TF1(TCON.7), 定时 / 计数器T1溢出中断请求标志位。

SCON( 串行口控制寄存器 )

image-20240621212044659

IP2 个人为优先级)

image-20240621210918383

IE(中断使能寄存器) 响应需要总开关打开且子开关打开

优先级

  • CPU 总是先响应优先级别最高的中断请求。

  • 不能被新的同级或低优先级的中断请求所中断

  • 能被高优先级中断请求所中断

打印机发送打印任务 , 中断 ,CPU 处理其他任务

实例

  • 中断源有中断请求

  • 此中断源的中断允许位为 1

  • CPU 开中断(即 EA=1

image-20240508122502143

image-20240508122506367

中断程序标准写法:

    ORG 0000H
START:
    LJMP MAIN                ;跳转到主程序
    ORG 0003H
    LJMP INT0                ;转向中断服务程序
    ORG 0030H                ;主程序
MAIN:
    CLR IT0                      ;设为电平触发方式
    SETB EA                     ;CPU开放中断
    SETB EX0                   ;允许中断
    MOV  DPTR,#1000H 		;设置数据区地址指针
    AJMP $
    ORG 0200H                  ;中断服务程序
INT0:
    PUSH PSW                  ;保护现场
    PUSH ACC
    CLR P3.0                     ;由P3.0输出0
    NOP;
    NOP;
    SETB P3.0					;由P3.0输出1,撤除       
    MOV A,P1					;输入数据
    MOVX   @DPTR,A				;存入数据存储器
    INC   DPTR					;修改数据指针,指向下一个单元
    ... ... 
    POP ACC                     ;恢复现场
    POP PSW
    RETI                              ;中断返回

外部中断的扩展

多外部中断源的系统示例。

设有 5 个外部中断源 , 中断优先级排队顺序为:XI0、XI1、XI2、XI3、XI4。试设计它们与 80C51 单片机的接口。

image-20240508133213756

    ORG  0003H
    LJMP INSE0       ;转外部中断0服务程序入口
    ORG  0013H
    LJMP INSE1		;转外部中断1服务程序入口
    … …
    … …
INSE0:  
	PUSH PSW	;XI0中断服务程序
    PUSH ACC
    … …
    … …
    POP  ACC
    POP  PSW
    RETI 
INSE1:
	PUSH PSW         ;中断服务程序
    PUSH ACC
    JB P1.0,DV1    ;P1.0为1,转XI1中断服务程序
    JB P1.1,DV2     ;P1.1为1,转XI2中断服务程序
    JB P1.2,DV3     ;P1.2为1,转XI3中断服务程序
    JB P1.3,DV4     ;P1.3为1,转XI4中断服务程序
INRET:
	POP ACC
    POP PSW
    RETI
DV1:
    … …             ;XI1中断服务程序
    AJMP INRET
DV2:
	… …             ;XI2中断服务程序
    AJMP INRET
DV3:
	… …             ;XI3中断服务程序
	AJMP INRET
DV4:
	… …             ;XI4中断服务程序
	AJMP INRET

定时 / 计数

时序

时序是对象(事件、信息)按照时间顺序组成的序列关系

时序图最为常用。

纵轴表示电平

image-20240621192004419

晶振fosc

机器周期、指令周期 、振荡周期、状态周期

1 状态 = 2 振荡

1 机器 = 12 振荡

1 指令 = 1~4 个机器周期

1 个指令周期 =N 个机器周期 =6N 个状态周期 =12N 个节拍 =12N 个时钟周期 =12N 个振荡周期

  • 如果晶振频率 \(f_{osc} = 12 MHz\), 则时钟周期 \(T_{clock}\) 为: \(T_{clock} = \frac{1}{12 \times 10^6 Hz} = 83.33 ns\)

  • 如果某个微处理器的一个机器周期需要 12 个时钟周期完成 , 则机器周期 \(T_{machine}\) 为: \(T_{machine} = 12 \times 83.33 ns = 1\mu s\)

短时延时函数

;简单
DELAY:
    MOV R7,#TIME
LOOP:
    NOP
    NOP
    DJNZ R7,LOOP
    RET

;定时较长
DELAY:
    MOV R5,#TIME1
LOOP2:
    MOV R7,#TIME2
LOOP1:
    NOP
    NOP
    DJNZ R7,LOOP1
    DJNZ R5,LOOP2
    RET

结构

image-20240508135706335

2 16 位定时器、计数器:

  • T0 由两个 8 SFR TH0(high) TL0 (low)构成
  • T1 由两个 8 SFR TH1 TL1 构成

实质是 +1 计数器

定时器在单片机内部就像一个小闹钟一样 , 根据时钟的输出信号 , 每隔“一秒”, 计数单元的数值就增加一 , 当计数单元数值增加到“设定的闹钟提醒时间”时 , 计数单元就会向中断系统发出中断申请 , 产生“响铃提醒”, 使程序跳转到中断服务函数中执行 - 定时器:机械周期,晶振已知;对片内时钟进行计数;计数值N乘以机器周期\(T_{cy}\)就是定时时间\(t\) 。 - 计数器:例如光电码盘测量电机转速;对Tx引脚输入的脉冲进行计数

1 计数器输入的计数脉冲有两个来源 , 一个是由系统的时钟振荡器输出脉冲经 12 分频后送来 ; 一个是 T0 T1 引脚输入的外部脉冲源。

寄存器

控制寄存器TCON

TR0 TR1 控制定时计数器的启动停止

TF0 TF1 溢出中断请求标志位

image-20240508115812183

工作方式寄存器TMOD

低四位 T0,高四位 T1

image-20240508140054318

  • M0M1 :工作方式设置位工作在 4 种模式
M1M0 工作方式 说明
00 方式 0 13 位定时计数器
01 方式 1 16 位定时计数器
10 方式 2 8 位自动重装定时计数器
11 方式 3 T0 两个独立 8 位计数器 ,T1 停止计数
  • CT:定时控制器选择位:工作在定时模式(0)还是计数模式(1)

  • GATE:启停模式

中断允许控制寄存器 IE

image-20240511233252243

开启 ET1,ET0 才能中断

工作方式

兼容 48 芯片 , 所以有 4 种工作状态

方式 0

方式 0 13 位计数 , TL0 的低 5 位(高 3 位未用)和 TH0 8 位组成

定时模式 Gate = 0,CT = 0

Gate = 1:由 INT0 进行控制

Gate = 0:或门让右侧一直是 1 , 完全由 TR 决定

image-20240511234311556

分析上图可以得出设置规律

  • 计数外部脉冲个数: \(1~8192(2^{13})\)

  • 定时时间: \(T~8192T\)

  • \(f_{osc}=12MHz\),\(T=1\mu s\) , 最大定时时间:\(8.19ms\)

控制不同初始值来控制定时时间:溢出后会中断

初始化定时 / 计数器时 , 初值 N 计算 :
- 定时机器周期数: \(N=\frac{t}{T}\) ——定时时间/机器周期
- 计数初值:$X=2^{13}-N $​——计数最大值与计数值之差

测量周期 / 频率

设置 TR = 1,CT = 0,GATE = 1;
INT0 输入 , 高电平时候 , 计时开始 ; 就可以记录高电平有多少个机械周期

方式 0, 查询方式

选用定时 / 计数器 1工作方式 0 产生 \(500\mu s\) 定时 , P1.1 输出周期为 \(1ms\) 的方波 , 设晶振频率 =\(6MHz\)

  • GATE=0(用 TR1 位控制定时的启动和停止)
  • C/T =0(置定时功能)
  • M1M0=00(置方式 0
  • 因定时 / 计数器 0 不用 , 可将其置为方式 0(不能置为工作方式 3
  • 这样可将 TMOD 的低 4 位置 0, 所以(TMOD)=00H。

\([2^{13}- X]\times 2=500 X=7942D=1111100000110B\) 将低5位送TL1,高8位送TH1得:\((TH1)=F8H\),\((TL1)=06H\)

    ORG 0000H
    LJMP MAIN
    ORG 0300H
MAIN:
    MOV TMOD,#00H    ;TMOD初始化
    MOV TH1,#0F8H    ;设置计数初值
    MOV TL1,#06H
    MOV IE,#00H      ;禁止中断
    SETB TR1         ;启动定时
LOOP: 
    JBC TF1,ZCZ      ;查询计数溢出
    AJMP LOOP
ZCZ:  
    MOV TL1,#06H     ;重新置计数初值
    MOV TH1,#0F8H
    CPL P1.1          ;输出取反
    AJMP LOOP         ;重复循环

方式 1

16 计数 65536

image-20240622004345473

GATE 1 的时候,由 INT0 决定

可以用来测量脉宽

定时时间超过最大定时时间

例如 , 要求延时 100ms, 最大 65536 个机械周期
可以设置成50ms延时并执行两次

例子

1 利用定时 / 计数器 T0 的方式 1, 产生 10ms 的定时 , 并使 P1.0 引脚上输出周期为 20ms 的方波 , 采用中断方式 , 设系统时钟频率为 12 MHz

由于晶振为 12 MHz, 所以机器周期 \(Tcy\) \(1 ns\)

\(N=\frac{t}{T_{cy}}=\frac{10\times10^{-3}}{1\times10^{-6}}=10000\)

\(X=65536-10000=55536=D8F0H\)

即应将 \(D8H\) 送入 \(TH0\) ,\(F0H\) 送入 \(TL0\)

M1M0=01,GATE=0,C/T=0, 可取方式控制字为 01H;

ORG   0000H  
LJMP  MAIN                ;跳转到主程序
ORG   000BH              ;T0的中断入口地址
LJMP  DVT0                ;转向中断服务程序
ORG   0100H

MAIN:
    MOV   TMOD,#01H 		;置T0工作于方式1
    MOV   TH0,#0D8H			;装入计数初值
    MOV   TL0,#0F0H          
    SETB  ET0				;T0开中断
    SETB  EA				;CPU开中断
    SETB TR0				;启动T0
    SJMP $					;等待中断,程序一直停在这里,直至中断。
DVT0:
    CPL  P1.0                ;P1.0取反输出
    MOV  TH0,#0D8H          ;重新装入计数值
    MOV  TL0,#0F0H           
    RETI                            ;中断返回
    END

方式 2

image-20240511235352718

8 位自动重装定时计数器

  • 方式 0, 方式 1, 溢出后变成 0000, 需要重新设置初始值

  • 方式 2, 可以自动将 TH0 中的值压入 TL0, 不需要人工赋值

一般 C/T = 0,GATE =0

计数外部脉冲个数范围:1~256(\(2^8\))

定时时间范围:T~256T

方式 2

1:用定时 / 计数器 1 以工作方式 2 计数 , 要求每计满 100 次进行累加器加 1 操作。

  • M1M0=10(方式 2

  • CT=1(计数功能 )

  • GATE=0(TR1 启动和停止)

因此(TMOD)=60H。

\(2^8-100=156D=9CH\) 所以 \(TH1=9CH\)

ORG 0000H
AJMP MAIN     ;跳转到主程序
ORG 001BH     ;定时/计数器1中断服务程序入口地址
INC A
RETI
ORG 0030H

MAIN:	
	MOV TMOD #60H	;TMOD初始化
	MOV TL1,#9CH	;首次计数初值
	MOV TH1,#9CH  	;装入循环计数初值
	SETB EA			;开中断
    SETB ET1
    SETB TR1       ;启动定时/计数器1
HERE:	SJMP $        ;等待中断

方式 3

image-20240512000523646

T0 分成两个 8 位定时 / 计数器 TL0 TH0 ;

TL0既可计数也可定时 , 是一个 8 位定时 / 计数器。占用了 T0; 所有控制位: C/T,TR0,GATE,TF0 INT0T0 引脚 ;

TH0只能作为定时器 , 因为 T0 已被 TL0 占用 , TH0 T1 的控制位:TR1、TF1;

如果定时 / 计数器 T0 工作在方式 3,T1 只能工作在 0、1、2 方式。此时由于 T1 的运行控制位 TR1 及计数溢出标志位 TF1 已被定时 / 计数器 T0 借用 , 这时 ,T1 作为串行口的波特率发生器使用。

image-20240512001740549

欲用 80C51 产生两个方波 , 一个周期为 200μs, 另一个周期为 400μs, 80C51 同时使用串行口 , 用定时器/计数器作为波特率发生器。

用两个独立的定时计数器实现两个不同周期的定时

这时T0采用方式 3 工作 , 其中 , TL0产生 \(200\mu s\) 定时 , P1.0输出方波 ;

TH0产生 \(400\mu s\) 定时 , P1.1输出方波 ;

T1设置为方式 2 作波特率发生器用。\(f_{OCC}=9.216MHz\)​​

  • TLO定时常数为TL0\(t_{10} = 100μs\),\(TCL0 = 2^8 - 9.216×10^6×100×10^{-6} = 256 - 76.8 = 179.2\),单位 \(\mu s\),为十进制数值。十六进制数值为TL0 = B3H

  • TH0定时常数为TH0:定时时间为 \(t10 = 200μs\)\(TCH0 = 2^8 - 9.216×10^6×200×10^-6 = 256 - 153.6 = 102.4\),单位 \(\mu s\), 为十进制数值。十六进制的值为TH0 = 66 H

  • TH1 的波特率(详细计算见串行口部分:设波特率为2400 , 则定时常数为TC2 = F6H

; 定时器0初始化
MOV TL0, #0B3H ; 设TL0初值(100us定时)
MOV TH0, #66H ; 设TH0初值(200us定时)
MOV TL1, #0F6H ; 设TL1初值(波特率为2400)
MOV TH1, #0F6H ; 设TH1初值
SETB TR0 ; 启动TL0
SETB TR1 ; 启动TH0
SETB ET0 ; 允许TL0中断
SETB ET1 ; 允许TH0中断
SETB EA ; CPU中断开放
AJMP $

; 定时器0中断服务程序
ORG 0200H
ITL0: MOV TL0, #0B3H ; 重装定时常数
CPL P1.0 ; 输出方波(200us)
RETI
ITH0: MOV TH0, #66H ; 重装定时常数
CPL P1.1 ; 输出方波(400us)
RETI

; 主程序
ORG 0000H
AJMP MAIN
ORG 000BH ; TL0的中断入口
AJMP ITL0
ORG 001BH ; TH0的中断入口
AJMP ITH0
ORG 0100H
MAIN: MOV SP, #60H ; 设栈指针
MOV TMOD, #23H ; 设T0为方式3,T1为2

初始化

image-20240512001802295

设置工作方式 TMOD

确定用 T0 还是 T1:初始化 TMOD 高四位还是低四位

定时模式还是计数模式:CT

方式 0-3 使用哪一种: M1M0

控制模式:GATE

计算初始值

计算加 1 计数器的计数初值 Count, 并将计数初值 Count 送入 THTL

初始值 = 上限 - 计数值

计数方式时: \(X=M-计数值\)

定时方式时: 定时值 \(t(\mu s)=(M—X)\cdot T_M=\frac{12}{f_{osc}(M-X)}\), 所以 \(X=M-t(\mu s)\times f_{osc}(MHz)_{12}\)

  • M 为定时计数器溢出值:\(2^N,N=13,16,8\)

  • \(T_M\)​单片机时钟周期

若采用中断方式 , 则应设置 IE

TCON

启动计数器工作 TCON, 启动定时计数器使 TR0 TR1 置位

image-20240516202857183

// 设置工作方式:GATE,C/T,M1M0→TMOD
TMOD = 0x01; // 定时器0工作在模式1

// 设置加1计数器初值:Count→TH,TL
TH0 = 0xFC;  // 高8位初值
TL0 = 0x66;  // 低8位初值

// 启动定时/计数器:1→TRx (x=0,1)
TR0 = 1;     // 启动定时器0

// 开中断:1→ETx (x=0,1),1→EA
ET0 = 1;     // 使能定时器0中断
EA = 1;      // 总中断使能

串口通信

数据通信 = 数据处理 + 数据传输

MCS-51 单片机的串行口——全双工的异步串行通信接口(即:通用异步收发器 UART

它内部包括一个发送器和一个接收器 , 实现 CPU 并行输出→串行发送 , 串行接收→CPU 并行接收的转换功能。

概念

有部分内容其实是计网物理层的内容

并行通信

串行通信

物理接口

参考串口、COM 口、UART , TTL、RS-232、RS-485 区别详解 - 知乎 (zhihu.com)

单片机应用原理篇之串行通信基本概念 _ 哔哩哔哩 _bilibili

串口、UART 口、COM 口、USB 口是指的物理接口形式 ( 硬件 )

概念

通用异步收发器(Universal Asynchronous Receiver/Transmitter),UART 是串口收发的逻辑电路,这部分可以独立成芯片,也可以作为模块嵌入到其他芯片里,单片机、SOC、PC 里都会有 UART 模块。

特指台式计算机或一些电子设备上的 D-SUB 外形 ( 一种连接器结构,VGA 接口的连接器也是 D-SUB) 的串行通信口,应用了串口通信时序和 RS232 的逻辑电平。

通用串行总线,和串口完全是两个概念。虽然也是串行方式通信,但由于 USB 的通信时序和信号电平都和串口完全不同,因此和串口没有任何关系。USB 是高速的通信接口,用于 PC 连接各种外设,U 盘、键鼠、移动硬盘、当然也包括“USB 转串口”的模块USB 转串口模块,就是 USB 接口的 UART 模块)

img

电平标准(电信号)

TTL、RS-232、RS-485 是指的电平标准 ( 电信号 )

全双工(逻辑 1: 2.4V5V 逻辑 0: 0V–0.5V)
距离:1m 左右

电平:全双工(逻辑 1:-15V–3V 逻辑 0:+3V–+15V)
距离:15m 左右,用 232 做中转可以做的更远;

负逻辑

image-20240516235636473

主要引脚 作用
TXD P3.0 发送数据
RXD P3.1 接收数据
SGND 信号接地

公头 - , 母头 - 孔(2,3 交换 ,5 共地)

image-20240516235207535

不能过远的原因 : 距离太远,电平衰减

RS485 是一种串口接口标准,为了长距离传输采用差分方式传输,传输的是差分信号,抗干扰能力比 RS232 强很多。
半双工(逻辑 1+2V-+6V 逻辑 0: -6V- -2V)
可以实现主从机器的功能

注意

COM 口一般是 RS232, 只是把 UART 的高电平电压增大了,以便传得更远,而 RS485 又在此基础上把低电平改成了负电压,从而把信号改成了差分信号,增加了抗干扰能力。其实信号的本质并没有变化。

通信方向

全双工: 通信双方可以在同一时刻互相传输数据

半双工: 通信双方可以互相传输数据 , 但必须分时复用一根数据线;

在发送时候不可以接收,在接收的时候不可以发送

对讲机

单工: 通信只能有一方发送到另一方 , 不能反向传输

image-20240622101003848

同步异步

异步:

通信双方各自约定通信速率 ,

传输数据是以字符为单位的 , 待传送的字符串中的每个字符均加上起始位、停止位、校验位等控制信息位 , 构成一个字符帧。空闲的时候发送的是高电平 5V;起始位有低电平

帧与帧之间的时间间隔是任意的

帧格式

同步:

通信双方靠一根时钟线来约定通信速率

image-20240516233936771

通信速率

通信速率是以每秒传送多少个二进制位来度量的 , 这个速率称作波特率(Baud Rate), 其单位为 bpsbits per second, / 秒)

常用波特率:300,600,1200,2400,4800,9600,19200

总线:连接各个设备的数据传输线路(类似于一条马路 , 把路边各住户连接起来 , 使住户可以相互交流)

先确定波特率,让定时器产生波特率,约定波特率再通信

结构

image-20240516235651266

串行数据缓冲寄存器 SBUF(99H)

(逻辑地址只有一个 , 两个物理地址)

类似于一个教室有两个门

image-20240517101614853

image-20240519232852513

虽然接收和发送 SBUF 使用同一个逻辑地址,但物理是两个地址

接收移位寄存器 , 每收到一个位 , 就左移一个位 , 满载(8bit)以后就移到 SBUF 当中

接收最多 2Byte, 主动发送最多 1Byte

接收方有两级缓存

串行口控制寄存器 SCON

image-20240517102324310

  • SM0、SM1——串行口工作方式选择位。

  • SM2——多机通信控制位 ( 主要用于方式 2 和方式 3)

  • REN-允许 / 禁止串行口接收控制位REN=1, 允许接收 ;REN=0, 禁止接收。可通过软件对该位进行设置

  • TB8-第 9 位发送数据:方式 0 中不使用 TB8。在方式 1 ,TB8 为停止位 , 在方式 2 和方式 3 ,TB8 的内容是要发送的数据格式中的第 9 位。

  • RB8-第 9 位接收数据:方式 0 中不使用 RB8;方式 1 RB8 为接收到的停止位;方式 2 和方式 3 ,RB8 存放接收到的第 9 位数据 , 在双机通信中 , 作为奇偶校验 ; 在多机通信中 , 用作区别地址帧 / 数据帧的标志。

  • TI ——发送结束和发送中断标志位:串行发送停止位的开始时候,内部硬件置 1;注意要清零

  • RI——接收结束和接收中断标志位

可以通过检验 TI RI 来判断是否接受、发送结束

电源控制寄存器 PCON

PCON 的单元地址为 87H, 其内部各位均不能进行位寻址

image-20240517105934465

SMOD 为串行口波特率倍增位 , 当串行口工作在方式 1 和方式 3 , 其波特率可调。调节手段之一便是利用 SMOD

(1)若 SMOD=0, 波特率不倍增 ;

(2)若 SMOD=1, 则选定的波特率倍频 1 ;

系统复位时 ,SMOD 自动清零

工作方式

帧的结构和通信速率不同

SM0 SM1 工作方式 功能描述 波特率
0 0 方式 0 8 位同步移位寄存器 $frac{fosc}{12} $
0 1 方式 1 10 位异步收发 由定时器控制
1 0 方式 2 11 位异步收发 \(\frac{fosc}{64}\) $frac{fosc}{32} $
1 1 方式 3 11 位异步收发 由定时器控制

工作方式 0

发送 / 接收过程:SBUF 中的串行数据由 RXD 逐位移出 / 移入

低位在先 , 高位在后;TXD 输出移位时钟 , 频率 = $frac{fosc}{12} $ ;

每送出 / 接收 8 位数据 TI/ RI 自动置 1; 需要用软件清零 TI/ RI

image-20240517110554534

发送完成后 ,TI 就置 1

串行口在方式 0 下的工作并非是一种同步通信方式 , 经常配合“串入并出”“并入串出”移位寄存器一起使用 , 以达到扩展一个并行口的目的。 扩展电路如下图所示。

image-20240517110640047

image-20240517110648124

51 RXD 传入有效信息位 ,TXD 机械周期放到时钟,对外展示并行输出

如要发送数据 , 查询方式的程序如下:

MOV SCON,#00H	;串行口方式0
MOV SBUF,A		;将数据送出
JNB TI,$         ;等待数据发送完毕,等待TI=1,即发送完成
CLR TI           ;为下次发送作准备,手动软件清零不要忘记

注意:复位时 ,SCON 已经被清零。

  • 发送条件:TI=0。

  • 接收条件:TI=0, 置位 REN=1 (允许接收数据

工作方式 1

10 位的异步通信:1 位起始位 +8 位信息位 +1 位结束位

波特率可变,由定时器 1 的波特率决定

起始位 D0 D1 D2 D3 D4 D5 D6 D7 停止位

波特率设置

  • 波特率 = \((2^{SMOD}/32) \times (定时/计数器1的溢出率)\)
  • 定时 / 计数器 1 的溢出率 =$ frac{f_{osc}}{12 times (256 - 初值 )}\(;溢出率指的是T1溢出的频率,计算出T1溢出一次的时间\)T\(,那么\)frac{1}{T}$ 就是 T1 的溢出率
  • 波特率 = \(2^{SMOD}/32 \times \frac{f_{osc}}{12 \times (256 - 初值)}\)
  • 定时器初值 = \(256 - \frac{f_{osc} \times 2^{SMOD}}{384 \times 波特率}\)

为了能够被 384 整除

串行口工作时 ,\(f_{osc}\) 常取 11.0592M 而非 12M, 是因为 11.0592M 时能提供更精确的波特率。12M 晶振计算出的定时器 T1 初值不是整数,会产生累计误差

;发送代码
    MOV	SCON,#40H    ;串口工作在方式1下
    MOV	A,P1
    MOV	SBUF,A    ;启动串口发送
LP:   
    JNB	TI	LP    ;等待发送完成
    CLR	TI           ;发送完成后清TI

image-20240517112045860

;接收代码
     MOV	SCON,	#50H; 串口工作在方式1,启动接收
LP: 
     JNB	RI	LP        ;  等待接受完毕
     MOV	A,	SBUF ;把收到的数据保存下来
     MOV	P1,	A      ;接收到的数据送P1口
     CLR	RI               ;  清接收中断标志

工作方式 2

1 位起始位 +8 位数据 +1 位校验 +1 位终止

起始位 D0 D1 D2 D3 D4 D5 D6 D7 校验 停止位

发送过程

A、首先根据要传送的 8 位数据的特征 ( 如奇偶、地址 / 数据特征 ) 决定第 9 个信息位的状态。

B、启动串口发送(MOV SBUF,AMOV SBUF,#XXH。按起始位、数据位 D0~D7、校验位、停止位的顺序将该帧信息以规定的波特率逐一从 TXD 引脚移出。

C、待发送完毕后自动将 SCON 中的 TI 位置 1, 表示发送过程结束。

image-20240519143852958

接收过程

A、软件将REN 1, 启动串行口在方式 2 下的接收过程 ;

B、UART 自动地按规定的波特率从引脚RXD上逐位接收信息 , 移入串口中的接收移位寄存器。

C、接收完毕后 , 将接收移位寄存器中的数据位 D0D7 锁入SBUF。同时将校验位送入SCON中的RB8 , 自动将SCON中的 RI 1, 表示接收过程结束。编程时可通过查询和中断方式对下一步进行处理。

image-20240519144526889

波特率设置

倍频:SMOD = 1 波特率 = \(\frac{2^{SMOD}\times f_{osc}}{64} = \frac{f_{osc}}{32}\)

不倍频:SMOD = 0 波特率 = \(\frac{2^{SMOD}\times f_{osc}}{64} = \frac{f_{osc}}{64}\)

工作方式 3

多级通信 or 奇偶校验

在方式 3 , 串行口的结构、传送的帧格式、各位的定义皆与方式 2 相同 , 唯一的区别在于工作方式 3 通信的波特率是可编程的。

初始化

RITI 不会自动清零 必须软件清零

先确定波特率,再找到溢出率,再计算定时器初值,让串口得到这个溢出率

方式 0 的波特率 =$ frac{fosc}{12}$

方式 2 的波特率 =\((\frac{2^{SMOD}}{64})\cdot fosc\)

方式 1 的波特率 =\((2^{\frac{SMOD}{32}}) \times (T1的溢出率)\)

方式 3 的波特率 =\((2^{\frac{SMOD}{32}}) \times (T1的溢出率)\)

image-20240517113020751

8f30c5e6ea7a025457568b080915e65

编程

查询方式

指令查询标志位 TI RI

TI =1, 一帧发送完 ,TI1, 没有发送完

RI=1, 一帧数据已送到 ,RI1, 没有送到

中断方式

设置中断允许 , TIRI作为中断请求标志位 , TI=1RI=1均可引发中断。

image-20240519150922105

串口方式 1

通过 MCS-51 串行口按模式 1 发送存放在片内RAM 20H~3FH中的数据 , 要求传送的波特率为1200bps。编写有关的通信程序。 fosc=11.0592MHz

设串行口为方式 1, 定时器 / 计数器 T1 为方式 2 作为串行口的波特率发生器。可以避免计数溢出后用软件重装定时初值的工作。 \(波特率 = \frac{2^{SMOD}}{32}\times \frac{fosc}{12\times(2^8-TH1)}\)\(SMOD=0\) \((TH1)=232=0E8H\)

;A机发送程序
MOV	 TMOD,#20H	;设T1为方式2
MOV	 TL1,#0E8H	;T1定时常数
MOV	 TH1,#0E8H
SETB TR1	;启动T1
MOV SCON,#01000000B;设串行口为方式1
MOV	 R0,#20H		;设发送数据区首址
MOV	 R7,#32		;发送32个ASCII码数据
LOOP:
    MOV	A,@R0 ;取ASCII码数据
    MOV	SBUF,A ;带校验位发送
    JNB	TI,$ ;发送等待
    CLR	TI ;清TI标志	
    INC	 R0 ;未发送完,则继续
    DJNZ R7,LOOP

采用查询方式,本例与上例相呼应,接收器把接收到的 32 个数据存放在 20H3FH 单元内,波特率同上。

MOV   SCON,#01010000B    ;设串口方式1,允许接收
MOV   TMOD,#20H;设置定时器T1为方式2
MOV   TL1,#0E8H                  ;初值,波特率为1200b/s
MOV   TH1,#0E8H  
SETB  TR1                   	           ;启动T1运行
MOV   R0,#20H                       ;数据存放首地址
MOV   R7,#32                        ;数据块长度
LOOP: JNB   RI,$         	;RI由硬件置位
CLR   RI            	;软件清除RI
MOV  A,SBUF 
MOV    @R0,A         	          ;存放接收的数据
INC      R0
DJNZ   R7,LOOP