分享

【MSP430趣谈】MSP430第四讲之简谈中断

 知芯世界 2020-10-28

上次和大家聊到了GPIO的使用,但是讲的不是很全面,要是全面涉及的话就是我们后面要讲的内容了,这里我们就不多加描述。在后期的讲解中也会慢慢涉及我们没有讲到的一些功能的。今天我们要涉及一个对于单片机来说非常重要的一个概念和功能。

什么是中断?

我们不以专业术语来描述这个东西,我们以一个比较好理解的方式来讲。首先大家要有一个理解就是我们单片机是按照程序一步一步的执行的,通过仿真的时候大家也可以看出来我们点击单步运行我们就可以看到光标向下移动一步,也就是单片机向下移动一步。就是单步运行的。就像我们人一样,你只能在一个时刻内做一件事情,没有办法说一边吃饭一边喝水吧(极短的时刻内你不行的吧),当你要做另外一件事的时候,你需要把手上这件事停下来去做另外一件事,对吧,这样子我们就产生了一个中断的概念,但我们在写作业的时候需要去把烧开的水关掉,就需要停止手头的事情去关掉开水。对于单片机来说也是这样的,我们看到我们之前写的程序中,都会有一个死循环,for(;;),这个是C语言的东西我们就不在过多描述了,在这个死循环里面做我们的动作,但是这是如果系统告诉我们需要去点亮一个灯,那单片机就需要停止死循环里面的动作,先去点灯,然后在跑回来继续执行死循环里面的代码。通过图示我们可以更加了解他的机制。

就如上图中描述的一样,当然我们也可以进行中断嵌套,也就是说在一个中断中间又进行中间又来一个优先级更高的中断,这是就会在中断当中又产生一个中断。这个我们在后头会继续再说,这里大家先知道一下他可以有这么个功能。

好了接下来我们进入中断的学习了,那么关于中断的知识我们该去哪里找呢?

还是那份文档,MSP430FR58xx, MSP430FR59xx, MSP430FR68xx, and MSP430FR69xx Family User's Guide.pdf。这份文档是十分重要的,我希望大家在写程序的时候需要打开它,查找到我们需要的那部分内容。

在第十章的10.2.6中有一个章节是Port Interrupts,这里就是讲到中断了。

插曲:

为什么我想写一个关于430的教程,前面也说到说他的资料较少,学的人感觉好像也不多,很少有人选择他作为入门的单片机学习,所以想打破这个局面。另外一个方面是他的很多资料是英文的,这个对大家是很有帮助的,在你以后进公司的时候可能面临的很多资料都不会是中文的,所以从一开始打破大家对中文的一种依赖性我觉得是很好的。虽然这样子明显难度就会大一些,我会尽量减少这个门槛的。

大家点击到这里的话就可以看到文档对中断的一个描述,我这里简单吧重点说一下,其他的大家就慢慢看一下,打开有道不懂的单词就查一下,不要觉得很烦,但是真的对你有很大的帮助。

对于430来讲,P1和P2口都是可以作为单片机的中断入口的,是由三个寄存器进行控制的。具体是PxIFG,PxIE,PxIES。有些器件可能会有些不同,具体要看他们的数据手册。

那么这三个寄存器分别是什么呢?

PxIFG(Port x Interrupt Flag Register)端口x中断标志寄存器

PxIE(Port x Interrupt Enable Register)端口x中断使能寄存器

PxIES(Port x Interrupt Edge Select Register)端口x中断边沿选择寄存器

接下来我们看下怎么用它来写代码。

所限我们需要明白使用中断的一个具体的步骤是什么?(这里我们使用的是端口中断,下次我们还会谈到定时器中断)

1.配置端口,设置端口的方向,也就是设置PxDIR的方向,设置上拉下拉等

注意:如果外部硬件上面没有上下拉电阻的话,这里一定要进行配置,否则将导致输入电平不稳定

2.设置中断的触发模式,上升沿还是下降沿或者两者均可以产生中断

