最近在一个项目中,由于客户要求,需要留有1个引脚后续扩展功能,导致原本刚好的I/0口,经过考虑从按键管脚移走一个,用于扩展,留下来一个引脚控制两个按键。
图中串在两个按键上下的电阻作用为防止两个按键同时按下时电源正负极短路,轻则烧坏芯片,重则烧坏电池。
最开始的代码思路来自下面链接,根据我个人需要,我修改为利用定时器中断来延时。使用芯片为九齐的NY8B062E(I/O口带内部上下拉)
一个GPIO控制两个按键的方法https://blog.csdn.net/sw7989/article/details/105609145
#define Switch_Enable 1
#define Switch_Disable 0
#define PULL_UP 1
#define PULL_DOWN 0
#define Input_KEY PORTBbits.PB0
unsigned char Key_Time; // 按键消抖计数
unsigned char Switch_Flag; // 按键上下拉切换标志
unsigned char Switch_Time; // 切换时间计数
unsigned char Resistor_Status; // 电阻状态 1:上拉 0:下拉
unsigned char Up_Trigger_Flag; // 按键触发标志
unsigned char Down_Trigger_Flag;// 按键触发标志
unsigned char Only_Once_Flag;
// 九齐没有位定义功能,如果空间不够,可以利用位域功能实现位定义功能
void isr(void) __interrupt(0)
{
if(INTFbits.T0IF) //500US
{
TMR0 = 0X09;
Key_Time++;
Switch_Time++;
INTFbits.T0IF = 0; // Clear T0IF flag bit
}
}
void Key_Scan(void)
{
if( ( Switch_Flag == Switch_Enable ) && ( System_Status == System_Status_Run ) )
/*< 上下拉切换 */ //系统未开启时,关闭切换,电阻默认上拉,等待开机
{
BWUCON = 0X00; // 成功唤醒后关闭按键中断
if( Switch_Time >= 10 ) // 5MS切换一次
{
Switch_Time = 0;
if ( Resistor_Status == PULL_UP )
{
Resistor_Status = PULL_DOWN;
ABPLCON = 0XEF; // 1110 1111 PB0 下拉
BPHCON = 0XFF; // 1111 1111 关闭 PB0 上拉
}
else
{
Resistor_Status = PULL_UP;
BPHCON = 0XFE; // 1111 1110 PB0 上拉
ABPLCON = 0XFF; // 1111 1111 关闭 PB0 下拉
}
}
Key_Time = 0;
}
if( ( Switch_Time > 4 ) || ( System_Status == System_Status_Sleep ) )
// 等待电平稳定
{
if ( ( Resistor_Status == PULL_UP && !Input_KEY ) || ( Down_Trigger_Flag ) )
/*< 上拉使能同时接地按键按下 */
{
Switch_Flag = Switch_Disable; /*< 禁止上下拉切换 */
Down_Trigger_Flag = 1;
if( Key_Time >= 60 ) // 30ms消抖
{
if ( !Input_KEY )
{
if(!Only_Once_Flag)
{
Only_Once_Flag = 1;
// 按下一次只执行一次,防止由于未松开导致的多次触发
}
}
else
{
Switch_Flag = Switch_Enable; /*< 使能上下拉切换 */
Down_Trigger_Flag = 0; // 清除触发标志
Only_Once_Flag = 0; // 按键执行程序恢复触发
}
Key_Time = 0;
}
}
else if( (Resistor_Status == PULL_DOWN && Input_KEY ) || ( Up_Trigger_Flag ) )
/*< 上拉禁止同时接电源按键按下 */
{
Switch_Flag = Switch_Disable; /*< 禁止上下拉切换 */
Up_Trigger_Flag = 1;
if( Key_Time >= 60 ) // 30ms消抖
{
if ( Input_KEY )
{
if( !Only_Once_Flag )
{
Only_Once_Flag = 1;
// 按下一次只执行一次,防止由于未松开导致的多次触发
}
}
else
{
Switch_Flag = Switch_Enable; /*< 使能上下拉切换 */
Up_Trigger_Flag = 0; // 清除触发标志
Only_Once_Flag = 0; // 按键执行程序恢复触发
}
Key_Time = 0;
}
}
}
}