找回密码
 立即注册
查看: 40|回复: 2

8H1K08 初始化了按键引脚电平 按键连接引脚对地 长按之后 松开结果按键引脚 | 已解决

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-08-05 11:06:16
已绑定手机

2

主题

4

回帖

30

积分

新手上路

积分
30
发表于 6 天前 | 显示全部楼层 |阅读模式
这是代码     按键长按 进入状态3  代码明明没有把按键拉低赋值的操作   为什么按键松开之后  按键还是低电平    我尝试过镊子短接代替按键  拿开镊子后自己变成了低电平    这种异常现象 只有长按才会出现  包括镊子短接也是需要一定时间   准双向和推挽都试过还是这样  最后还是在状态3里面加了一个拉高操作  才解决这个问题   但是不知道具体原因    代码也初始化了按键引脚高电平 并且没有拉低操作的代码

#include <STC8H.h>
#include "choosegrade.h"
#include "adc.h"
#include <intrins.h>
#include "print.h"
#include "ntc.h"
#include "ledflicker.h"
#include "pwm.h"
#include "pid.h"
#define LED  P35
#define key_down P32
#define FAN P13
#define targettemp 10.0f
// 全局变量定义
unsigned char xdata key_state = 0;      // 按键状态:0-空闲,1-按下消抖,2-按下稳定,3-释放消抖
unsigned int xdata press_time = 0;      // 按下时间计数(20ms/单位)
unsigned char xdata click_count = 0;    // 单击次数计数
unsigned int xdata click_delay = 0;     // 双击延迟计数
char xdata off = 0;
int xdata key=0;            // 长按标志
float xdata l_temp=0;
float xdata r_temp=0;
char xdata v=0;
float xdata vin;
char xdata grade=0;
char xdata tc=0;
char xdata gradeChage=0;

void temp();

static void Delay1ms(unsigned int t)    //@24.000MHz
{
    while (t--)
    {
            unsigned char data i, j;

    i = 24;
    j = 85;
    do
    {
        while (--j);
    } while (--i);
    }


}



void Timer0_Isr(void) interrupt 1
{


    // 按键状态机
    switch(key_state)
    {
        case 0:  // 空闲状态
            if(!key_down)  // 检测到按键按下(低电平)
            {
                key_state = 1;  // 进入按下消抖状态
                press_time = 0; // 重置按下时间
            }
            break;

        case 1:  // 按下消抖状态
            if(!key_down)  // 连续20ms检测到按下
            {
                key_state = 2;  // 进入按下稳定状态
                press_time = 1; // 开始计时
            }
            else
            {
                key_state = 0;  // 抖动干扰,返回空闲状态

            }
            break;

        case 2:  // 按下稳定状态
            if(key_down)  // 检测到按键释放(高电平)
            {
                key_state = 3;  // 进入释放消抖状态
            }
            else
            {
                press_time++;  // 持续按下,累加时间
                if(press_time >= 50)  // 长按检测(50*20ms=1000ms)
                {
                    key = 3;   // 标记长按事件

                    key_state = 0;    // 返回空闲状态
                    click_count = 0;  // 重置单击计数

                }
            }
            break;

        case 3:  // 释放消抖状态
            if(key_down)  // 连续20ms检测到释放
            {
                if((press_time < 40))  // 短按(非长按)
                {
                    click_count++;  // 单击计数+1

                    if(click_count == 1)
                    {
                        click_delay = 0;  // 开始双击计时
                    }
                    else if(click_count == 2)
                    {
                        key = 2;  // 标记双击事件
                        click_count = 0;   // 重置单击计数

                    }

                }

                key_state = 0;  // 返回空闲状态
            }
            else
            {
                key_state = 2;  // 释放抖动,返回按下稳定状态
            }
            break;
    }

    // 双击超时检测
    if(click_count == 1)
    {
        click_delay++;
        if(click_delay >= 15)  // 双击超时(15*20ms=300ms)
        {
            key = 1;  // 标记单击事件
                tc = 0;//温控标志
            click_count = 0;   // 重置单击计数



        }
    }

    print("key:%d\r\n",key);
}
// void Timer2_Isr(void) interrupt 12
// {

