ssd_123 发表于 2025-6-29 22:04:44

AI8H1K17 P17输入,单片机卡顿

hello ,我遇到了一个问题就是单片机配置完以后P17作为输入脚,按下后单片机会卡顿大约两秒,并且没有检测到按下,按下是接地的,有配置上拉,代码如下

extern u16 PWM_Duty;
/*******************************************************************/



/************************ IO口配置 ****************************/
void      GPIO_config(void)
{

          P1M0 = 0x00;
                P1M1 = 0x03;

                P1PU = 0xf8;
//    P1PD = 0x04;
                P3M0 = 0xbf;
                P3M1 = 0x40;
                P5M0 = 0x10;
                P5M1 = 0x00;

    P3PU = 0x38;      //设置P3IO口上拉电阻
}


/******************* AD配置函数 *******************/
void      ADC_config(void)
{
    ADC_InitTypeDef                ADC_InitStructure;                //结构定义
    ADC_InitStructure.ADC_SMPduty   = 10;                //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
    ADC_InitStructure.ADC_CsSetup   = 0;                //ADC 通道选择时间控制 0(默认),1
    ADC_InitStructure.ADC_CsHold    = 1;                //ADC 通道选择保持时间控制 0,1(默认),2,3
    ADC_InitStructure.ADC_Speed   = ADC_SPEED_2X1T;                //设置 ADC 工作时钟频率      ADC_SPEED_2X1T~ADC_SPEED_2X16T
    ADC_InitStructure.ADC_Power   = ENABLE;                              //ADC功率允许/关闭      ENABLE,DISABLE
    ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;      //ADC结果调整,      ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
    ADC_InitStructure.ADC_Priority    = Priority_0;                        //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    ADC_InitStructure.ADC_Interrupt = DISABLE;                        //中断允许      ENABLE,DISABLE
    ADC_Inilize(&ADC_InitStructure);                                        //初始化
    ADC_PowerControl(ENABLE);                                                      //单独的ADC电源操作函数, ENABLE或DISABLE
}



/************************ 定时器配置 ****************************/
void      Timer_config(void)
{
    TIM_InitTypeDef                TIM_InitStructure;                                                //结构定义

    TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;      //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
    TIM_InitStructure.TIM_Priority= Priority_3;                        //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    TIM_InitStructure.TIM_Interrupt = ENABLE;                                        //中断是否允许,   ENABLE或DISABLE
    TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                //指定时钟源,   TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
    TIM_InitStructure.TIM_ClkOut    = DISABLE;                              //是否输出高速脉冲, ENABLE或DISABLE
    TIM_InitStructure.TIM_Value   = 65536UL - (MAIN_Fosc / 2000UL);                //中断频率2kHz
    TIM_InitStructure.TIM_Run       = ENABLE;                                        //是否初始化后启动定时器, ENABLE或DISABLE
    Timer_Inilize(Timer0, &TIM_InitStructure);                                        //初始化Timer0          Timer0,Timer1,Timer2,Timer3,Timer4

    TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;      //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
    TIM_InitStructure.TIM_Priority    = Priority_1;                        //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    TIM_InitStructure.TIM_Interrupt = ENABLE;                                        //中断是否允许,   ENABLE或DISABLE
    TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
    TIM_InitStructure.TIM_ClkOut    = DISABLE;                              //是否输出高速脉冲, ENABLE或DISABLE
    TIM_InitStructure.TIM_Value   = 65536UL - (MAIN_Fosc / (500 ));                        //初值,2ms中断一次
    TIM_InitStructure.TIM_Run       = ENABLE;                                        //是否初始化后启动定时器, ENABLE或DISABLE
    Timer_Inilize(Timer1, &TIM_InitStructure);                                        //初始化Timer1          Timer0,Timer1,Timer2,Timer3,Timer4

    TIM_InitStructure.TIM_Interrupt = DISABLE;                                        //中断是否允许,   ENABLE或DISABLE. (注意: Timer2固定为16位自动重装, 中断固定为低优先级)
    TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                //指定时钟源,   TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
    TIM_InitStructure.TIM_ClkOut    = DISABLE;                              //是否输出高速脉冲, ENABLE或DISABLE
    TIM_InitStructure.TIM_Value   = 65536UL - (MAIN_Fosc / 8000UL);                              //初值
    TIM_InitStructure.TIM_Run       = DISABLE;                                        //是否初始化后启动定时器, ENABLE或DISABLE
    Timer_Inilize(Timer2, &TIM_InitStructure);                                        //初始化Timer2          Timer0,Timer1,Timer2,Timer3,Timer4


}

