从单片机基础到程序框架(全集 2019pdf版).pdf - 第361页
断函数” 仿佛是隔离 的毫无 “物理连接” 的, 为什么单片 机还能在 “m ain 函数” 与 “中断函数” 两者中切换 自如?没错 ,确实, “ma in 函数”与 “中断函数” 在书写上是 隔离的毫无 关联的 ,但是它们 之间之所以 能相 互切换,是 因为背后有一 只无形的手在 自动操 控这一切,这 只手就是单片 机硬件自身, 这是一 种特殊机制, 也可以理解 成一种特殊 的游戏规则, 我们只要遵 守就好 了, 除了普通函 数, …

第八十四节: 中断与中断函数。
【84.1 中断。】
单片机的“中断”跟日常生活的“中断”差不多,我正在做“常事”的时候,突然遇到优先级更高的“急
事”,这时我必须先暂停手上的“常事”,马上去处理突如其来的“急事”,处理完“急事”再返回来继续做
“常事”。要理解单片机的“中断”,有六个关键点,第一点是“配置中断”,第二点是“做常事”,第三点是
“中断请求”,第四点是“保护中断现场”,第五点是“处理急事”,第六点是“返回中断现场”。举一个我生
活的例子如下:
第一点:我老婆随时都会打电话给我,所以我的手机 24 小时都打开处于待机的状态。(配置中断)
第二点:我正在读一本书《道德经》(做常事)。
第三点:当我读到第 18 页的时候,老婆突然给我打电话,让我去幼儿园帮接一下小孩(中断请求)。
第四点:我在第 18 页里夹了一张书签做标记(保护中断现场)。
第五点:我放下手上的书去幼儿园接小孩(处理急事)。
第六点:接了小孩,我回来继续打开《道德经》,找到书签标记的第 18 页(返回中断现场),继续阅读。
上述六点,在单片机的 C 语言里,“配置中断”放在主函数的初始化那里,“做常事”放在主函数的主循
环里(main 函数内部的 while(1)循环),“中断请求”单片机内部硬件检测到符合发生中断的条件,“保护中
断现场”是单片机内部硬件电路自动处理的(不需要我们软件干涉),“处理急事”是单片机自动跳转到另外
开辟的一个特殊中断函数处理(自动跳转是单片机的硬件自动完成不需要我们软件干涉),执行完一次中断
函数后单片机再自动跳转到主函数的主循环的现场点继续从现场点开始继续做常事(返回中断现场)。在这
六点中,其中第四点的“保护中断现场”与第六点的“返回中断现场”是要特别强调的,单片机从 main 函
数的主循环 while(1)准备跳转到中断函数之前,它会自动记录当前的位置(做好路标),以便处理完中断函
数后再返回 main 函数的主循环 while(1)时,能找到之前的被中断跳转前的位置,这样就可以接上原来的步
骤去处理原来的“常事”,在步骤上既不提前也不滞后恰到好处,中断就不会影响到常事的完整性。代码分
布图的模板描述如下:
void main()
{
配置中断;
while(1)
{
处理常事;
}
}
void 中断函数() interrupt 序号 //中断函数后缀带“interrupt 序号”特别修饰
{
急事;
}
奇怪!上述代码,为什么“main 函数”与“中断函数”在软件上看不到任何关联,既不存在“main 函
数”调用“中断函数”,也不存在“中断函数”调用“main 函数”的情况,在观感上,“main 函数”与“中
断函数”仿佛是隔离的毫无“物理连接”的,为什么单片机还能在“main 函数”与“中断函数”两者中切换
自如?没错,确实,“main 函数”与“中断函数”在书写上是隔离的毫无关联的,但是它们之间之所以能相
互切换,是因为背后有一只无形的手在自动操控这一切,这只手就是单片机硬件自身,这是一种特殊机制,
也可以理解成一种特殊的游戏规则,我们只要遵守就好了,除了普通函数,其它凡是中断函数的,都不用跟
main 函数发生软件上的关联调用,它们之间的切换都是硬件自动完成的,这就是 main 函数与中断函数的特
殊跳转机制(或者称为游戏规则也可以)。
【84.2 常用的中断函数有哪三类?】
单片机的中断有很多,但常用在项目上的有三类:
第一类是定时中断。配置中断后,使其每隔一段时间就产生一次中断,比如“1ms 一次的定时中断”几
乎是所有的系统里的标配,因为它对程序框架起到一个时间节拍的作用。
第二类是通讯中断。比如串口每接收完一个字节就会产生一个中断通知我们去处理。
第三类是电平变化的中断。下降沿或者上升沿的中断,常常用在采集高速的脉冲信号。
【84.3 我们如何操控中断?】
刚才 84.1 提到“单片机硬件自动”这个概念,但是说它“硬件自动”并不意味着它不可控。单片机本
身出厂的时候内部就携带了很多种类的中断,这些中断是否开启取决于你的“配置中断”代码,你要开启或
者关闭某类中断,只需编写对应的“配置中断”代码就可以,而“配置中断”的代码本质就是填写某些寄存
器数值。