3.开启中断,就是设置PxIE

4.编写中断子函数

5.清除中断标志位,设置PxIFG

大概是这样的一个操作流程,但是也可能中间还会有些不同的地方。要根据具体的使用情景和方式。

这里我们要实现的是按键按下触发中断然后点亮led。这里我们使用FR5969板子上的按键S2和LED2。

第一步:还是和之前一样,需要关闭看门狗。关闭低功耗模式

WDTCTL = WDTPW + WDTHOLD;

PM5CTL0 &= ~LOCKLPM5;

第二步:设置端口方向

P1DIR |= BIT0; //设置LED的方向

P1OUT &= ~BIT0;//设置LED的默认输出,为低电平不点亮

P1DIR &= ~BIT1;//这一步可以省略,但是我们最好都写,默认端口为输入

P1REN = BIT1;//设置按键的上拉电阻

第三步:配置中断

P1IES |= BIT1;//设置按键中断为下降沿触发

P1IE |= BIT1;//使能中断

最后我们还要使能总中断:

_enable_interrupts();

第四步:

我们要编写中断子函数:

#pragma vector = PORT1_VECTOR

__ interrupt void PORT1_ISR(void)

{

unsigned int Key = 0;

Key = P1IFG & (~P1DIR);

__delay_cycles(10000);

if((P1IN&Key) == 0)

{

switch(Key){

//Case BIT0: P10_Onclick();break;

Case BIT1: P11_Onclick();break;

//Case BIT2: P12_Onclick();break;

//Case BIT3: P13_Onclick();break;

//Case BIT4: P14_Onclick();break;

//Case BIT5: P15_Onclick();break;

//Case BIT6: P16_Onclick();break;

//Case BIT7: P17_Onclick();break;

}

}

P1IFG = 0;//清除中断标志位

}

void P11_Onclick()

{

P1OUT ^= BIT0;//翻转LED的电平

}

大家可以看到我们使用了一个switch的语句进行了Key的跳转,这里因为我们输入的引脚是P1.1所以我们对应的中断服务函数是P11_Onclick(),这样子有一个什么好处呢?就是我们可以封装我们的一个函数,可以写的更加方便,写一个函数我们达到P1端口任意一个引脚的按键输入。(这一段代码参考的是从零开启大学生电子设计之路一书)

这样子我们就完成了整个的一个中断函数的的编写,也完成了我们预期想要达到的一个目的,按下按键点亮LED。

我们大概说一下代码的书写,其实大家发现,这次代码的书写没有只写在main函数中,我们分成了几个函数,分别称为主函数和子函数,那么程序开始都是从主函数中执行的。现在我们的工程还不大,所以在一个c文件我们就可以达到我们想要的功能,但是等你的代码很复杂的话,就需要进行模块化的搭建,需要一个框架来整理整个代码结构。下一讲我们会具体讲到如何应用该方法。

#pragma vector = PORT1_VECTOR

这个中断向量定义,是固定的写法,具体为什么这么写,我们来看看。

所先#pragma是一个预处理指令,和我们#define有点类似,具体的话我也不懂希望大家给一下解释。

vector = PORT1_VECTOR

这一句我的理解是指定中断向量表的入口地址,那么这些地址定义在哪里呢?还是一样的办法,右键找到定义。在msp430FR5969.h文件中找到。

跟着下面就是我们要写的中断函数了,__ interrupt前面是两个下划线,表示该函数为中断服务函数这种特殊的函数。关于函数名字则大家可以自己取。

好了,本次就说这么多了,下次我们将更加具体的讲解如何利用TI官方给的库函数进行编写。


这一讲中我们只是简单介绍了IO的中断,其实中断还包括了很多内容,中断向量表,然后各种中断,一看你就头大的那种,这里我们暂时不说,只是给大家一个概念,之后我们用到的时候回在细细的说明!

欢迎观看

【MSP430趣谈】MSP430第一讲

【MSP430趣谈】MSP430第二讲

【MSP430趣谈】MSP430第三讲

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多