6205|16

26

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

按键的下降沿和低电平的问题 [复制链接]

请教各位,按键原来是下降沿有效,但我想把按键改为低电平有效,应该怎么改呢,是把原来的下降沿中断去掉吗?

最新回复

又过了近两周,想问问楼主还有下文么?  详情 回复 发表于 2015-11-28 10:10
 
点赞 关注

回复
举报

503

帖子

1

TA的资源

一粒金砂(高级)

沙发
 
一般按键都有加消痘和松手检测的,所以用下降沿有效还是低电平有效 效果上看是没什么区别
你说的低电平有效是要实现按键长按效果吧,在松手检测里加计时和参数、界面修改
 
 

回复

1万

帖子

141

TA的资源

版主

板凳
 
那要看后级电路是什么,以及你要求低电平持续多长时间才动作。
 
个人签名上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

4
 
曾经in 发表于 2015-11-14 17:13
一般按键都有加消痘和松手检测的,所以用下降沿有效还是低电平有效 效果上看是没什么区别
你说的低电平有 ...

恩,就是实现长按键有效
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

5
 
chunyang 发表于 2015-11-14 21:39
那要看后级电路是什么,以及你要求低电平持续多长时间才动作。

我就是想按键是按下的状态时,P1.0端口输出高电平。按键松开的状态,P1.0输出电平

点评

看来是MCU了,那就是纯软件问题,多次查询判断状态即可。  详情 回复 发表于 2015-11-16 21:45
 
 
 

回复

503

帖子

1

TA的资源

一粒金砂(高级)

6
 
还是那句,松手检测
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

7
 
曾经in 发表于 2015-11-15 14:18
还是那句,松手检测

#include "MSP430G2553.h"

//-----在main函数前提前申明函数-----
void P1_IODect()        ;
void P13_Onclick();
void GPIO_init();

void main(void) {
        WDTCTL = WDTPW + WDTHOLD;        //关狗
        GPIO_init();                                                                                        //IO初始化
        _enable_interrupts();                                                        //使能总中断
        _bis_SR_register(LPM3_bits);                                //休眠
}
/******************************************************************************************************
* 名       称:GPIO_Init()
* 功       能:设定按键和LED控制IO的方向,启用按键IO的上拉电阻
* 入口参数:无
* 出口参数:无
* 说       明:无
* 范       例:无
******************************************************************************************************/
void GPIO_init()
{
        //-----设定P1.0和P1.6的输出初始值-----
        P1DIR |= BIT0+BIT6;                                //设定P1.0和P1.6为输出
        P1OUT |= BIT0;                                                //设定P1.0初值
        P1OUT &= ~BIT6;                                        //设定P1.6初值
        //-----配合机械按键,启用内部上拉电阻-----
        P1REN |= BIT3;                                        //启用P1.3内部上下拉电阻
        P1OUT |= BIT3;                                    //将电阻设置为上拉
        //-----配置P1.3中断参数-----
        P1DIR &= ~BIT3;                    // P1.3设为输入(可省略)
        P1IES |= BIT3;                          // P1.3设为下降沿中断
        P1IE  |= BIT3 ;                          // 允许P1.3中断
}
/******************************************************************************************************
* 名       称:PORT1_ISR()
* 功       能:响应P1口的外部中断服务
* 入口参数:无
* 出口参数:无
* 说       明:P1.0~P1.8共用了PORT1中断,所以在PORT1_ISR()中必须查询标志位P1IFG才能知道
*                                          具体是哪个IO引发了外部中断。P1IFG必须手动清除,否则将持续引发PORT1中断。
* 范       例:无
******************************************************************************************************/
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
        //-----启用Port1事件检测函数-----
        P1_IODect();                                                                //检测通过,则会调用事件处理函数
           P1IFG=0;                                                    //退出中断前必须手动清除IO口中断标志
}

