当前课程知识点:ARM微控制器与嵌入式系统 >  第五章 ARM微控制器的各种外设 >  5.3.2 ARM微控制器外设:IO的中断编程(下) >  5.3.2 ARM微控制器外设:IO的中断编程(下)

返回《ARM微控制器与嵌入式系统》慕课在线视频课程列表

5.3.2 ARM微控制器外设:IO的中断编程(下)在线视频

5.3.2 ARM微控制器外设:IO的中断编程(下)

下一节:5.4.1 ARM微控制器外设:定时器的原理

返回《ARM微控制器与嵌入式系统》慕课在线视频列表

5.3.2 ARM微控制器外设:IO的中断编程(下)课程教案、知识点、字幕

各位同学大家好

我是清华大学工程物理系的曾鸣老师

欢迎大家继续回到我们

ARM微控制器与嵌入式系统MOOC课堂

那么我们在这个单元里呢

继续挑战我们外设学习当中第一次的中断编程

我们仍然是拿最简单一类外设IO的中断来开刀

那么在前半个单元

前半个部分呢

我们花了很多很多口舌带着大家来回忆

中断是怎么样一种机制

然后这个中断是怎么工作起来的

以及中断向量表如何打开总开关

如何打开子开关等等这些内容

那么在这个单元

我们接着进行我们编程开发的剩下三个步骤

来真真正正把这个程序给写出来

在这个过程当中我带着大家

继续回忆和梳理加深理解

对于中断的这样一种程序的

运行机制和编程模式

这是我们学习的一个难点

但是大家学会了一定会觉得受益无穷

那么第二个步骤呢

就是把我们对应的中断源给配置好

就是 Configure the corresponding Interrupt Source

那么我们在第一个步骤打开了中断的总开关

那就不区分是哪个中断

同时打开了中断的子开关

如果大家认真回忆我们打开的那个子开关呢

是PORTA的子开关

也就是RORTA这个模块

这个引脚单元的中断源的子开关

我们已经打开了

换言之我们接下来应该配置PORTA

可是最多能管32个引脚哦

PTA0到PTA31

究竟哪一个引脚在什么情况下

可以向CPU产生中断呢

这是需要配置的

所以接下来我们要进行这样一个配置

对于每个引脚的配置

我不知道大家还有没有深刻的印象

我们都会有一个专门的寄存器

之前做IO编程的时候用过很多次

就是PORTx_PCRn这个寄存器

这个寄存器是每一个物理引脚

对应都有一个独立的寄存器

比如PTA1对应的就是PORTA_PCR1这个寄存器

我们之前对它的所有编程

都是对于这个寄存器下面这几个比特

特别是比特8、9、10这三个比特设值

设成000到111的这八个值来确定

这个引脚给哪个功能用

比如说我们一般会配置成001当IO用对不对

学UART的时候

我们会配置成UART这个串行通讯模块

所要的功能的值

这是我们做的一件事

那么在实验1的时候

我们如果对照电路图把这个引脚

希望配置成一个按键电路

我们还多配置了一位呢是这个比特1

也就是0X000...02这个配置

把这一位置1

那么这一位一旦置1

我们启用了这个IO的上拉电阻

那么对应我们的电路图呢

就是片内有一个上拉电阻

片外是一个接地的按键

于是当这个键不按的话

在上拉电阻作用下我们输入的时候

读到的逻辑1

键按下读到的是逻辑0

所以我们当时给的语句是PORTA_PCR1

也就是PTA这个引脚接了一个按键

我们赋了一个值

等于0X0102

就是给IO用

给上拉电阻

不知道大家回忆起来没有

那么涉及到中断源

一个PORTA我们设置了中断子开关打开

我们希望其中比如说按键PORTA_PTA1这个引脚

对应的按键成为我们的中断源

每次键按下告诉CPU发生了一个中断

我们应该怎么配置呢

在这个寄存器的上面几个比特

进行进一步的编程

比特16、17、18、19这四个比特

它们的值可以是0000到1111这16个值

那么其中1000、1001、1010和1111这四个值

都是将这个引脚配置成可以产生中断

而这四个值对应的是这个引脚

在发生什么样的电平变化的时候产生中断

如果我们读一下我们的电路我们会发现

我们的键平时是悬着的

内部上拉电阻作用下引脚读到的值

是逻辑高电平逻辑1

3.3伏