//      x--;
//  if (x==0)
//  {
//      x=5;
//      gradeChage=0;
//      AUXR &= ~0x10;          //定时器2关闭计时
//      T2L = 0xFC;             //设置定时初始值
//      T2H = 0x03;             //设置定时初始值
//  }

// }

// void Timer2_Init(void)       //1秒@24.000MHz
// {
//  TM2PS = 0x1E;           //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
//  AUXR &= 0xFB;           //定时器时钟12T模式
//  T2L = 0xFC;             //设置定时初始值
//  T2H = 0x03;             //设置定时初始值
//  AUXR |= 0x10;           //定时器2开始计时
//  IE2 |= 0x04;            //使能定时器2中断
// }
void Uart1_Init(void)   //115200bps@24.000MHz
{
    SCON = 0x50;        //8位数据,可变波特率
    AUXR |= 0x40;       //定时器时钟1T模式
    AUXR &= 0xFE;       //串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;       //设置定时器模式
    TL1 = 0xCC;         //设置定时初始值
    TH1 = 0xFF;         //设置定时初始值
    ET1 = 0;            //禁止定时器中断
    TR1 = 1;            //定时器1开始计时
    ES = 1;             //使能串口1中断
    // EA = 1;              //使能总中断
}
//定时器0
void Timer0_Init(void)      //20毫秒@24.000MHz   按键扫描
{
    TM0PS = 0x00;           //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
    AUXR &= 0x7F;           //定时器时钟12T模式
    TMOD &= 0xF0;           //设置定时器模式
    TL0 = 0xC0;             //设置定时初始值
    TH0 = 0x63;             //设置定时初始值
    TF0 = 0;                //清除TF0标志
    TR0 = 1;                //定时器0开始计时
    ET0 = 1;                //使能定时器0中断
    EA = 1;             //使能总中断
}


void temp()
{   float vl;
    vl=adc('l',3.3);
     l_temp=ntc((vl)/((3.3-vl)/10000.0f));

    vl=adc('r',3.3);
     r_temp=ntc((vl)/((3.3-vl)/10000.0f));


}
void voltage()
{
    float x;
    // float vin;
    x=adc('v',3.3);

     vin=13000.0f*(x/3000.0f);
     if (vin>10 && vin < 14)
     {
        v = 1;
     }
     else{

         v = 0;
     }



}
// void tempControl()
// {
//  /*每次档位变换需要留一定的时间做观察 直到温度完全到达上限并且占空比到达100%再开始判断*/
//  if (((targettemp-(l_temp))<-5) && output ==100.0f && gradeChage==0)//欠调判断
//  {
//      if (grade == 1)
//      {
//          grade = 2;
//          gradeChage = 1;

//          AUXR |= 0x10;           //定时器2开始计时
//      }
//      else if(grade == 2)
//      {

//          grade = 3;
//          gradeChage = 1;
//          AUXR |= 0x10;           //定时器2开始计时

//      }
//      else if(grade ==3)
//      {

//          gradeChage = 1;
//          AUXR |= 0x10;           //定时器2开始计时

//      }
//      choosegrade(grade);
//      pwm(100);

//  }
    // else if (((targettemp-(l_temp))>5) && output == 30.0f)//超调判断
    // {
    //  if (grade == 1)
    //  {
    //      gradeChage = 1;
    //      AUXR |= 0x10;           //定时器2开始计时
    //  }
    //  else if(grade == 2)
    //  {

    //      grade = 1;
    //      gradeChage = 1;
    //      AUXR |= 0x10;           //定时器2开始计时

    //  }
    //  else if(grade ==3)
    //  {
    //      grade = 2;
    //      gradeChage = 1;
    //      AUXR |= 0x10;           //定时器2开始计时

    //  }
    //  choosegrade(grade);

    // }
    // if(gradeChage ==1 ) {

    //  PID_Control(targettemp,l_temp);

    // }



// print("占空比:%f",output);
// print("冷端温度:%f",l_temp);
// print("targettemp-l_temp=%f",targettemp-(l_temp));



// }
void wdtInit()
{
WDT_CONTR = 0X27;
}