/******************************************************************************************************
* 名       称:P1_IODect()
* 功       能:判断具体引发中断的IO,并调用相应IO的中断事件处理函数
* 入口参数:无
* 出口参数:无
* 说       明:该函数兼容所有8个IO的检测,请根据实际输入IO激活“检测代码”。
*                                          本例中,仅有P1.3被用作输入IO,所以其他7个IO的“检测代码”没有被“激活”。
* 范       例:无
******************************************************************************************************/
void P1_IODect()
{
        unsigned int Push_Key=0;
        //-----排除输出IO的干扰后,锁定唯一被触发的中断标志位-----
        Push_Key=P1IFG&(~P1DIR);
        //-----延时一段时间,避开机械抖动区域-----
        __delay_cycles(10000);                                                        //消抖延时
        //----判断按键状态是否与延时前一致-----
        if((P1IN&Push_Key)==0)                                 //如果该次按键确实有效
   {
         //----判断具体哪个IO被按下,调用该IO的事件处理函数-----
          switch(Push_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;
         default:                                                                        break;                //任何情况下均加上default
         }
   }
}
/******************************************************************************************************
* 名       称:P13_Onclick()
* 功       能:P1.3的中断事件处理函数,即当P1.3键被按下后,下一步干什么
* 入口参数:无
* 出口参数:无
* 说       明:使用事件处理函数的形式,可以增强代码的移植性和可读性
* 范       例:无
******************************************************************************************************/
void P13_Onclick()
{
        //-----翻转IO电平-----
        P1OUT ^= BIT0;
        P1OUT ^= BIT6;
        }
  
我没找到松手检测在哪可否指点指点
 
 
 

回复

503

帖子

1

TA的资源

一粒金砂(高级)

8
 
本帖最后由 曾经in 于 2015-11-16 00:02 编辑

看一下数据手册有没跳变沿中断(就是上升沿下降沿都产生中断)有的话按下面处理处理,
没有的话要么手动切换触发的边沿要么用while去卡(就是松手检测), 自己看看
void P1_IODect()
{        static unsigned int old_Push_Key=0;
        unsigned int Push_Key=0;
        //-----排除输出IO的干扰后,锁定唯一被触发的中断标志位-----
        Push_Key=P1IFG&(~P1DIR);
        //-----延时一段时间,避开机械抖动区域-----
        __delay_cycles(10000);                                                        //消抖延时
        //----判断按键状态是否与延时前一致-----
        if((P1IFG&(~P1DIR))==Push_Key)                                 //如果该次按键确实有效
   {
        switch(old_Push_Key^Push_Key)       //按键有变化
        {
         //----判断具体哪个IO有变化,调用该IO的事件处理函数-----
         case BIT3:         P13_Onclick(Push_Key&BIT3);                break;
         default:                                                                        break;                //任何情况下均加上default
         }
         old_Push_Key=Push_Key;
   }
}

void P13_Onclick(unsigned int key)
{
       if(key==0)
       {//按键松开
       }
       else
       {//按键按下
       }
}



点评

恩,好的,谢谢指导~  详情 回复 发表于 2015-11-16 21:57
 
 
 

回复

1万

帖子

141

TA的资源

版主

9
 
crysislove 发表于 2015-11-15 13:47
我就是想按键是按下的状态时,P1.0端口输出高电平。按键松开的状态,P1.0输出电平

看来是MCU了,那就是纯软件问题,多次查询判断状态即可。

点评

恩,谢谢指导  详情 回复 发表于 2015-11-16 21:58
 
个人签名上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

10
 
曾经in 发表于 2015-11-15 23:55
看一下数据手册有没跳变沿中断(就是上升沿下降沿都产生中断)有的话按下面处理处理,
没有的话要么手动切 ...

恩,好的,谢谢指导~
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

11
 
chunyang 发表于 2015-11-16 21:45
看来是MCU了,那就是纯软件问题,多次查询判断状态即可。

恩,谢谢指导
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

12
 