键按下的时候与地短路

我们引脚读到的值变成了0伏

也就是逻辑0

由1向0的跳变

是我们键按下的一瞬间

所以如果我们把这四个比特的值

配置成1010这个组合

也就是按照芯片手册第183页告诉我们的含义

那么把这个引脚配置成了

发生由1到0的下降沿的时候可以触发中断

那反过来有的同学说

老师 那我希望是这个键每次按下去不作用

一撒手发生作用

很简单

改这四个值

改成刚才这张表里的

由0到1上升沿的时候产生中断

就可以了对不对

所以如果我们完成这个中断源的配置

把某一个引脚配置成可以产生中断

就是PORTA_PCR1赋值这个语句稍微改一改

变成等于0X0A0102

是不是就配置成了下降沿可以产生中断

同时当IO用

并且启动上拉电阻

是不是跟我们电路就契合了

这就完成了这样一个中断源的配置

那么多说一句的是

如果大家仔细再看这个寄存器

我打出红框的比特24这一个比特

这个比特是我们这个引脚

对应的这个中断发生以后的中断标志位

中断标志位我们称为flag

也就是刚才我们配置这件事情一旦发生

它就置位产生1

这个1与我们中断总开关的开关的允许

大家记不记得大大的与号

三个条件都满足的时候

就会向CPU打出一个中断

那么换言之从操作上来讲

每当一个中断响应完了

我们应该清除这个中断标志位

以便在下一个按键

下一次跳变沿的时候

能够正确的再一次触发中断

这叫清除中断标志位

怎么清

大家看这个芯片手册这个图上

写了一个小小的字符串

对这一位的解释显示W1C

就是write one to clear

也就是你对它写一次1

就可以清掉标志位

也就是我们对这个比特要置一次1

怎么置1啊

把它跟有1这个比特或一下对不对

所以这是如何清中断标志位

在这个地方我们讲了两件事

如何配这个引脚成为中断源

以及日后操作当中如何清除中断标志位

所以把它对照我们的电路图大家就会发现

我们一共有八个引脚都接在PORTA上

比如说我们把第一个引脚PTA1这个IO

配置成我们的中断源

回头希望这个按键按下的时候

能够向我们的CPU发出一个中断请求

告诉CPU一件事发生了

也就是执行我们刚才所说的这样一个配置语句

放到我们主程序里大家会发现

就是比刚才的汇编语言打开总开关

C语言对NVIC寄存器置位打开子开关

又加了一句PORTA的PCR1等于0X0102

下降沿产生中断

设置为IO用和上拉电阻

我不再重复

那么这样我们就完成了前两个步骤

打开中断的总开关和配置这个中断这个

大大的PORTA能用的32个引脚里头

究竟哪一个或者哪几个引脚

可以以什么方式触发中断

那么外设具备 开关打开了

这个中断的条件也具备了

是不是这件事情一旦发生

这个键一旦被按下去

就会有一个请求从电路上打开我们的CPU

CPU收到这么一个请求

那么接下来两个编程大家回顾我们的思想

就是CPU在完全硬件的触发下

它得到这个请求

它应该能够正确的去调用一个函数

执行我们希望这个键按下以后所做的操作

也就是找到对应的corresponding的

ISR中断服务子程序

那么这我们的第三个步骤

那么这中断服务子程序怎么写呢

我们来回顾一下基本概念

在讲中断的时候我们讲

中断服务子程序是跟每一个中断源

每一个中断请求所对应的

要做的那样一个操作

我们把它写成一个函数

这个函数我们可以用C语言来写

特别是在ARM Cortex M0的CPU上

它跟普通的C语言函数没有任何区别

因为CPU在设计的时候

对于中断的返回指令该做哪些操作

已经自己在CPU的机制上加以了处理

在return指令的某一个比特上加以了标示

所以我们对于C语言

ARM的C语言编写的时候非常简单

就是写成了一个void的参数

void的返回值的这样一种函数类型就可以了

那么对于编程者大家要理解的是

这一个函数

是由我们前面设置的中断条件满足的时候

由CPU自动调用的

所以它写好了以后放在那里

它任何时候都不在我们main函数里被调用

所以它是在CPU条件符合的时候自动调用

这个概念大家一定要强

后面我们看整个程序

还会带着大家梳理这个概念

那么这个函数怎么写呢

它的原型就像我们这么说的

一个空的参数

