DYyanfa 2024-03-20 15:21 采纳率: 31.3%
浏览 2
已结题

按键长按IO口置高电平,持续按按键,LED会熄灭。

如下为长按按键2秒让io口翻转,点亮LED或熄灭LED的代码,长按按键2秒LED灯会亮,此时不松手继续按住按键,又经过大约2秒,LED灯会熄灭?我已经在程序中设计了if(KeySta != backup)的判断,不清楚为什么一直按着按键会熄灭,我想实现按着按键不松手,LED应该常亮,松手后再按2秒,LED熄灭。

-----------------------------------------------------------------------------------key.c------------------------------------------------------------------------
#define  _KEY_C

#include "Key.h"
#include "config.h"

bit KeySta = 1;
bit IsTiming = 0; 
sbit PWR_key_det = P3^2;
sbit PWR_HOLD = P1^5;
unsigned long KeyDownTime = 0; //记录按键按下时间

void ConfigTimer0();
void KeyDriver();
void KeyScan();

void  KeyDriver()
{    
    bit backup = 1;
    if(KeyDownTime > 0 && !IsTiming)
    {
        if(KeyDownTime >= 1000)
        {
            if(KeySta != backup)
            {
                _nop_();
                _nop_();
                PWR_HOLD = ~PWR_HOLD;  //按下按键2秒,PWR_HOLD状态取反
                IsTiming = 1;
                backup = KeySta;
            }
        }
    }
}

void KeyScan()  //按键扫描函数
{
    
    static unsigned char keybuf = 0xFF;
    keybuf = (keybuf <<1) |PWR_key_det;
    if(keybuf == 0x00)
    {
        KeySta = 0;
        KeyDownTime ++;//按键按下每次进入中断就加2
    }
    else if(keybuf == 0xFF)
    {
        KeySta = 1;
        KeyDownTime = 0;
    }
    else
    {}
}

void ConfigTimer0()
{
    AUXR &= 0x7F;   //2ms定时
    TMOD &= 0xF0;
    TH0 = 0xF8;     
    TL0 = 0xCD;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0
}

void TM0_Isr() interrupt 1
{
    KeyScan();
    if(IsTiming)
    {
        KeyDownTime = 0;
        IsTiming = 0;
    }
    TH0 = 0xF8;
    TL0 = 0xCD;
    TF0 = 0;    
}

#define  _MAIN_C

#include "main.h"
#include "Battery.h"
#include "Key.h"
#include "GPIO.h"
#include "config.h"
#include "Uart.h"
-----------------------------------------------------------------------------------main.c------------------------------------------------------------------------
void main()
{
    GPIO_Init();
    UartInit();   //串口初始化
    EA = 1;                 //打开总中断
    ES = 1;         //打开串口中断
    ConfigTimer0();  //定时2ms
    ConfigTimer1();  //定时2ms
    UartSendStr("Uart Test !\r\n");

    while (1)
    {
        KeyDriver(); //按键扫描
        BatCheck();//电池插入扫描
        if (rptr != wptr)  //读写指针不等,说明有数据需要发送
        {
           UartSend(buffer[rptr++]);
           rptr &= 0x0f;
        }
            
    }
}
  • 写回答

2条回答 默认 最新

  • 码农阿豪@新空间代码工作室 Java领域优质创作者 2024-03-20 15:22
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    问题描述: 长按按键2秒让io口翻转,点亮LED或熄灭LED的代码,长按按键2秒LED灯会亮,此时不松手继续按住按键,又经过大约2秒,LED灯会熄灭?已经在程序中设计了if(KeySta != backup)的判断,不清楚为什么一直按着按键会熄灭,想实现按着按键不松手,LED应该常亮,松手后再按2秒,LED熄灭。 问题分析: 根据代码中的描述,长按按键2秒会让IO口翻转,点亮或熄灭LED。在程序中有if(KeySta != backup)的判断,但仍然发生LED熄灭的情况,这可能是因为按键长按时间不够导致的。按键扫描函数中的KeyDownTime记录按键按下的时间,当KeyDownTime大于等于1000ms时,判断按键状态是否改变,如果改变则翻转IO口状态。根据描述,在长按按键2秒后,LED应该常亮,松手后再按2秒才会熄灭。但是在代码中只记录了一次按键按下的时间,当按键一直按着不松手时,KeyDownTime会一直累加,经过一段时间后会大于等于1000ms,导致LED熄灭。 解决方案: 为了实现按着按键不松手,LED常亮的效果,需要修改程序。可以在按键扫描函数中添加一个IsLongPress的标志,用于表示是否长按。当KeyDownTime大于等于2000ms时,将IsLongPress置为1。在KeyDriver函数中判断IsLongPress的值,如果为1,则翻转IO口状态,否则不做任何处理。这样即使按键一直按着不松手,LED也可以常亮。 以下是修改后的代码:
    bit IsLongPress = 0; // 是否长按
    void KeyScan() // 按键扫描函数
    {        
        static unsigned char keybuf = 0xFF;
        keybuf = (keybuf << 1) | PWR_key_det;
        if (keybuf == 0x00) // 检测到按键按下
        {
            KeySta = 0;
            KeyDownTime++; // 按键按下每次进入中断就加2
            if (KeyDownTime >= 2000) // 长按2秒
            {
                IsLongPress = 1;
                KeyDownTime = 0;
            } 
        }
        else if (keybuf == 0xFF) // 检测到按键弹起
        {
            KeySta = 1;
            KeyDownTime = 0;
            IsLongPress = 0; // 置为0,避免误判
        }
        else 
        {
            // do nothing
        }
    }
    void KeyDriver() // 按键驱动函数
    {      
        if (IsLongPress) // 长按
        {
            PWR_HOLD = ~PWR_HOLD; // 翻转IO口状态
            IsLongPress = 0; // 置为0,等待下一次长按
        }
    }
    

    这样即使按键一直按着不松手,LED也可以常亮。等待松手后再按2秒,LED才会熄灭。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月4日
  • 已采纳回答 3月27日
  • 创建了问题 3月20日

悬赏问题

  • ¥15 怎么把512还原为520格式
  • ¥15 MATLAB的动态模态分解出现错误,以CFX非定常模拟结果为快照
  • ¥15 求高通平台Softsim调试经验
  • ¥15 canal如何实现将mysql多张表(月表)采集入库到目标表中(一张表)?
  • ¥15 wpf ScrollViewer实现冻结左侧宽度w范围内的视图
  • ¥15 栅极驱动低侧烧毁MOSFET
  • ¥30 写segy数据时出错3
  • ¥100 linux下qt运行QCefView demo报错
  • ¥50 F1C100S下的红外解码IR_RX驱动问题
  • ¥20 基于matlab的航迹融合 航迹关联 航迹插补