第八十五节: 定时中断的寄存器配置。
【85.1 寄存器配置的本质。】
单片机内部可供我们选择的资源非常丰富,有定时器,有串口,有外部中断,等等。这些丰富的资源,
就像你进入一家超市,你只需选择你所需要的东西就可以了,所以配置寄存器的关键在于选择,所谓选择就
是往寄存器里面做填空题,单片机系统内部再根据你的“选择清单”,去启动对应的资源。那么我们怎么知
道某个型号的单片机内部有哪些资源呢?看该型号“单片机的说明书”呀,“单片机的说明书”就是我们通
常所说的“芯片的 datasheet”,或者说是“芯片的数据手册”,这些资料单片机厂家会提供的。
跟单片机打交道,其实跟人打交道没什么区别,你要让单片机按照你的“意愿”走,你首先要把你的“意
愿”表达清楚,这个“意愿”就是信息,信息要具备准确性和唯一性,不能模凌两可。比如,现在要让单片
机“每 1ms 产生一次中断”,你想想你可能需要给单片机提供哪些信息?
(1)51 单片机有 2 个定时器,一个是 0 号定时器,一个是 1 号定时器,我们要面临“二选一”的选择,
本例子中用的是“0 号定时器”。
(2)0 号定时器内部又有 4 种工作方式:方式 0,方式 1,方式 2,方式 3,本例子中用的是“方式 1”。
(3)定时器到底多长时间中断一次,这就涉及到填充与中断时间有关的寄存器的数值,该数值是跟时
间成比例关系,本例子中配置的是 1ms 中断,就要填充对应的数值。
(4)默认状态下,定时器是不会被开启的,如果要开启,这里就是涉及到定时器的“开关”,本例子要
开启此开关。
(5)定时器时间到了就要产生中断,中断也有“总开关”和“定时器的局部开关”,这两个开关都必须
同时打开,中断才会有效。
要配置定时器“每 1ms 产生一次中断”,大概就上述这些信息,根据这些信息提示,下面开始讲解一下
寄存器的具体内容。
【85.2 定时器/计数器的模式控制寄存器 TMOD。】
寄存器 TMOD 是一个 8 位的特殊变量,里面每一位都代表了不同的功能选择。根据芯片的说明书,TMOD
的 8 位从左到右依次对应从 D7 到 D0(左高位,右低位),定义如下:
GATE C/T M1 M0 GATE C/T M1 M0
仔细观察,发现左 4 位与右 4 位是对称的,分别都是“GATE,C/T , M1 , M0”,左 4 位控制的是“定
时器 1”,右 4 位控制的是“定时器 0”,因为本例子用的是“定时器 0”,因此“定时器 1”的左 4 位都设置
为 0 的默认数值,我们只需重点关注右 4 位的“定时器 0”即可。
GATE:定时器是否受“其它外部开关”的影响的标志位。定时器的开启或者停止,受到两个开关的影响,
第一个开关是“自身原配开关”,第二个开关是“其它外部开关”。GATE 取 1 代表定时器受“其它外部开关”
的影响,取 0 代表定时器不受“其它外部开关”的影响。本例子中,定时器只受到“自身原配开关”的影响,
而不受到“其它外部开关”的影响,因此,GATE 取 0。
C/T:定时器有两种模式,该位取 1 代表“计数器模式”,取 0 代表“定时器模式”。本例子是“定时器
模式”,因此,C/T 取 0。
M1 与 M0:工作方式的选择。M1 与 M0 这两位的 01 搭配,可以有 4 种组合(00,01,10,11),每一种组合
就代表一种工作方式。本例子选用“方式 1”,因此 M1 与 M0 取“01”的组合。
综上所述,TMOD 的配置代码是:TMOD=0x01;