嵌入式单片机MSP430F149学习笔记(三)IO中断方式来实现按键检测

姓名:周唯 ;学号:20011210136;学院:通信工程学院

原链接:https://blog.csdn.net/weixin_44323997/article/details/117154707

【嵌牛导读】MSP430的中断有哪些作用?如何使用按键中断?

【嵌牛鼻子】单片机、msp430、中断

【嵌牛提问】如何使用IO中断?

【嵌牛正文】

一、按键说明

在MSP430开发板中,有四个按键连接到P1,即


按键io口连接表


二、中断流程图

中断流程图如下,在用C语言实现我们想要的功能的时候,我们可能需要使用switch、if语句对某些变量进行多次判别,这样会加长我们的代码并且不易观看,使用外部中断的好处就是:

1.可以在中断服务程序中对变量的值进行修改,从而达到随时更改变量值的目的

2.对一些变量可以进行单独控制,减少主程序代码的长度


中断流程图1



中断流程图2

三、中断配置

我们要开启P1口的低四位中断,使用下降沿触发中断,意思就是,我们按下按键,某个p1口由高电平状态→低电平状态,便产生了一个下降沿,从而触发了中断程序,代码如下:

//*************************************************************************

// 初始化IO口子程序

//*************************************************************************

void Port_init()

{

  P1SEL = 0x00;                  //P1普通IO功能

  P1DIR = 0xF0;                  //P10~P13输入模式,外部电路已接上拉电阻

  P1IE  = 0x0F;                  //开启P1低四位中断

  P1IES = 0x0F;                  //下降沿触发中断

  P1IFG = 0x00;                  //软件清零中断标志寄存器


  LED8DIR = 0xFF;                //P6口输出模式

  LED8  = 0xFF;                  //先关闭所有LED

}


在中断程序中,我们判别是哪个按键按下,并且清零中断标志寄存器

中断标志寄存器里面存储了中断的信息,我们正是依靠它来判别出是哪个按键按下来了,所以判别出来了之后还需要将其清零,方便下次中断操作,代码如下:

//**********************************************************************

// P1口中断服务程序,需要判断

//**********************************************************************

#pragma vector = PORT1_VECTOR

__interrupt void P1_IRQ(void)

{

  switch(P1IFG&0x0F)

  {

  case 0x01: key=0x01;P1IFG=0x00;state = 'D';break;    // 引脚0对应S1中断,必须手动清标志位,点亮D1D2

  case 0x02: key=0x02;P1IFG=0x00;state = 'N';break;    // 引脚1对应S2中断,必须手动清标志位,点亮D3D4

  case 0x04: key=0x03;P1IFG=0x00;break;    // 引脚2对应S3中断,必须手动清标志位,点亮D5D6

  case 0x08: key=0x04;P1IFG=0x00;break;    // 引脚3对应S4中断,必须手动清标志位,点亮D7D8

  }

}

在中断程序中,我们的操作是:

按下key1,给全局变量state赋值‘D’

按下key2,给全局变量state赋值‘N’

四、完整代码

该代码有两部分,一个是配置文件Config.h,另外一个是主文件main.c

Config.h

/********************************************************************

//DM430-L型最小系统板外部资源配置文件Config.h

//包含板载各个资源的硬件配置,如果用户使用过程中,对应的硬件发生了更改,可利用该头文件更改使用

//SD/MMC卡初始化硬件配置未包含

********************************************************************/

//延时函数,IAR自带,经常使用到

#define CPU_F ((double)8000000)  //外部高频晶振8MHZ

//#define CPU_F ((double)32768)  //外部低频晶振32.768KHZ

#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))

#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

//自定义数据结构,方便使用

#define uchar unsigned char

#define uint  unsigned int

#define ulong unsigned long

//8个LED灯,连接在P6口,可通过断开电源停止使用,ADC使用时断开电源

#define LED8DIR        P6DIR

#define LED8            P6OUT                            //P6口接LED灯,8个

//4个独立按键连接在P10~P13

#define KeyPort        P1IN                              //独立键盘接在P10~P13

//串口波特率计算,当BRCLK=CPU_F时用下面的公式可以计算,否则要根据设置加入分频系数

#define baud          9600                                //设置波特率的大小

#define baud_setting  (uint)((ulong)CPU_F/((ulong)baud))  //波特率计算公式

#define baud_h        (uchar)(baud_setting>>8)            //提取高位

#define baud_l        (uchar)(baud_setting)              //低位

//RS485控制管脚,CTR用于控制RS485处于收或者发状态

#define RS485_CTR1      P5OUT |= BIT2;          //控制线置高,RS485发送状态

#define RS485_CTR0      P5OUT &= ~BIT2;        //控制线置低,RS485接收状态

//2.8寸TFT彩屏显示控制相关硬件配置

#define RS_CLR         P5OUT &= ~BIT5          //RS置低

#define RS_SET         P5OUT |=  BIT5          //RS置高

#define RW_CLR         P5OUT &= ~BIT6          //RW置低

#define RW_SET         P5OUT |=  BIT6          //RW置高