void main()
{

     P_SW2 = 0x80;

    P1M0 = (P1M0 & ~0x13) | 0xc8; P1M1 = (P1M1 & ~0x18) | 0xc3;
    P3M0 = (P3M0 & ~0x47) | 0x30; P3M1 = (P3M1 & ~0x37) | 0x40;
    P5M0 |= 0x10; P5M1 |= 0x10; //开漏



    key_down = 1;
    LED =0;
    pwmInit();
    Timer0_Init();
    Uart1_Init();
    // Delay1ms(100);//等待电压稳定进行判定
    // voltage();
    //
    pwm(0);
    FAN =1;
    choosegrade(1);
    wdtInit();
    while(1)
    {

        if (tc!=1)//温控
        {
            switch (key)
        {
        case 1:
            WDT_CONTR = 0X27;
            pwm(100);
            FAN =0;
            tc = 0;//温控标志
            grade+=1;
            if (grade>=4)
                grade=1;
            choosegrade( grade);
            // ledflicker(grade,300);
            key = 0;//重按键

            print("状态:%s", "单击");

            break;
        case 2:
            WDT_CONTR = 0X27;
            tc = 1;//温控标志
            ledflicker(10,150);
            key = 0;//重按键
            grade = 3;
            choosegrade(grade);
            //  grade-=1;
            //  if (grade==0)
            //  grade=1;
            // choosegrade( grade);
            key = 0;//清除按键状态
            print("状态:%s", "双击");

            break;
        case 3:

            EA = 0;
            TL0 = 0xC0;             //设置定时初始值
            TH0 = 0x63;             //设置定时初始值
            TF0 = 0;                //清除TF0标志
            TR0 = 0;                //关闭计时  

            key_state = 0;      // 按键状态:0-空闲,1-按下消抖,2-按下稳定,3-释放消抖
            press_time = 0;      // 按下时间计数(20ms/单位)
            click_count = 0;    // 单击次数计数
            click_delay = 0;     // 双击延迟计数   

            /*全部重置 ,因为长按判断是直接返回空闲 中断响应结束后  
            这个时候按键可能没有释放,进入了按键稳定状态判断,
            这个时候关闭中断  但是没有重置所有参数为初值
            那么中断再开之后就会续上之前的状态执行
             然后现在按键是已经释放了  刚好被识别为一个单击从而误触,简答来说就是残留状态的影响 加上中断重开后按键释放 刚好组成了一个完整的单击状态*/

            grade = 1;
            choosegrade(grade);
            key = 0;
            pwm(0);
            LED = 0;
            WDT_CONTR=0X00;//关闭看门狗
            // key_down = 1;
            while(!key_down);
            Delay1ms(1000);//长按松手消抖
            EA = 1;//消抖完才允许中断扫描  避免长按释放误识别为单击的情况
            TR0 = 1;//启动定时器
            break;



        }
        }
        else{
            temp();
            PID_Control(targettemp,l_temp);
            if (key==1 || key == 3)  
            {
            tc = 0;//温控标志
            }

        }





        temp();
            if ( r_temp>55.0f)//进入过热保护
            {
                grade = 1;
                choosegrade(grade);
                pwm(0);//关闭制冷
                FAN =1;
                LED = 0;//关闭LED显示
                while(!(r_temp<45))//等待温度冷却,才可以退出死循环 重新操控
                {

                    temp();
                    Delay1ms(500);
                }

            }   


        print("正常循环%s\r\n");
        WDT_CONTR = 0X37;//看门狗清零
      Delay1ms(20);
    //   print("冷端温度:%f", l_temp);
    //   print("热端温度:%f", r_temp);
    //   print("电压:%f", vin);
    //   print("档位:%d", grade);


    //    if (v==0)
    //    {
    //   ledflicker(1,1000);
    //    }


    }


}


回复

使用道具 举报 送花

3

主题

2076

回帖

1000

积分

等待验证会员

积分
1000
发表于 6 天前 | 显示全部楼层
尊敬的用户:

您好,感谢您对我们产品的关注与反馈。针对您提到的STC8H1K08按键引脚在长按后松开仍保持低电平的问题,我们已认真分析了您的代码和描述,并结合芯片特性进行排查。

