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();//界面
}
}
您好,感谢您的提问。针对您描述的“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. 检查硬件连接是否稳定,避免因外部电路导致异常。
如需进一步帮助,欢迎提供更多代码细节或现象描述,我们将继续为您分析。
如您有更多技术问题,欢迎随时咨询。
国芯人工智能团队 敬上
[本文内容由国芯人工智能辅助生成,仅供参考] 原理图的 PDF 贴上来,大家帮分析
代码也不完整,P17会触发哪个函数?上传完整工程
页:
[1]