#define RD_CLR         P5OUT &= ~BIT7          //E置低

#define RD_SET         P5OUT |=  BIT7          //E置高

#define CS_CLR         P5OUT &= ~BIT0            //CS置低

#define CS_SET         P5OUT |=  BIT0            //CS置高

#define RST_CLR         P5OUT &= ~BIT3            //RST置低

#define RST_SET         P5OUT |=  BIT3            //RST置高

#define LE_CLR         P5OUT &= ~BIT1            //LE置低

#define LE_SET         P5OUT |=  BIT1            //LE置高

//2.8寸TFT彩屏触摸屏控制相关硬件配置

#define PEN_CLR         P2OUT &= ~BIT0          //PEN置低,触碰触摸屏时,Penirq引脚由未触摸时的高电平变为低电平

#define PEN_SET         P2OUT |=  BIT0          //PEN置高

#define PEN            (P2IN & 0x01)            //P2.0输入的值

#define TPDO_CLR P2OUT &= ~BIT1          //TPDO置低

#define TPDO_SET P2OUT |=  BIT1          //TPDO置高

#define TPDOUT          ((P2IN>>1)&0x01)        //P2.1输入的值

#define BUSY_CLR P2OUT &= ~BIT3          //BUSY置低

#define BUSY_SET P2OUT |=  BIT3          //BUSY置高

#define TPDI_CLR P2OUT &= ~BIT4            //TPDI置低

#define TPDI_SET P2OUT |=  BIT4            //TPDI置高

#define TPCS_CLR P2OUT &= ~BIT5            //TPCS置低

#define TPCS_SET P2OUT |=  BIT5            //TPCS置高

#define TPCLK_CLR P2OUT &= ~BIT6            //TPCLK置低

#define TPCLK_SET P2OUT |=  BIT6            //TPCLK置高

//彩屏/12864液晶/1602液晶的数据口,三液晶共用

#define DataDIR        P4DIR                    //数据口方向

#define DataPort        P4OUT                    //P4口为数据口

//12864/1602液晶控制管脚

#define RS_CLR         P5OUT &= ~BIT5          //RS置低

#define RS_SET         P5OUT |=  BIT5          //RS置高

#define RW_CLR         P5OUT &= ~BIT6          //RW置低

#define RW_SET         P5OUT |=  BIT6          //RW置高

#define EN_CLR         P5OUT &= ~BIT7          //E置低

#define EN_SET         P5OUT |=  BIT7          //E置高

#define PSB_CLR         P5OUT &= ~BIT0            //PSB置低,串口方式

#define PSB_SET         P5OUT |=  BIT0            //PSB置高,并口方式

#define RST_CLR         P5OUT &= ~BIT1            //RST置低

#define RST_SET         P5OUT |= BIT1            //RST置高

//12864应用指令集

#define CLEAR_SCREEN 0x01           //清屏指令:清屏且AC值为00H

#define AC_INIT 0x02           //将AC设置为00H。且游标移到原点位置

#define CURSE_ADD 0x06           //设定游标移到方向及图像整体移动方向(默认游标右移,图像整体不动)

#define FUN_MODE 0x30           //工作模式:8位基本指令集

#define DISPLAY_ON 0x0c           //显示开,显示游标,且游标位置反白

#define DISPLAY_OFF 0x08           //显示关

#define CURSE_DIR 0x14           //游标向右移动:AC=AC+1

#define SET_CG_AC 0x40           //设置AC,范围为:00H~3FH

#define SET_DD_AC 0x80                      //设置DDRAM AC

#define FUN_MODEK 0x36           //工作模式:8位扩展指令集

//颜色代码,TFT显示用

#define White          0xFFFF          //显示颜色代码

#define Black          0x0000

#define Blue          0x001F

#define Blue2          0x051F

#define Red            0xF800

#define Magenta        0xF81F

#define Green          0x07E0

#define Cyan          0x7FFF

#define Yellow        0xFFE0

//NRF2401模块控制线

#define  RF24L01_CE_0        P1OUT &=~BIT5        //CE在P15       

#define  RF24L01_CE_1        P1OUT |= BIT5       

#define  RF24L01_CSN_0      P2OUT &=~BIT7        //CS在P27

#define  RF24L01_CSN_1      P2OUT |= BIT7   

#define  RF24L01_SCK_0      P3OUT &=~BIT3        //SCK在P33

#define  RF24L01_SCK_1      P3OUT |= BIT3 

#define  RF24L01_MISO_0      P3OUT &=~BIT2        //MISO在P32

#define  RF24L01_MISO_1      P3OUT |= BIT2

#define  RF24L01_MOSI_0      P3OUT &=~BIT1        //MOSI在P31

#define  RF24L01_MOSI_1      P3OUT |= BIT1

#define  RF24L01_IRQ_0      P1OUT &=~BIT4        //IRQ在P14   

#define  RF24L01_IRQ_1      P1OUT |= BIT4

//DS18B20控制脚,单脚控制

#define DQ_IN         P1DIR &= ~BIT7   //设置输入,DS18B20接单片机P53口

