找回密码
 立即注册
查看: 12|回复: 3

STC8H1K17 P17输入,单片机卡顿

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-06-29 22:04:44

2

主题

6

回帖

128

积分

注册会员

积分
128
发表于 昨天 22:04 | 显示全部楼层 |阅读模式
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[1];
    expect_temp =  10 * eeprom_dat[2];
    set_sleep_time =  eeprom_dat[3];
    //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();  //界面
    }
}


回复

使用道具 举报 送花

3

主题

523

回帖

-243

积分

等待验证会员

积分
-243
发表于 昨天 22:08 | 显示全部楼层
您好,感谢您的提问。针对您描述的“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请求未处理,导致主循环阻塞。

三、按键检测逻辑问题

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

建议在主循环中加入如下逻辑:
  1. c
  2. if (P17 == 0) { // 检测到按键按下
  3.     Delayms(20); // 延时去抖
  4.     if (P17 == 0) {
  5.         // 执行按键处理逻辑
  6.     }
  7. }
复制代码

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

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

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

五、硬件连接问题

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

总结与建议

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

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

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

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

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

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:112
  • 最近打卡:2025-06-29 00:35:48

741

主题

1万

回帖

1万

积分

管理员

积分
17207
发表于 昨天 22:41 | 显示全部楼层
原理图的 PDF 贴上来,大家帮分析


截图202506292243052699.jpg

截图202506292244275798.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:221
  • 最近打卡:2025-06-29 14:47:56
已绑定手机

72

主题

2018

回帖

4548

积分

荣誉版主

无情的代码机器

积分
4548
发表于 昨天 23:12 | 显示全部楼层
代码也不完整,P17会触发哪个函数?上传完整工程
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-6-30 07:53 , Processed in 0.140314 second(s), 80 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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