GPIO接口及其外部中断的应用

一、实验目的

(1)掌握MSP430系列芯片结构、主要功能部件和片上外设;

(2)掌握MSP430系列CPU的结构特征和存储器结构、寻址总线和寻址方式;

(3)掌握MSP430系列16位CPU精简指令系统和C语言基础;

(4)掌握MSP430系列位操作运算与表达式;

(5)熟悉CCS编译环境及其基本操作、系统设计与调试的方法;

(6)掌握MSP430系列软件编程﹑单任务和多任务典型程序结构以及模块化程序设计方法。

二、实验内容

(1)利用软件循环查询方法编程实现:扩展板上的按键S1控制L1指示灯的亮灭,按键S2控制L2指示灯的亮灭,均为高电平点亮。要求按键被按下再松开一个来回后切换LED指示灯的亮灭状态。LED指示灯模块和机械按键模块的原理图如图2.1(a)和(b)所示。

注意:

①初始化GPIO接口的输出方式、输出模式和使能上下拉电阻功能;

②利用软件循环查询方法检测技键是否被按下。

③使用按键时会有抖动,按键抖动的时间一般为5ms~10ms。调用实验一中编写的软件延时函数void delayms (volatile unsigned int n),调试延时参数实现软件延时消抖功能。提示:①以S1技键为例:已知按键被按下P1.2=0,按键被松开P1.2=1

②查询S1按键是否技下的代码为:

if(!(P1IN&BIT2))或者if(P1IN&BIT2)==0)

(2)利用GPIO接口外部中断方式,设置下降沿触发外部中断编程实现上题功能。要求利用外部中断方式检测按键是否按下,并使用变量NUM统计中断次数。 

提示:

(1)以S1按键为例,利用IO外部中断判断S1按键是否按下的代码为: if(P1FG&BIT2);

(2)通过单步调试,观察并记录变量NUM数值的变化情况;

(3)分析并说明循环查询和外部中断方式分别在什么情况下使用更有效。

三、实验代码:

#include <msp430.h> 
/**
 * main.c
 */
void delay()
{
    volatile unsigned int i;
    for(i=1000;i>0;i--);
}
void main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	P8DIR |= BIT1;
	P1DIR &=~BIT2;
	P8OUT |= BIT1;
	P1REN |= BIT2;
	P1OUT |= BIT2;
	P3DIR |= BIT7;
	P3OUT |= BIT7;
	P2DIR &=~BIT6;
	P2REN |= BIT6;
	P2OUT |= BIT6;
	while(1)
	{
	    if(!(P1IN&BIT2))
	    {
	        delay();
	       if(P1IN & BIT2)
	       {
	           P8OUT ^=BIT1;
	       }
	    }

	    else if(!(P2IN&BIT6))
	            {
	                delay();
	               if(P2IN & BIT6)
	               {
	                   P3OUT ^= BIT7;
	               }
	            }
	  }
	return 0;
}

#include <msp430.h>
//按键控制LED
unsigned int num=0;
int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    /*初始化LED2为输出*/
    P3DIR |= BIT7;
    P8DIR |= BIT1;
    /*初始化LED2为低电平,熄灭*/
    P3OUT &= ~BIT7;
    P8OUT &= ~BIT1;
    /*初始化KEY P1.3为输入*/
    P1DIR &= ~BIT2;
    P1DIR &= ~BIT3;
    /*使能P1.3口的上拉电阻*/
    P1REN |= BIT2;
    P1OUT |= BIT2;
    P1REN |= BIT3;
    P1OUT |= BIT3;
    /*打开P1.3口的中断*/
        P1IE |= BIT2;
        P1IE |= BIT3;
        /*设定为下降沿触发*/
        P1IES |= BIT2;
        P1IES |= BIT3;
        /*清除中断标志位*/
        P1IFG &= ~BIT2;
        P1IFG &= ~BIT3;
        /*打开全局中断*/
        __bis_SR_register(GIE);
    while(1)
    {
    }
    return 0;
}
#pragma vector = PORT1_VECTOR
__interrupt void Port1_ISR(void)    //Port1_ISR(void)   中断服务函数
{
       if(!(P1IN & BIT2)) /*如果P1.3口为高电平,证明按键没有被按下*/
        {__delay_cycles(500);
        if(P1IN & BIT2)
            {P8OUT ^= BIT1;//翻转LED2
            num++;
            P1IFG  &= ~ BIT2;   //清除标志位
            }
        }
       else if(!(P1IN & BIT3)) /*如果P1.3口为高电平,证明按键没有被按下*/
                {  __delay_cycles(500);
                    if(P1IN & BIT3)
                        {P3OUT ^= BIT7;//熄灭LED2
                        num++;
                         P1IFG  &= ~ BIT3;   //清除标志位
                        }
                }
}/*
#pragma vector = PORT2_VECTOR
__interrupt void Port2_ISR(void)    //Port1_ISR(void)   中断服务函数
{
        if(!(P2IN & BIT1)) //如果P1.3口为高电平,证明按键没有被按下
           {  __delay_cycles(500);
               if(P2IN & BIT1)
                   {P8OUT ^= BIT1;//熄灭LED2
                   num++;
                    P2IFG  &= ~ BIT1;   //清除标志位
                   }
           }
}*/