给三条建议:
第一,搞清楚什么叫低功耗模式,如何进入和退出低功耗模式,在低功耗模式下MCU会怎么工作
第二,别将按键检测全部放在外部中断里,尝试将部分检测工作放到主函数里去
第三,尝试使用定时器中断而不是__delay_cycles函数来处理延时的问题。

楼主先参照这三条建议修改一下代码,明后天再给楼主上参考代码
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

13
 
过了两天不见楼主重写程序,看样子楼主已经没有在做这个项目了,那么就不上参考代码了。

点评

首先感谢版主大大上心和认真啊,非常抱歉啊,这两天我一直在忙其他事,所以没有上论坛回复。然后下面是我对低功耗的认识和了解以及用定时器中断改写的代码请版主指导指导。下面这段代码我  详情 回复 发表于 2015-11-18 23:52
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

14
 
本帖最后由 crysislove 于 2015-11-19 00:12 编辑
qiushenghua 发表于 2015-11-18 16:59
过了两天不见楼主重写程序,看样子楼主已经没有在做这个项目了,那么就不上参考代码了。

首先感谢版主大大上心啊,非常抱歉啊,这两天我一直在忙其他事,所以没有上论坛回复。然后下面是我对低功耗的认识和了解以及用定时器中断改写的代码请版主指导指导。下面这段代码我想要实现的是:当P1.3按键按下不放的时候,P1.0 和P1.6保持亮的状态,当按键松开的时候两个的是灭的状态。代码编译没错,但是下载之后,没有实现上面的功能。

低功耗模式也叫休眠模式是一种间歇式工作方式。通过间歇性的方式来启动和停止系统时钟,就可以开启低功耗模式。
MSP430G2553的CPU有5种工作模式: AM(Active Mode)、LPM0(Low Power Mode 0)、LPM1、LPM2、LPM3。后四种为低功耗模式。有些程序中的CPUOFF也是休眠模式。
LMP0模式:CPU、MCLK停用,SMCLK,ACLK激活。
LMP1模式:CPU、MCLK、如果DCO(数控振荡器)不作为SMCLK源的时候停用,ACLK激活。
LMP2模式;CPU、MCLK、SMCLK、DCO停用。ACLK激活。
LMP3模式:CPU、MCLK、SMCLK、DCO停用。ACLK激活。(与LMP2模式不同的是LMP3模式SR寄存器的SCG0置1了)
LMP4模式:CPU、MCLK、SMCLK、DCO、ACLK停用。
常用的模式是LPM0、LPM3。如果想用LMP3模式,在主程序的最后调用内函数_bis_SR_register(LPM3_bits),如果是退出LMP3模式则调用内部函数_bic_SR_register_on_exit(LPM3_bits)。
代码如下:
#include "MSP430G2553.h"
void WDT_init();
void P1_IODect();
void P13_Onclick();

void main(void)
{
        WDTCTL = WDTPW + WDTHOLD;
        P1DIR |= BIT0+BIT6;
        P1OUT |= BIT0;
        P1OUT |= BIT6;

        P1REN |= BIT3;
        P1OUT |= BIT3;
        WDTCTL = WDT_ADLY_16;
        IE1 |= WDTIE;
        _enable_interrupts();
        _bis_SR_register(LPM3_bits);
                }

#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
P1_IODect();
}

void P1_IODect()
{
    unsigned char KEY_1=0;
        if(P1IN&BIT3) //如果BIT3的值为1,
                KEY_1=1;
        else KEY_1=0;
        while(KEY_1==0)
        P13_Onclick();
}

void P13_Onclick() //P1.3的事件处理函数
{
        P1OUT ^= BIT0;
        P1OUT ^= BIT6;
}

 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

15
 
本帖最后由 qiushenghua 于 2015-11-19 02:01 编辑