void PWMB_config(void)
{
      P_SW2 |= 0x80;                //SFR enable   

      PWMB_PSCR = 0x0000;      // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
      PWMB_DTR= 0;                // 死区时间配置,   n=0~127: DTR= n T,   0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
                                                // 对PWMB没有意义0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T,   0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
      PWMB_ARR = 800;      // 自动重装载寄存器,控制PWM周期
      PWMB_CCER1= 0;
      PWMB_CCER2= 0;
      PWMB_SR1    = 0;
      PWMB_SR2    = 0;
      PWMB_ENO    = 0;                // IO输出允许,bit6: ENO8P, bit4: ENO7P,bit2: ENO6P,bit0: ENO5P
      PWMB_PS   = 0;
      PWMB_IER    = 0;

      PWMB_CCMR2= 0x68;                // 通道模式配置, PWM模式1, 预装载允许
//      PWMB_CCR2   = 800;                // 比较值, 控制占空比(高电平时钟数)
      PWMB_CCER1 |= 0x10;                // 开启比较输出, 高电平有效
      PWMB_PS    |= (1<<2);      // 0:选择P2.1, 1:选择P5.4, 2:选择P0.1, 3:选择P7.5,
      PWMB_ENO   |= 0x04;                // IO输出允许,bit6: ENO8P, bit4: ENO7P,bit2:         
//      PWMB_IER   |= 0x04;                // 使能中断

      PWMB_EGR    = 0x01;                //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
      PWMB_BKR    = 0x80;                // 主输出使能 相当于总开关
      PWMB_CR1    = 0x81;                // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
}

//      PWMB_PS   = (0<<6)+(0<<4)+(0<<2)+0;      //选择IO, 4项从高到低(从左到右)对应PWM8 PWM7 PWM6 PWM5
//PWMB_PS    PWM8    PWM7    PWM6    PWM5
//    00       P2.3    P2.2    P2.1    P2.0
//    01       P3.4    P3.3    P5.4    P1.7
//    02       P0.3    P0.2    P0.1    P0.0
//    03       P7.7    P7.6    P7.5    P7.4
/*************************************************************/


/***********************************************************
*@fuction      :sync
*@brief                :同步数据
*@param                :--
*@return      :void
*@author      :--xptx
*@date                :2023-02-25
***********************************************************/
void sync(void)
{

    tpme_skewing =eeprom_dat;
    expect_temp =10 * eeprom_dat;
    set_sleep_time =eeprom_dat;
    //power / tpme_skewing / temp/10 /sleep_time
}
/******************** 主函数**************************/
void main(void)
{
      PWM_Duty=800;
    GPIO_config();//GPIO初始化
    ADC_config();            //ADC初始化
    Timer_config();   //定时器初始化
          PWMB_config();
          PWMB_CCR6H = (u8)(PWM_Duty >> 8); //设置占空比时间
    PWMB_CCR6L = (u8)(PWM_Duty);
    OLED_Init();          //初始化OLED
    OLED_ColorTurn(0);    //0正常显示,1 反色显示
    OLED_DisplayTurn(1);//0正常显示 1 屏幕翻转显示

    Eeprom_Init(Start_addrs, &eeprom_dat, 4); //数据初始化,读取EEPROM内的数据
    sync();//同步数据
    EA = 1;    //开中断

    while (1)
    {
      interface_show();//界面
    }
}