#define DQ_OUT         P1DIR |= BIT7   //设置输出

#define DQ_CLR         P1OUT &= ~BIT7           //置低电平

#define DQ_SET         P1OUT |= BIT7           //置高电平

#define DQ_R         P1IN & BIT7   //读电平

//红外接收头H1838控制脚,单脚控制

#define RED_IN         P1DIR &= ~BIT6           //设置输入,红外接收头接单片机PE3口

#define RED_OUT         P1DIR |=  BIT6           //设置输出

#define RED_L         P1OUT &= ~BIT6           //置低电平

#define RED_H         P1OUT |= BIT6            //置高电平

#define RED_R         (P1IN & BIT6)           //读电平

//***********************************************************************

//                  系统时钟初始化,外部8M晶振

//***********************************************************************

void Clock_Init()

{

  uchar i;

  BCSCTL1&=~XT2OFF;                //打开XT2振荡器

  BCSCTL2|=SELM1+SELS;              //MCLK为8MHZ,SMCLK为8MHZ

  do{

    IFG1&=~OFIFG;                  //清楚振荡器错误标志

    for(i=0;i<100;i++)

      _NOP();

  }

  while((IFG1&OFIFG)!=0);          //如果标志位1,则继续循环等待

  IFG1&=~OFIFG;

}

//***********************************************************************

//                  系统时钟初始化,内部RC晶振

//***********************************************************************

void Clock_Init_Inc()

{

  uchar i;


// DCOCTL = DCO0 + DCO1 + DCO2;              // Max DCO

// BCSCTL1 = RSEL0 + RSEL1 + RSEL2;          // XT2on, max RSEL


  DCOCTL = 0x60 + 0x00;                      //DCO约3MHZ,3030KHZ

  BCSCTL1 = DIVA_0 + 0x07;

  BCSCTL2 = SELM_2 + DIVM_0 + SELS + DIVS_0;

}

//***********************************************************************

//                  系统时钟初始化,外部32.768K晶振

//***********************************************************************

void Clock_Init_Ex32768()

{

  uchar i;

  BCSCTL2|=SELM1 + SELM0 + SELS;    //MCLK为32.768KHZ,SMCLK为8MHZ

  do{

    IFG1&=~OFIFG;                  //清楚振荡器错误标志

    for(i=0;i<100;i++)

      _NOP();

  }

  while((IFG1&OFIFG)!=0);          //如果标志位1,则继续循环等待

  IFG1&=~OFIFG;

}

//***********************************************************************

//              MSP430内部看门狗初始化

//***********************************************************************

void WDT_Init()

{

  WDTCTL = WDTPW + WDTHOLD;      //关闭看门狗

}

main.c

/********************************************************************

//DM430-L型最小系统板4位独立按键作为中断按键使用测试程序,下降沿触发

//按不同的按键,显示不同的LED灯,具体请看程序,测试外部中断功能

********************************************************************/

#include <msp430x14x.h>

#include "Config.h"

uchar key;

uchar state;

//*************************************************************************

// 初始化IO口子程序

//*************************************************************************

void Port_init()

{

  P1SEL = 0x00;                  //P1普通IO功能

  P1DIR = 0xF0;                  //P10~P13输入模式,外部电路已接上拉电阻

  P1IE  = 0x0F;                  //开启P1低四位中断

  P1IES = 0x0F;                  //下降沿触发中断

  P1IFG = 0x00;                  //软件清零中断标志寄存器


  LED8DIR = 0xFF;                //P6口输出模式

  LED8  = 0xFF;                  //先关闭所有LED

}

//**********************************************************************

// P1口中断服务程序,需要判断

//**********************************************************************

#pragma vector = PORT1_VECTOR

__interrupt void P1_IRQ(void)

{

  switch(P1IFG&0x0F)

  {

  case 0x01: key=0x01;P1IFG=0x00;state = 'D';break;    // 引脚0对应S1中断,必须手动清标志位,点亮D1D2

  case 0x02: key=0x02;P1IFG=0x00;state = 'N';break;    // 引脚1对应S2中断,必须手动清标志位,点亮D3D4

  case 0x04: key=0x03;P1IFG=0x00;break;    // 引脚2对应S3中断,必须手动清标志位,点亮D5D6

  case 0x08: key=0x04;P1IFG=0x00;break;    // 引脚3对应S4中断,必须手动清标志位,点亮D7D8

  }

}

//*************************************************************************

// 主程序

//*************************************************************************

void main(void)

{   

  WDT_Init();                            //看门狗设置

  Clock_Init();                          //系统时钟设置

  Port_init();                          //系统初始化,设置IO口属性

  delay_ms(100);                        //延时100ms

  _EINT();                              //使能中断

  while(1)

  {

    LED8DIR = 0xFF;                //P6口输出模式

    switch(state)

    {

      case 'D' :

          LED8 = 0xBF;//D7亮

          break;

      case 'N' :

          LED8 = 0x7F;//D8亮

          break;

    }



  }

}

5.实物效果图

按下key1,第7个灯亮

按下key2,第8个灯亮



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容