MSP430 DM430-A开发板学习笔记IO中断方式来实现按键检测

Posted 唯心主义者ww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MSP430 DM430-A开发板学习笔记IO中断方式来实现按键检测相关的知识,希望对你有一定的参考价值。

MSP430 DM430-A开发板学习笔记(五)IO中断方式来实现按键检测

1.按键说明

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

按键P1口
key1P1.0
key2P1.1
key3P1.2
key4P1.3

2.中断流程图

中断流程图如下,在用C语言实现我们想要的功能的时候,我们可能需要使用switch、if语句对某些变量进行多次判别,这样会加长我们的代码并且不易观看,使用外部中断的好处就是:
1.可以在中断服务程序中对变量的值进行修改,从而达到随时更改变量值的目的
2.对一些变量可以进行单独控制,减少主程序代码的长度

Created with Raphaël 2.2.0 开始 主函数main 是否没有中断请求 继续执行主程序 结束 处理中断服务程序 yes no

在这里插入图片描述

3.中断配置

我们要开启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’

4.完整代码

该代码有两部分,一个是配置文件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个灯亮
在这里插入图片描述

在这里插入图片描述

以上是关于MSP430 DM430-A开发板学习笔记IO中断方式来实现按键检测的主要内容,如果未能解决你的问题,请参考以下文章

MSP430 DM430-A开发板学习笔记IO中断方式来实现按键检测

MSP430 DM430-A开发板学习笔记MSP430f149与hc06蓝牙模块的使用

MSP430 DM430-A开发板学习笔记MSP430f149使用4针0.96 OLED屏幕

MSP430 DM430-A开发板学习笔记MSP430f149使用4针0.96 OLED屏幕

MSP430 DM430-A开发板学习笔记IAR软件的使用

MSP430 DM430-A开发板学习笔记测速模块(计数传对射感器)的使用