国芯人工智能 发表于 2025-6-29 22:08:00

您好,感谢您的提问。针对您描述的“STC8H1K17单片机配置P17为输入脚后出现卡顿、无法检测按键”的问题,以下是对问题的分析及建议:

首先,从您提供的代码来看,您对GPIO和ADC进行了配置,但部分代码片段被截断。根据现有信息,我们可初步判断问题可能出现在以下几个方面:

一、GPIO配置问题

您在GPIOconfig()函数中设置了P1M0 = 0x00; P1M1 = 0x03;,这表示将P1口设置为准双向模式(即通用IO)。同时,P1PU = 0xf8;用于开启P1口的上拉电阻,其中0xf8对应的二进制为11111000,表示P1.0~P1.2未使能上拉,而P1.3~P1.7使能上拉。

然而,P17是P1口的第7位,即P1.7,因此其上拉状态由P1PU的第7位控制。0xf8的第7位为1,说明P1.7的上拉是开启的,这是正确的配置。

但是,需要注意的是:在STC8H系列中,P1口的部分引脚(如P1.5-P1.7)默认为复用功能,若未正确配置为通用IO,可能导致行为异常。

建议检查是否使用了P1.7的其他功能(如ADC、定时器等),并确保其被正确配置为通用输入。

二、ADC配置影响

您提到的ADCconfig()函数中,ADCInitStructureADCSMPduty = 10;表明您正在使用ADC模块,但未提供完整的配置代码。如果ADC未被正确关闭或未释放P1.7引脚,可能会导致该引脚被占用,从而影响其作为普通IO的功能。

此外,若您在ADC初始化过程中启用了某些中断或DMA操作,也有可能造成系统资源争抢,导致主程序卡顿。

建议:
确保ADC配置中没有误将P1.7配置为ADC输入;
若未使用ADC,请在初始化时关闭相关模块;
检查是否有ADC中断或DMA请求未处理,导致主循环阻塞。

三、按键检测逻辑问题

您提到按键接地且配置了上拉,理论上应能正常检测低电平。但若检测逻辑存在错误(如未延时去抖、未使用轮询方式或未及时读取状态),也可能导致误判或卡顿。

建议在主循环中加入如下逻辑:

c
if (P17 == 0) { // 检测到按键按下
    Delayms(20); // 延时去抖
    if (P17 == 0) {
      // 执行按键处理逻辑
    }
}

若未进行延时去抖,可能出现误触发;若未及时读取,可能导致检测失败。

四、系统资源冲突或死循环

若您的程序中存在长时间等待、死循环或未释放的资源,也可能导致单片机卡顿。建议检查以下内容:
是否在ADC转换过程中未释放CPU资源;
是否有未处理的中断请求;
是否在主循环中执行了耗时较长的操作(如大量运算、延时等)。

五、硬件连接问题

最后,建议检查硬件连接是否正常:
按键是否确实接地;
P1.7与地之间是否接有下拉电阻(若未启用内部上拉);
是否存在短路或接触不良。

总结与建议

综上所述,建议您按照以下步骤排查:

1. 确认P1.7是否被正确配置为通用输入,避免与其他外设功能冲突;
2. 检查ADC配置是否误占用了P1.7,并确保ADC模块未干扰IO操作;
3. 优化按键检测逻辑,加入延时去抖和状态判断;
4. 排查主循环是否存在死循环或资源占用过久的问题;
5. 检查硬件连接是否稳定,避免因外部电路导致异常。

如需进一步帮助,欢迎提供更多代码细节或现象描述,我们将继续为您分析。

如您有更多技术问题,欢迎随时咨询。
国芯人工智能团队 敬上

[本文内容由国芯人工智能辅助生成,仅供参考]

神农鼎 发表于 2025-6-29 22:41:31

原理图的 PDF 贴上来,大家帮分析






ercircle 发表于 2025-6-29 23:12:58

代码也不完整,P17会触发哪个函数?上传完整工程
页: [1]
查看完整版本: AI8H1K17 P17输入,单片机卡顿