下面这个是刚刚在楼主程序基础上修改后的结果,读懂这段程序,大概就能理解MSP430的低功耗模式是怎么回事了。

  1. #include "MSP430G2553.h"
  2. void WDT_init();
  3. void P1_IODect();
  4. void P13_Short_Click();
  5. void P13_Long_Click();

  6. char count=0;                                      //用来统计按键按下的时间占据了多少个定时中断周期
  7. unsigned char KEY_STATE=0;                //定义一个变量储存按键状态
  8. unsigned char KEY_LAST_STATE=0;       //再定义一个变量储存上次检测到的按键状态


  9. void main(void)
  10. {
  11.         /*下面这几句是配置时钟源的,自己看着改*/
  12.         BCSCTL3 |= LFXT1S_2;                // 将VLO作为ACLK时钟源
  13.         WDTCTL = WDT_ADLY_16;          // 使用内部的16ms看门狗中断,不过这个时间是用32768晶振算出来的,实际中断周期为                                                                                // 16ms/12k*32k=44ms
  14.         IE1 |= WDTIE;                            // 使能看门狗周期性中断
  15.         BCSCTL1 = CALBC1_8MHZ;              // 配置CPU工作时钟MCLK=DCO_8MHZ
  16.         DCOCTL = CALDCO_8MHZ;


  17.         P1DIR |= BIT0+BIT6;
  18.         P1OUT |= BIT0;
  19.         P1OUT |= BIT6;

  20.         P1REN |= BIT3;
  21.         P1OUT |= BIT3;
  22.         
  23.         _enable_interrupts();        //使能总中断
  24.         while(1)                          //想想为什么要循环起来,和你之前的程序有什么不同
  25.         {
  26.                 P1_IODect();          //检测按键
  27.                 LPM3;                    //进入LPM3模式,相当方便的语句
  28.         }
  29. }

  30. #pragma vector=WDT_VECTOR
  31. __interrupt void WDT_ISR(void)
  32. {
  33.         LPM3_EXIT;                                //定时中断到来的时候唤醒CPU,退出LPM3也就是一条语句的事情
  34. }

  35. void P1_IODect()
  36. {
  37.         KEY_LAST_STATE=KEY_STATE;        //将键值存入上一状态laststate
  38.         KEY_STATE=!(P1IN&BIT3);              //读取按键键值,高为未按下,低为按下,因此对其取逻辑反,便于理解。
  39.                                                              //现在KEY_STATE为true表示按键按下,KEY_STATE为false表示按键未按下
  40.                                                              //实际上按键按下的时候KEY_STATE=BIT3,按键未按下为0。

  41.         if((!KEY_STATE)&&KEY_LAST_STATE)//如果当前状态为按键未按下,但是上一状态按键是按下的
  42.                                                              //说明按键弹起了。
  43.         {
  44.                 if(count<30)                           //如果按下到弹起小于30个周期也就是44ms*30=1.3s
  45.                         P13_Short_Click();           //处理短按程序
  46.                 count=0;
  47.         }

  48.         if(KEY_STATE)                       //当前按键如果是按下的
  49.         {
  50.                 count++;                      //不管那么多计数先加一

  51.                 if(count>100)
  52.                         count=100;           //避免count溢出,给其设置一个上限100
  53.         }
  54.         if(count==60)                        //如果按键按下44ms*60=2.6s
  55.                 P13_Long_Click();          //处理长按程序
  56.                                                     //注意这个长按的时钟是不准确的,具体怎么算长按怎么算短按自己调整

  57. }

  58. void P13_Short_Click()//短按翻转BIT0
  59. {
  60.         P1OUT ^= BIT0;
  61. //        P1OUT ^= BIT6;
  62. }

  63. void P13_Long_Click()//长按翻转BIT6
  64. {
  65. //        P1OUT ^= BIT0;
  66.         P1OUT ^= BIT6;
  67. }
复制代码
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

16
 
又过了近两周,想问问楼主还有下文么?

点评

一定有下文,楼主上两周忙着应付期末考试了这周才继续  详情 回复 发表于 2015-11-30 21:48
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

17
 
qiushenghua 发表于 2015-11-28 10:10
又过了近两周,想问问楼主还有下文么?

一定有下文,楼主上两周忙着应付期末考试了这周才继续
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表