zhudean11
发表于 2023-12-28 16:52:02
社区闲人 发表于 2023-12-28 16:00
【分享】新型的按键扫描程序 + 累计循环次数。不占用定时器
https://www.stcaimcu.com/forum.php?mod=vie ...
收到,感谢分享{:4_250:}
ulvtkb126
发表于 2024-1-17 11:19:12
用定时器来延时和用 软件延时那个资源用的少些
Snapdragon
发表于 2024-1-21 15:17:01
不用定时器的话可以做成非阻塞形式的,在while(1)里面循环检测,比如加个状态机什么的。
QW123
发表于 2024-1-31 16:33:29
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖
jwg
发表于 2024-1-31 16:59:40
QW123 发表于 2024-1-31 16:33
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖
{:4_250:}
21cnsound
发表于 2024-1-31 19:53:32
QW123 发表于 2024-1-31 16:33
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖
有必要在1ms这么短的中断中判断按键码?会不会时间片太短了?我觉得10-20ms应该比较合理吧,纯技术探讨
hhh402
发表于 2024-2-1 22:46:56
按键扫描最好方式就是放在10ms计时器中断中,因为检测间隔大于按键抖动时间,不需要做消抖检测,而且这种方式不会和其他程序起冲突。其他放在主循环中执行的方式不靠谱,只要再加上其他程序按键扫描时间间隔就会受影响,难道单片机只检查按键别的什么都不做吗?用计时器中断保证了按键检测时间间隔恒定,学会使用定时器中断是复杂变成的基础。
DebugLab
发表于 2024-2-2 00:15:47
本帖最后由 DebugLab 于 2024-2-2 00:26 编辑
不使用中断!不使用定时器!不使用延时函数!
怎么消抖?用执行其他程序的时间消抖!
延时函数?坚决不用!!!
放到主循环里一直循环就行,注意一下主循环的频率10~1000Hz都行,中断函数进去必须马上出来,不能进去100ms以上或者死在里面,如果有以固定频率运行的定时器中断,放在里面也行,这个按键扫描程序几乎不耗时。
基本结构:
void Key_Scan(void)
{
static bit Key_Flag;
if(KEY==0)
{
if(Key_Flag==1)
{
Key_Flag=0;
//在这里加按下要执行的
}
}
else
{
if(Key_Flag==0)
{
Key_Flag=1;
//在这里加松开要执行的
矩阵键盘因为要切换IO状态读取第二个坐标,需要延时函数消抖,单击双击长按才需要定时器。
矩阵键盘扫描单击双击长按:
#define Init_Up 25 //默认释放时间
#define Init_Down 25 //默认按下时间
#define Init_Long 100 //默认长按时间
#define Init_Disable 1 //默认死区时间
unsigned char Key_Decode(unsigned char temp)
{
unsigned char key;
switch(temp)
{
case 0x01:key=0;break;
case 0x02:key=1;break;
case 0x04:key=2;break;
case 0x08:key=3;break;
case 0x10:key=4;break;
case 0x20:key=5;break;
case 0x40:key=6;break;
case 0x80:key=7;break;
default:key=0xff;
}
return key;
}
void Key_Scan(void)
{
unsigned char temp_x,temp_y;
X_BUS=0x00;
Y_BUS=0xff;
Delay_x10us(100);
temp_y=Y_BUS;
if(temp_y!=0xff)
{
temp_y=Y_BUS;
X_BUS=0xff;
Y_BUS=temp_y;
Delay_x10us(100);
temp_x=X_BUS;
temp_x=Key_Decode(~temp_x);
temp_y=Key_Decode(~temp_y);
if(temp_x<8&&temp_y<8)
{
Key=temp_x*8+temp_y;
Key_Flag=1;
}
else
{
Key_Flag=0;
Key=0xff;
}
}
else
{
Key_Flag=0;
Key=0xff;
}
}
void Clear_Time(bit flag)
{
TL1=0x00;
TH1=0x70;
TR1=flag;
}
void main(void)
{
Init(); //初始化设置定时器1为不自动重载模式,以20ms为单位,定20ms
Temp=IapReadByte(Sector0);
if(Temp>=5&&Temp<=50)
Time_Up=Temp;
else
{
IapEraseSector(Sector0);
IapProgramByte(Sector0,Init_Up);
Time_Up=Init_Up;
}
Temp=IapReadByte(Sector1);
if(Temp>=5&&Temp<=50)
Time_Down=Temp;
else
{
IapEraseSector(Sector1);
IapProgramByte(Sector1,Init_Down);
Time_Down=Init_Down;
}
Temp=IapReadByte(Sector2);
if(Temp>=50&&Temp<=250)
Time_Long=Temp;
else
{
IapEraseSector(Sector2);
IapProgramByte(Sector2,Init_Long);
Time_Long=Init_Long;
}
Temp=IapReadByte(Sector3);
if(Temp>=1&&Temp<=10)
Time_Disable=Temp;
else
{
IapEraseSector(Sector3);
IapProgramByte(Sector3,Init_Disable);
Time_Disable=Init_Disable;
}
Key_Temp=255;
while(1)
{
Key_Scan();
if(Key_State!=Key_Flag) //按键状态改变
{
Key_State=Key_Flag;
Clear_Time(1);
if(Key_State) //按下瞬间
{
Count_Down=0;
Key_Single=1;
Key_Long=1;
if(Key_Temp==Key)
Key_Double=1; //和上次一样
else //和上次不一样
{
Key_Double=0;
Key_Temp=Key;
}
}
else //松开瞬间
{
Count_UP=0;
Key_Long=0;
if(Key_Single&&Count_Down>Time_Disable&&Count_Down<Time_Down);
else
{
Clear_Time(0);
Key_Single=0;
Key_Double=0;
Key_Long=0;
Key_Temp=0xff;
}
}
}
if(Key_Flag) //按下
{
if(Count_UP>=Time_Long&&Key_Long) //长按
{
Send_Key(Key_Temp+128);
Clear_Time(0);
Key_Single=0;
Key_Double=0;
Key_Long=0;
Key_Temp=0xff;
}
}
else //松开
{
if(Count_UP>=Time_Up&&Key_Single) //单击
{
Send_Key(Key_Temp);
Clear_Time(0);
Key_Single=0;
Key_Double=0;
Key_Long=0;
Key_Temp=0xff;
}
if(Count_UP>=Time_Disable&&Count_UP<=Time_Up&&Count_Down>=Time_Disable&&Count_Down<=Time_Down&&Key_Double&&Key_Single) //双击
{
Send_Key(Key_Temp+64);
Clear_Time(0);
Key_Single=0;
Key_Double=0;
Key_Long=0;
Key_Temp=0xff;
}
}
}
}
void Timer1_Isr(void) interrupt 3
{
Count_UP++;
Count_Down++;
if(Count_UP>250||Count_Down>250)
{
Count_UP=0;
Count_Down=0;
}
}
QW123
发表于 2024-2-21 16:44:43
21cnsound 发表于 2024-1-31 19:53
有必要在1ms这么短的中断中判断按键码?会不会时间片太短了?我觉得10-20ms应该比较合理吧,纯技术探讨 ...
1ms 是基础值,意思就是: 定时器1ms 中断一次,然后根据每项任务的需求,累加中断次数,达到一个定时器中断,完成不同的任务要求。比方: 按键是累加10次判断是否按下, LED循环使用累加20次去翻转,移动之类的。感觉这个用法在要求不高的条件下,还挺省定时器
zhange
发表于 2024-6-5 09:26:50
myliuyu 发表于 2023-12-28 11:15
amobbs里有几个关于按键的帖子挺不错的可以去参考下
{:5_278:} 这论坛还要钱????