void参数

一个void返回值的函数

里头要做do something

也就是我们这个中断发生了我们希望它做的事

最后记得清除中断标志位

以便下一次中断的发生

那写到我们这个IO的这个函数里头

非常清晰

PORTA如果发生了一次中断

这个中断源我们已经配置好了

是某一个或者某几个按键

能够触发这个中断

那么这个函数怎么写

在这样一个函数void类型

void的返回值里头

首先判断一下PORTA的PDIR寄存器

跟某个值与一下来判断

是哪一个按键按了引起了PORTA这个中断

比如说我们现在只配置了一个引脚

能够产生中断

但我们仍然进来做一次检查

检查完了确实是这个按键触发了中断

我们就做跟它对应的操作

什么操作呢

注意我们把bMode这个全局变量

在这里仍然取了下反

这是一个在堆上的全局变量

在中断函数里感觉它的值在main函数里

能够看得到它的变化对不对

然后我们把原来main函数里做的那个操作

把两个灯的状态进行一次归零

是归成两个灯同亮同灭

还是归成一亮一灭

是不是就对灯的闪烁模式进行了切换呢

那么在主程序那边它怎么做

我们待会看整个程序会再看

最后这个事做完了

每次按键切换了灯的闪烁模式在退出之前

我们是不是要清一下对应的中断标志位

也就是我们原来所说的PORTA_PCR1寄存器

我们要把它跟第24比特那个1或一下

对它写一次1

把它标志位清掉

这就是一个中断函数的写法

那么做完这件事

我们就完成了我们的第三个步骤

接下来 我们应该看的是第四个步骤

如何把这样一个中断函数

写好的函数跟我们的中断向量表关联起来

让我们CPU

能够在对应的中断发生的时候找到它

以及把刚才讲的所有内容关联起来

让大家理解这个中断函数究竟是怎么工作的

这是第四个步骤

那么在这个步骤里头我们再回忆一下

中断向量表是一段连续的存储空间

你可以把它认为是一个由指针构成的表

每一个指针都指向一个函数的入口地址

所以每当一个中断发生的时候

CPU就到这张表里头去读一个指针的值

从而使PC寄存器

跳转到一个对应的函数的入口地址

开始执行对应的函数操作

执行这个中断对应所需要做的那些操作

那么如何填表呢

其实我们中断向量表一共有48项

前16项是ARM公司设计的内部的异常

后面32项就是我们刚才所讲的从0到31

32个外设中断

那么我们如果再回忆一下

我们用到的PORTA这个中断

在外设这32个中断里排位第几号呢

我们前面做中断的这个子开关打开的时候

查中断表已经做过

PORTA是第30号

也就是第倒数第二项

那么换言之

我们就应该在这张表的倒数第二项

那四个字节这个表项里

填入我们刚才所写的这个函数的入口地址

第一条指令的地址

这样CPU在这个对应的中断发生了之后

到这个表里

把它的值搂出来

加载给PC指针

从而跳转到那个地方进行执行

这件事情说起来很清晰

很多同学听了很多基本概念以后

已经知道是什么含义

仍然不知道怎么做对不对

那么CodeWarrior帮我们做了很多基础的操作

如果我们绕开了这样一个简单的赋值

和对flash里头某一个地址填值的

这样一个操作的话

在CodeWarrior里头非常简单

我们新建一个project

指明了我们用的芯片型号的时候

如果大家打开CodeWarrior生成的代码的

最左边那个列

会有一个文件叫kinetis_sysinit.c

大家往下拉会发现CodeWarrior

自动的根据我们的型号

生成这么一个数据结构

这个数据结构里头是一系列函数的名称

构成的一个结构体

那么我们大家一定从C语言要记住这个概念是

跟数组一样

函数的名称也是一个指针

它的值就是函数的第一条指令

所以这个结构体里头

每一个函数名就是每一个函数的入口地址

所以我们顺着往下找

找到倒数第二发现这个函数名称已经填在这儿了

就是PORTA_IRQHandler这么一个函数名称

那么我们有两种做法

可以把我们刚才写的函数

跟这个地址关联起来

第一种这就是一个空函数

我们写我们的函数的时候

就把我们函数起成这个名字就可以了

它在编译的时候会自动的链接在一起

第二种就是我们给我们的中断函数

刚才写了一个不同的名字

我们将我们写的函数名