首先,从您的描述来看,按键连接方式为“对地”,即按键一端接GND,另一端接MCU的IO口。正常情况下,若未按下按键,该引脚应为高电平;按下时拉低至低电平。但您指出,在长按之后松开,引脚依然保持低电平,且在状态3中加入拉高操作后问题得以解决。

一、可能原因分析

1. 引脚配置异常  
   虽然您提到已经初始化为高电平,但在某些情况下,如果引脚被错误配置为输入模式(而非输出),或者存在上拉/下拉设置不当,可能导致引脚状态不稳定。请确认以下几点:
是否将按键引脚配置为“准双向”或“推挽”模式?
是否开启了内部上拉电阻?(部分型号默认开启)
是否存在其他模块或中断影响了该引脚状态?

2. 长时间按键导致寄存器状态未复位  
   在状态3中,若存在某些寄存器或标志位未正确复位,可能会导致引脚状态被意外修改。例如:
若使用了ADC或其他外设,可能在长按期间触发了某些中断或状态变更。
若未正确释放按键检测逻辑,可能使系统误认为按键仍然处于按下状态。

3. 硬件干扰或信号毛刺  
   长按过程中,若存在外部干扰或信号毛刺,可能导致MCU误判。建议检查:
按键是否接触不良或有漏电现象?
PCB布局是否合理,是否存在高频噪声干扰?
是否在按键引脚并联了去耦电容以滤除毛刺?

4. 代码逻辑未完全清除状态  
   您提到在状态3中添加了拉高操作才解决问题,这表明状态3中的某些逻辑可能未正确恢复初始状态。建议检查:
状态切换逻辑是否完整?
是否存在未重置的变量或标志位?
是否在退出状态3时重新配置了引脚模式和电平?

二、建议解决方案

1. 明确引脚配置  
   在初始化阶段,确保按键引脚配置为“准双向”或“推挽”模式,并关闭内部上拉/下拉(如需)。可参考如下代码片段:

  
  1. c
  2.    P1M1 = 0x00;    // 设置为准双向
  3.    P1M2 = 0xFF;
  4.    P1 = 0xFF;      // 初始设为高电平
复制代码

2. 完善状态切换逻辑  
   在状态3中,除了拉高操作外,还应确保:
引脚模式恢复为输入;
相关标志位清零;
任何可能影响引脚状态的外设功能关闭。

3. 增加防抖与去噪机制  
   即使是长按,也建议在检测逻辑中加入防抖处理,防止因毛刺或误触导致状态异常。例如:

  
  1. c
  2.    if (keystate == LOW) {
  3.        Delayms(20);        // 延时消抖
  4.        if (keystate == LOW) {
  5.            // 进入状态3
  6.        }
  7.    }
复制代码

4. 测试与调试建议  
使用示波器观察按键引脚在长按后的实际电平变化;
在状态3中加入调试输出,确认引脚状态是否被意外修改;
尝试更换其他引脚测试,排除硬件故障可能。

三、总结

综上所述,该问题可能由引脚配置不准确、状态逻辑未完全恢复、或外部干扰等因素引起。建议您从以上几个方面逐一排查,并根据实际测试结果调整代码逻辑。若您愿意提供更详细的代码或电路图,我们将进一步协助定位问题根源。

如您有其他技术疑问,欢迎随时联系国芯人工智能技术支持团队,我们将竭诚为您服务。

此致  
敬礼!

国芯人工智能技术支持团队  
2025年4月

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-08-05 11:06:16
已绑定手机

2

主题

4

回帖

30

积分

新手上路

积分
30
发表于 6 天前 | 显示全部楼层
国芯人*** 发表于 2025-8-5 11:38
尊敬的用户:

您好,感谢您对我们产品的关注与反馈。针对您提到的STC8H1K08按键引脚在长按后松开仍保持低 ...

感谢你的回复  ,我已经找到原因了 是led 闪光操作使用的读改写操作   导致按键按压时的低电平 在闪光的寄存器读改写操作 被读模式读取  然后被写入了全局寄存器中 这样导致了按键一直低电平的情况   SAFE_SET_P3(x, val) (P3 = (P3 & ~(1<<(x))) | ((val)<<(x)))  
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-8-11 13:19 , Processed in 0.117113 second(s), 58 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表