四、问题讨论

1.叙述MSP430F5529的工作模式,以及如何在低功耗模式下转到活动模式﹖

工作模式:

①改变工作模式会立即生效;

②发生中断时,当前的模式设置信息会被保存,以便恢复(除非中断服务程序中改变了工作模式);

③处于LPM4.5模式时,PMM的电源监管不会生效,所有的RAM和寄存器都会丢失,但是I/O口状态会锁定;

退出低功耗模式如下:

LPM0_EXIT; //退出低功耗模式0

LPM4_EXIT; //退出低功耗模式4

LPM0:CPU停止工作,MCLK时钟停止,SMCLK、ACLK时钟还在工作。

LPM1:CPU停止工作,MCLK时钟停止,在活动模式如果DCO没有作为MCLK和SMCLK时钟时,则直流发生器被禁止,否则就保持活动状态,SMCLK、ACLK时钟依然还在工作。

LPM2:CPU停止工作,MCLK、SMCLK时钟停止工作,如果DCO没有作为MCLK、SMCLK,自动被禁止直流发生器保持有效,ACLK还处于工作中。

LPM3:CPU停止工作,MCLK、SMCLK时钟停止工作,DCO时钟也停止工作,仅ACLK时钟还处于工作状态。

LPM4:CPU停止工作,MCLK、SMCLK时钟停止工作,DCO时钟也停止工作,ACLK也停止工作。此时功耗最低。

  一般情况下,处理器进入低功耗模式后,由中断来唤醒,外部中断或内部中断。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
出现按一次键而LED灯闪一次或多次的情况通常是由于按键产生的毛刺或抖动引起的。在按键被按下或松开的瞬间,因为机械开关的反弹,可能会产生一些非常短暂的高低电平跳变,导致单片机检测到多个按键事件。 为了解决这个问题,可以在程序中添加一些处理按键抖动的代码。一种常用的方法是使用延时消抖法,即在检测到按键按下或松开后,延时一段时间再进行下一次检测,如果在这段时间内检测到按键状态没有发生改变,则认为按键已经稳定按下或松开。另外还可以使用软件消抖法或硬件消抖法,根据具体情况选择合适的方法。 具体实现方法可以参考以下代码: ``` // 定义按键IO口和LED灯IO口 #define KEY_PIN P2_0 #define LED_PIN P1_0 // 延时消抖法处理按键 void key_scan(void) { static uint8_t key_state = 0; // 按键状态:0-未按下,1-按下 static uint8_t key_press = 0; // 按键按下标志:0-未按下,1-按下 static uint16_t key_count = 0; // 按键计数器 // 检测按键电平 if (KEY_PIN == 0) { key_count++; if (key_count >= 20) { key_count = 20; if (key_state == 0) { key_state = 1; key_press = 1; LED_PIN = !LED_PIN; // 点亮或熄灭LED灯 } } } else { key_count = 0; if (key_state == 1) { key_state = 0; } } } ``` 以上代码是基于STC89C52单片机的Keil C语言代码,实现了延时消抖法处理按键的功能。在程序中,通过一个静态变量记录当前按键的状态,并使用一个计数器来记录按键电平持续的时间。当检测到按键电平为低电平时,计数器加1,如果计数器的值达到一定阈值(20次),则认为按键已经稳定按下,更新按键状态并设置按键按下标志。同时,在按键按下时翻转LED灯的状态。在检测到按键电平为高电平时,重置计数器并更新按键状态。 综上所述,使用延时消抖法可以有效处理按键产生的毛刺、抖动现象,并确保按键事件的正确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值