替换到这个结构体里然后加以编译和build

那么就回头我们函数入口地址

就会自动的填写到中断向量表这个位置

那么如果我们把刚才所有东西串联起来

得到的代码就是个屏幕所示

我们对于中断的这次编程

不是单独的一次实验

而是大家自己根据代码把它编写出来加以体验

体会它运行的机制

所以这里我多说两句

我们在我们的main函数里

完成了原来所有的打开时钟配置引脚的IO用

以及配置引脚的初始方向和值这些操作

增加了三句话

一句话是打开中断的总开关

一句话是打开中断PORTA的子开关

一句话是把PORTA里头的某一个

或者以后的某几个引脚

配置成在什么条件下

比如在下降沿下能够产生中断

就这么三句话

那么我们把我们对应的

中断源按键按下的操作拎出来

成了一个中断子函数大家看一看

是PORTA_IRQHandler这个函数

那么这个函数是void参数 void的返回值

并且这个函数在我们的main函数里头

任何时候都没有被调用

那么我们的main函数里头最后的for循环

只剩下了delay和让PORTA反转灯闪烁

那么大家一定要脑袋想清楚这样一种

中断工作的机制

用一句话或者用几句话来加以描述就是

我们设置好了一种中断触发的条件

并且让它可以发生就是这个键被按

一旦键被按一个指令

一个硬件的信号打给了CPU

CPU根据中断向量表

自动去调用IRQHandler这个函数

切换完了我们灯闪烁的基础模式

同时清理下中断标志位

以便下一次按键能够响应

这个函数就退出了

继续回到我们的主程序执行

而在主程序里for循环变得非常简单

只是延时闪烁

延时闪烁

换言之我们的中断函数

并不是被main函数调用

是在按键的时候

在人的操作下CPU自动调用

它可能发生在main函数这个循环体

无休无止的循环当中的任意时刻

而对我们灯的闪烁模式完成切换

所以这样一种中断的工作模式万变不离其宗

回到最开始大家想想最开始那张打电话的图

我们的主程序就是你正在做作业

正在做你的工作

而我们的中断就是一个拨进来的电话

每当拨进来一个电话你接起的时候

CPU切换了一下灯的闪烁模式

挂掉电话主程序继续周而复始的闪烁

这样的一种模式

使我们的程序变得可靠又简单

它从编程上好像难以理解

但是从程序的执行乃至结构

乃至可读性

乃至日后的维护上

都得到了极大的提升

所以通过这两个单元的学习

我相信大家第一次掌握了

如何真真正正编写一个中断程序

如果大家理解了

是不是觉得它不是那么难

如果大家没有理解没有关系

我们在下面的几个单元

还会有定时器等等模式

再让大家反复加深

对于中断这样一个难点理解

今天这节课就到这儿

ARM微控制器与嵌入式系统课程列表:

第一章 概览

-1.1 课程概览

--1.1 课程概览

-1.2 如何学好嵌入式系统

--1.2 如何学好嵌入式系统

第二章 绪论

-2.1 计算机的基本概念、发展历史

--2.1 计算机的基本概念、发展历史

-2.2 从晶体管到CPU

--2.2 从晶体管到CPU

-2.3 概念CPU、微控制器MCU和嵌入式系统

--2.3 概念CPU、微控制器MCU和嵌入式系统

-2.4 八卦计算机史

--2.4 八卦计算机史与创新

-2.5 不同领域、不同系列的嵌入式系统

--2.5 不同领域、不同系列的嵌入式系统

-2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU【习题】

--2.6 ARM历史与MKL25Z128 MCU【讨论】

第三章 MCU基础

-3.1 CPU的基本结构和运行机制

--3.1 CPU的基本结构和运行机制

-3.2.1 堆栈的概念

--3.2.1 堆栈的概念

--3.2.1 堆栈的概念【习题】

-3.2.2 堆栈的概念-头脑体操

--3.2.2 头脑体操

-3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构【习题】

-3.3.2 ARM的体系结构-头脑体操

--3.3.2 ARM的体系结构-头脑体操

-3.4.1 中断的概念和机制

--3.4.1 中断的概念和机制

-3.4.2 中断子程的概念和编程

--3.4.2 中断子程的概念和编程

-3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线【习题】

-3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制【习题】

第四章 ARM微控制器的开发

-4.1 第一种外设:IO

--4.1 第一种外设:IO

-4.2 IO外设的编程实操-点亮LED

--4.2 IO外设的编程实操-点亮LED

-4.3 IO外设的进阶知识

--4.3 IO外设的进阶知识

-4.4 嵌入式开发的基本概念与工具链

--4.4 嵌入式开发的基本概念与工具链

-4.5 嵌入式开发的进阶知识

--4.5 嵌入式开发的进阶知识

-4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)【习题】

-4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)【习题】

-E0.1 实验零 开发板的初步认识与工具链的安装

--E0.1 实验零 开发板的初步认识与工具链的安装

-E0.2 实验零 体验一个例程的编译与下载

--E0.2 实验零 体验一个例程的编译与下载

-E0.3 实验零 编写第一个程序:点亮核心板LED

--E0.3 实验零 编写第一个程序:点亮核心板LED

-E1 实验一 点灯秘籍

--E1 实验一 点灯秘籍

第五章 ARM微控制器的各种外设

-5.1 ARM微控制器外设学习概述

--5.1 ARM微控制器外设学习概述

-5.2.1 ARM微控制器外设:通讯

--5.2.1 ARM微控制器外设:通讯

-5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)

--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)

--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)【习题】

-5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)

--5.2.3 ARM微控制器的外设:异步串行通讯UART的原理(下)

--5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)【习题】

-5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口

--5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口

-5.2.5 ARM微控制器外设:UART的寄存器编程(上)

--5.2.5 ARM微控制器外设:UART的寄存器编程(上)

-5.2.6 ARM微控制器外设:UART的寄存器编程(下)

--5.2.6 ARM微控制器外设:UART的寄存器编程(下)

--5.2.6 ARM微控制器外设:UART的寄存器编程(下)【习题】

-E2 实验二 UART编程实操

--E2 实验二 UART编程实操

-5.3.1 ARM微控制器外设:IO的中断编程(上)

--5.3.1 ARM微控制器外设:IO的中断编程(上)

-5.3.2 ARM微控制器外设:IO的中断编程(下)

--5.3.2 ARM微控制器外设:IO的中断编程(下)

-5.4.1 ARM微控制器外设:定时器的原理

--5.4.1 ARM微控制器外设:定时器的原理

-5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程【习题】

-E3 实验三 定时器中断编程实操

--E3 实验三 定时器中断编程实操

-5.5.1 ARM微控制器外设:PWM的原理

--5.5.1 ARM微控制器外设:PWM的原理

-5.5.2 ARM微控制器外设:PWM寄存器与编程

--5.5.2 ARM微控制器外设:PWM寄存器与编程

-5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

--5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

-E4 实验四 数码管显示编程实操

--E4 实验四 数码管显示编程实操

-5.6.1 ARM微控制器外设:SPI通讯简介

-- 5.6.1 ARM微控制器外设:SPI通讯简介

--5.6.1 ARM微控制器外设:SPI通讯简介【习题】

-5.6.2 ARM微控制器外设:SPI寄存器与编程

-- 5.6.2 ARM微控制器外设:SPI寄存器与编程

-5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动

--5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动

-5.7.1 ARM微控制器外设:I2C通讯简介

--5.7.1 ARM微控制器外设:I2C通讯简介

-5.7.2 ARM微控制器外设:I2C的通讯协议

--5.7.2 ARM微控制器外设:I2C的通讯协议

-5.7.3 ARM微控制器外设:I2C寄存器与编程

--5.7.3 ARM微控制器外设:I2C寄存器与编程

--5.7.3 ARM微控制器外设:I2C寄存器与编程【习题】

-5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器

--5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器

-5.8.1 ARM微控制器外设:ADC简介

--5.8.1 ARM微控制器外设:ADC简介

-5.8.2 ARM微控制器外设:ADC基础

--5.8.2 ARM微控制器外设:ADC基础

-5.8.3 ARM微控制器外设:ADC寄存器与编程

--5.8.3 ARM微控制器外设:ADC寄存器与编程

-E5 实验五 ADC编程实操

--E5 实验五 ADC编程实操

-E6 挑战实验

--E6 挑战实验

第六章 嵌入式系统设计

-6.1 嵌入式系统的接口与设计

--6.1 嵌入式系统的接口与设计

-6.2 嵌入式系统的实例

--6.2 嵌入式系统的实例

5.3.2 ARM微控制器外设:IO的中断编程(下)笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。