精巧的按键处理程序
按键扫描程序(4)

else if(key == D_key)
........//点亮B_LED,关闭A_LED和C_LED
else if(key == S_key)
key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击
key_m = key_state_1;
}
else
特别操作情况定义:
1。短按操作和长按操作间隔<0.5s,以及,长按操作和短按操作间隔<0.5s,均不产生双击事件
2。连续n次(n为奇数)短按操作,且间隔均<0.5s,产生(n-1)/2次双击事件+1次单击事件
3。连续n次(n为偶数)短按操作,且间隔均<0.5s,产生n/2次双击事件
题目:多功能按键设计。利用一个I/O口,接一个按键,实现3功能操作:单击 + 双击 + 长按。
============================================================================
用户基本操作定义:
1。短按操作:按键按下,按下时间<1s,属于一次短按操作
if (!key_press)
{
key_time = 0; //
key_state = key_state_2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
}
else
key_state = key_state_0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
VHDL入门:关于按键消抖的那个process

这学期的EDA课程设计有涉及到一个按键信号稳定的问题,虽然就算没有这块处理,最后成绩只会扣3分,但自己觉得像LED亮度变化,数字钟设置这些功能,如果没有加进一个稳定按键信号的模块,根本不能算是已实现的功能。
按键消抖的程序在网上有几种可供选择,但这里只讨论一种,本人觉得简单得来又比较强大的一种。
其实消抖的原理就是把一个按键周期内所输入的所有有效信号,包括那些毛刺,处理成一个脉冲输入。
能达到这点,就可以实现消抖功能了。
功能的源代码:代码中的 key 是按键输入,count 是自定义的计数器,N的值可以根据需要结合时钟频率设置,如果只是想达到按键一次输入一个脉冲的效果,建议 count 的时长设为 5ms,key_en 是处理完后输出的单个脉冲,至于有效信号是 '0' 还是'1' ,这要看板上的电路设计了。
此代码中是 '0' 为有效信号。
不要怀疑这段代码有错,理清逻辑后再套用,如果弄不明白什么原理,建议还是别用,用了可能会更糟糕。
要注意的是一个 process 中只能有一个时钟信号,否则很容易出错,就算编译通过,实际操作还是不行。
所以如果要对多个按键消抖,一定要在 "if clk'event and clk='1' then" 语句的内部增加,别重新设置一个 clk'event 。
还有就是按键的消抖功能块最好用单独的 process 运行,将 key_en 设置成新的按键输入信号,而实际的输入信号 key 只在按键消抖的process 中读入。
之所以说这种消抖方法简单得来又比较强大,是因为这方法不需要用到什么状态机、component 之类较高级点的东西,只需要多个 process 即可;另外这种方法还有其他的拓展用途,比如可以利用这个 count 延时周期设置一个短按键和长按键的识别,实现长按此键切换或者 reset 等等的功能,这里不详细解释。
单片机按键程序设计

单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void main(){while(1) //无限循环{if(key == 0) //如果按键按下,引脚为低电平{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;while(key == 0);//等待按键松开}}}```上述代码中,我们首先定义了按键连接的引脚`key`,然后在主函数的无限循环中不断检测按键引脚的状态。
当检测到按键按下时,执行相应的操作,并通过`while(key == 0)`等待按键松开。
除了查询法,还有中断法可以用于按键检测。
中断法的优点是能够及时响应按键动作,不会因为程序的其他操作而导致按键响应延迟。
```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void int0_init()//中断初始化函数{IT0 = 1; //下降沿触发中断EX0 = 1; //使能外部中断 0EA = 1; //开总中断}void int0() interrupt 0 //外部中断 0 服务函数{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;}void main(){int0_init();//初始化中断while(1);//无限循环,保持程序运行}```在上述代码中,我们首先在`int0_init` 函数中对中断进行了初始化设置,然后在`int0` 函数中编写了按键按下时的处理代码。
按键处理程序C语言单片机

按键处理程序C语言单片机分享一种按键处理程序(用C)//头文件定义:Ustruct KEY{Uchar Val;#define Key_Model_C 0 //按键1值#define Key_AddVal_C 1 //按键2值Uint ScanOnTime;Uchar LongKeyState;Uchar LongKeyRestState;Uchar SetInRn;Uchar Model; //按键状态(模式)#define Off_C 0 //之前未按下#define On_C 1 //现按下#define Delay_C 2 //按键处理后标志}Key;//----------------定义两个IO输入口为按键入口--------------------//#define KeyMo_Bin (GPIOB->IDR.Bit.B5)#define KeyAdd_Bin (GPIOB->IDR.Bit.B6)/*===================================== ==========================*/GPIO_Init(GPIO_Pin_5|GPIO_Pin_6,GPIO_Mode_In_PU_No_IT); //初始化为上拉输入无中断/*===================================== ==========================*///主程序大循环中每1毫秒扫描1次void KeyScan(void){if(Key.LongKeyRestState == 1) //长按键标志(复位处理长按键){if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1)) //当两按键均抬起{if(++Key.ScanOnTime >= 130) //延时后复位{Key.LongKeyRestState=0;Key.Model=Delay_C;}}elseKey.ScanOnTime=0;return;}if(Key.Model == Off_C) //如果当前按键状态为未按下“Off_C”{if((KeyMo_Bin == 0) || (KeyAdd_Bin == 0))//按键1或按键2已按下(低有效){if(++Key.ScanOnTime >= 10) //当按下后自加1,加够10次即1ms*10=10ms去抖动{Key.ScanOnTime=0;if(KeyMo_Bin == 0) //如果按键1为0即按下{Key.Val=Key_Model_C; //付当键1值(看头文件定义)Key.Model=On_C; //置按键已按下标志}else if(KeyAdd_Bin == 0) //如果按键2为0即按下{Key.Val=Key_AddVal_C; //付当键2值(看头文件定义)Key.Model=On_C; //置按键已按下标志}BellOn(200); //蜂鸣器响}}elseKey.ScanOnTime=0; //清去抖延时计数值}else if(Key.Model == Delay_C) //如果当前按键状态为已按下且已处理“Delay_C”{if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1))//如果两按键均抬起{if(++Key.ScanOnTime >= 100) //延时100ms后复位按键状态为“Off_C”{Key.SetInRn=0;Key.ScanOnTime=0;Key.Model=Off_C;}}else //如果按键没有被抬起,对应上面if{if(++Key.ScanOnTime >= 1000) //延时1000ms后再复位按键状态为“Off_C”(为长按处理){Key.ScanOnTime=0;Key.Model=Off_C;}}}}//===================================== ========================================= ========void LoadCheckKeyRest(void){Key.LongKeyRestState=1;Key.ScanOnTime=0;}//===================================== ========================================= ========//处理相应按键(可250ms才调用一次)长按if(Key.Model == On_C) //按键状态为已按下{if(Key.Val == Key_Model_C) //是键1按下(看头文件定义){if(++Key.SetInRn >= 3) //连计3次数3秒后为长按键(对应上面,如果按下未抬起的话会延时1000ms){Key.SetInRn=0;LoadCheckKeyRest(); //调清长按处理BellOn(600); //蜂鸣器响//-----------长按需处理的内容-----下-----------//WorkStateBit.Bit.SettingMo=1;SetOverTime=0;SetMoRn=0;SetBak[0]=Rtc_InitDate.RTC_Year;SetBak[1]=Rtc_InitDate.RTC_Month;SetBak[2]=Rtc_InitDate.RTC_Date;SetBak[3]=Rtc_InitDate.RTC_WeekDay;SetBak[4]=Rtc_InitTime.RTC_Hours;SetBak[5]=Rtc_InitTime.RTC_Minutes;//-----------长按需处理的内容------上----------//Key.Model=Delay_C; //置按键模式为:已处理按键(看头文件定义)return;}}elseKey.SetInRn=0;Key.Model=Delay_C;}。
gshock按键功能

gshock按键功能G-Shock按键功能是一款非常实用的功能齐全的手表。
它被广泛应用于各种户外运动和极限运动,凭借其耐冲击、防水、防磁等特点而备受青睐。
它不仅有时钟、计时器、秒表等常见功能,还具备一些独特的按键功能,下面我将为大家详细介绍一下:首先是G-Shock的调整按键功能。
通过这些按键,用户可以轻松地切换模式,调整时间和日期等基本设置。
手表上通常有四个按键,根据按键的不同组合方式可以进行不同的操作。
比如,通过同时按下两个按键,可以进入设置模式,并通过其他按键来调整时间和日期。
这使得调整时间和日期变得非常方便快捷。
其次是G-Shock的闹钟和定时器功能。
用户可以设置多个闹钟和定时器,可以在特定的时间提醒用户或计时。
通过按键,用户可以轻松地设置闹钟的时间和铃声。
同时,用户还可以在使用定时器时按下按键,以暂停或重置定时器。
这些功能对于生活和工作都非常有帮助,特别是在需要按时完成任务或者提醒自己的场合。
另外,G-Shock还具备倒计时和秒表功能。
倒计时功能可以帮助用户在特定时间内完成任务,用户可以通过按键轻松设置倒计时时间,并在倒计时结束时进行提示。
秒表功能可以对时间进行精确的计时,用户可以通过按键开始、停止和重置秒表。
这对于一些需要精确计时的运动或比赛来说尤为重要,比如游泳、跑步等运动项目。
此外,G-Shock还具备一些特殊的功能按键,如电子指南针、温度计和高度计等。
通过按键,用户可以轻松地切换这些功能,并进行相应的测量。
电子指南针可以帮助用户在户外环境中确定方向,温度计可以测量周围的气温,而高度计可以测量用户所处的海拔高度。
这些功能在登山、徒步等户外活动中非常有用,帮助用户更好地适应环境。
总而言之,G-Shock的按键功能非常丰富,能够满足用户在不同场合的需求。
无论是日常生活中的时间管理,还是户外运动中的环境适应,G-Shock都能提供便捷的操作和准确的测量。
这些按键功能使得G-Shock成为现代人不可或缺的时尚配饰和实用工具。
手机按键工艺介绍

案例分析 ---背印拉丝纹
工艺介绍: 用CNC铣出外型,然后背面丝印CD纹
优点:厚度可以做到很薄,PC片最薄可以使用0.13mm,
(一般取值0.4—0.5)
不足:丝印定位要求高,外观不良较高,外型靠 CNC铣出,所以局部尺寸受限制
案例分析 ---车铣拉丝纹
组装
表面处理:
1、喷涂+镭雕 2、凹坑点漆 3、背面丝印 4、IMD按键 5、水晶按键 6、电镀组合
普通P+R
案例分析 ---喷涂+镭雕
工艺介绍:注塑出来后,喷涂,镭雕、UV保护、组装 优点:最为常用的键盘工艺,成本优势,工艺很成熟 不足:中规中矩,无新意
普通P+R
案例分析 ---印刷按键
工艺介绍:注塑,印刷(多次)、(镭雕)、UV保护、组装 优点:工艺成熟 不足:不良高。字符不能做得太细,透光效果不好控制, 有的会有重影
案例分析 ---金属拉丝电镀后再电泳
工艺介绍: 0.2的铜片,蚀刻出外型,车铣CD纹,进行表面 第一次电镀,再进行电泳
优点:外观非常绚丽、醒目,很薄。
不足:成本很高,耐磨性差较差。
案例分析 ---UV转印按键
工艺介绍:
案例分析 ---IMD按键
工艺介绍: 在film上印出各种符号、图案,进行模内转印,注塑完成图案 优点:永久耐磨、可以达到丝印无法达到的效果,印出更多花样,
更多不同色彩,工序简单。 不足:成本较高,制造不良较高
案例分析 ---水晶按键
工艺介绍: 在注塑时添加特殊色母,荧光粉,用印 刷镜面油墨或蒸镀做背景,可以做出有 水晶效果的按键,具有较强的时尚感。
可编程键盘使用方法

可编程键盘使用方法当使用可编程键盘时,有许多方法和技巧可以帮助您更高效地利用它的功能。
以下是50条关于可编程键盘使用方法并展开详细描述:1. 定义自定义快捷键:使用可编程键盘的软件,您可以定义自己的快捷键,例如触发特定应用程序或执行特定功能。
2. 创建宏:通过可编程键盘软件,您可以创建宏,以便一键执行复杂的操作序列,例如输入一段代码、执行一系列操作或者发送一封预定义的电子邮件。
3. 分层编程:一些可编程键盘支持分层编程,即在不同的层次设置不同的功能,可以根据需要进行切换,从而提高按键的多功能性。
4. 键位调整:通过可编程键盘软件,您可以重新映射键位,使得您习惯的键位布局可以在不同键盘上使用。
5. 多设备切换:如果您使用多台电脑或设备,一些可编程键盘可以支持快速切换不同设备,方便您在不同工作环境间进行移动。
6. 文本扩展:通过可编程键盘软件,您可以定义文本缩写和扩展,方便您快速输入常用的短语和段落。
7. 游戏模式:一些可编程键盘有专门的游戏模式,可以通过一键切换来禁用Windows 键或其他会干扰游戏操作的按键。
8. 设置多重触发:一些高级的可编程键盘支持多重触发,即在一个键上设置多种功能,通过单击、双击、长按或其他方式进行不同的响应。
9. 配置LED灯光效果:一些可编程键盘配备了LED灯,可以通过软件对其进行配置,达到个性化的灯光效果。
10. 自定义屏幕显示:一些可编程键盘上配备了OLED屏幕,您可以自定义显示内容,实时显示信息,如CPU温度、系统负载等。
11. 设备管理:在使用多个可编程键盘时,一些软件可以帮助您管理多个设备的配置和设置。
12. 定义特定应用程序的功能:针对特定的软件应用程序,您可以通过可编程键盘软件为其定义特定的快捷功能,提高工作效率。
13. 脚本编程:通过可编程键盘软件支持脚本编程,您可以更加强大地定制键盘功能,并且支持更多复杂的操作。
14. 切换不同的配置文件:对于不同的工作场景,您可以在可编程键盘软件中创建不同的配置文件,并进行快速切换,以应对不同的工作需求。
最简洁的按键检测 原理算法 c语言

最简洁的按键检测原理算法 c语言按键检测是在电子设备中常见的操作,它可以实现对按键的状态进行监测和响应。
本文将介绍一种简洁的按键检测原理算法,并使用C语言进行实现。
在电子设备中,按键通常是一种开关,用于接通或断开电路。
按下按键时,电路闭合,产生一个信号,通过按键检测可以获取到这个信号,并进行相应的处理。
按键检测的原理算法如下:1. 初始化:首先需要对按键进行初始化设置,包括设置按键引脚的输入/输出状态和电平状态。
2. 检测按键状态:通过读取按键引脚的电平状态来检测按键的状态。
一般来说,按键引脚的电平为高电平(1)表示按键未按下,低电平(0)表示按键按下。
3. 延时:为了避免检测到按键的抖动(按键在按下和松开的瞬间会产生多次信号),可以在检测到按键状态改变后进行一个短暂的延时,一般为几毫秒。
4. 再次检测:在延时后,再次读取按键引脚的电平状态。
如果检测到的状态与之前不同,说明按键的状态发生了改变。
5. 处理按键事件:根据按键的状态改变来进行相应的处理,比如执行一段代码、发送一个信号等。
6. 循环检测:以上步骤需要放在一个循环中进行,以实现对按键状态的持续监测和响应。
下面是一个简单的按键检测的C语言示例代码:```c#include <stdio.h>#include <wiringPi.h>#define BUTTON_PIN 17int main(){if (wiringPiSetup() == -1) // 初始化wiringPi库{printf("wiringPi setup failed!\n");return -1;}pinMode(BUTTON_PIN, INPUT); // 设置按键引脚为输入模式int previousState = HIGH; // 初始状态为未按下while (1){int currentState = digitalRead(BUTTON_PIN); // 读取按键引脚的电平状态if (currentState != previousState) // 检测到按键状态改变{delay(50); // 延时50毫秒,避免按键抖动currentState = digitalRead(BUTTON_PIN); // 再次读取按键引脚的电平状态if (currentState != previousState) // 再次检测到按键状态改变{if (currentState == LOW) // 按键按下{printf("Button pressed!\n");// 其他处理代码...}else // 按键松开{printf("Button released!\n");// 其他处理代码...}}}previousState = currentState; // 更新前一个状态}return 0;}```以上代码使用了wiringPi库来进行GPIO的控制和读取,需要在编译时加上-lwiringPi选项。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
新型的按键扫描程序不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。
同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。
对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。
因为这是实际项目中总结出来的经验,学校里面学不到的东西。
以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。
当然,我自己也是在多个项目用过,效果非常好的。
好了,工程人员的习惯,废话就应该少说,开始吧。
以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。
用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。
核心算法:unsigned char Trg;unsigned char Cont;void KeyRead( void ){unsigned char ReadData = PINB^0xff; // 1 对变量PINB取反.一个数和1异或相当于取反和零异或不变Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
3:算法2,用来计算连续变量。
看到这里,有种“知其然,不知其所以然”的感觉吧?代码很简单,但是它到底是怎么样实现我们的目的的呢?好,下面就让我们绕开云雾看青天吧。
我们最常用的按键接法如下:AVR是有内部上拉功能的,但是为了说明问题,我是特意用外部上拉电阻。
那么,按键没有按下的时候,读端口数据为1,如果按键按下,那么端口读到0。
下面就看看具体几种情况之下,这算法是怎么一回事。
(1)没有按键的时候端口为0xff,ReadData读端口并且取反,很显然,就是0x00 了。
Trg = ReadData & (ReadData ^ Cont); (初始状态下,Cont也是为0的)很简单的数学计算,因为ReadData为0,则它和任何数“相与”,结果也是为0的。
Cont = ReadData; 保存Cont 其实就是等于ReadData,为0;结果就是:ReadData =0;Trg =0;Cont =0;(2)第一次PB0按下的情况端口数据为0xfe,ReadData读端口并且取反,很显然,就是0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因为这是第一次按下,所以Cont是上次的值,应为为0。
那么这个式子的值也不难算,也就是Trg = 0x01 & (0x01^0x00) = 0x01Cont = ReadData = 0x01;结果就是:ReadData =0x01;Trg =0x01;Trg只会在这个时候对应位的值为1,其它时候都为0Cont =0x01;(3)PB0按着不松(长按键)的情况端口数据为0xfe,ReadData读端口并且取反是0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因为这是连续按下,所以Cont是上次的值,应为为0x01。
那么这个式子就变成了Trg = 0x01 & (0x01^0x01) = 0x00Cont = ReadData = 0x01;结果就是:ReadData =0x01;Trg =0x00;Cont =0x01;因为现在按键是长按着,所以MCU会每个一定时间(20ms左右)不断的执行这个函数,那么下次执行的时候情况会是怎么样的呢?ReadData =0x01;这个不会变,因为按键没有松开Trg =ReadData & (ReadData ^ Cont) =0x01 & (0x01 ^ 0x01) = 0 ,只要按键没有松开,这个Trg值永远为0Cont =0x01;只要按键没有松开,这个值永远是0x01!!(4)按键松开的情况端口数据为0xff,ReadData读端口并且取反是0x00 了。
Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00Cont = ReadData = 0x00;结果就是:ReadData =0x00;Trg =0x00;Cont =0x00;很显然,这个回到了初始状态,也就是没有按键按下的状态。
总结一下,不知道想懂了没有?其实很简单,答案如下:Trg 表示的就是触发的意思,也就是跳变,只要有按键按下(电平从1到0的跳变),那么Trg在对应按键的位上面会置一,我们用了PB0则Trg的值为0x01,类似,如果我们PB7按下的话,Trg 的值就应该为0x80 ,这个很好理解,还有,最关键的地方,Trg 的值每次按下只会出现一次,然后立刻被清除,完全不需要人工去干预。
所以按键功能处理程序不会重复执行,省下了一大堆的条件判断,这个可是精粹哦!!Cont代表的是长按键,如果PB0按着不放,那么Cont的值就为0x01,相对应,PB7按着不放,那么Cont的值应该为0x80,同样很好理解。
如果还是想不懂的话,可以自己演算一下那两个表达式,应该不难理解的。
因为有了这个支持,那么按键处理就变得很爽了,下面看应用:应用一:一次触发的按键处理假设PB0为蜂鸣器按键,按一下,蜂鸣器beep的响一声。
这个很简单,但是大家以前是怎么做的呢?对比一下看谁的方便?#define KEY_BEEP 0x01void KeyProc(void){if (Trg & KEY_BEEP) // 如果按下的是KEY_BEEP{Beep(); // 执行蜂鸣器处理函数}}怎么样?够和谐不?记得前面解释说Trg的精粹是什么?精粹就是只会出现一次。
所以你按下按键的话,T rg & KEY_BEEP 为“真”的情况只会出现一次,所以处理起来非常的方便,蜂鸣器也不会没事乱叫,h oho~~~或者你会认为这个处理简单,没有问题,我们继续。
应用2:长按键的处理项目中经常会遇到一些要求,例如:一个按键如果短按一下执行功能A,如果长按2秒不放的话会执行功能B,又或者是要求3秒按着不放,计数连加什么什么的功能,很实际。
不知道大家以前是怎么做的呢?我承认以前做的很郁闷。
但是看我们这里怎么处理吧,或许你会大吃一惊,原来程序可以这么简单这里具个简单例子,为了只是说明原理,PB0是模式按键,短按则切换模式,PB1就是加,如果长按的话则连加(玩过电子表吧?没错,就是那个!)#define KEY_MODE 0x01 // 模式按键#define KEY_PLUS 0x02 // 加void KeyProc(void){if (Trg & KEY_MODE) // 如果按下的是KEY_MODE,而且你常按这按键也没有用,{ //它是不会执行第二次的哦,必须先松开再按下Mode++; // 模式寄存器加1,当然,这里只是演示,你可以执行你想// 执行的任何代码}if (Cont & KEY_PLUS) // 如果“加”按键被按着不放{cnt_plus++; // 计时if (cnt_plus > 100) // 20ms*100 = 2S 如果时间到{Func(); // 你需要的执行的程序}}}不知道各位感觉如何?我觉得还是挺简单的完成了任务,当然,作为演示用代码。
应用3:点触型按键和开关型按键的混合使用点触形按键估计用的最多,特别是单片机。
开关型其实也很常见,例如家里的电灯,那些按下就不松开,除非关。
这是两种按键形式的处理原理也没啥特别,但是你有没有想过,如果一个系统里面这两种按键是怎么处理的?我想起了我以前的处理,分开两个非常类似的处理程序,现在看起来真的是笨的不行了,但是也没有办法啊,结构决定了程序。
不过现在好了,用上面介绍的办法,很轻松就可以搞定。
原理么?可能你也会想到,对于点触开关,按照上面的办法处理一次按下和长按,对于开关型,我们只需要处理Cont就OK了,为什么?很简单嘛,把它当成是一个长按键,这样就找到了共同点,屏蔽了所有的细节。
程序就不给了,完全就是应用2的内容,在这里提为了就是说明原理~~好了,这个好用的按键处理算是说完了。
可能会有朋友会问,为什么不说延时消抖问题?哈哈,被看穿了。
果然不能偷懒。
下面谈谈这个问题,顺便也就非常简单的谈谈我自己用时间片轮办法,以及是如何消抖的。
延时消抖的办法是非常传统,也就是第一次判断有按键,延时一定的时间(一般习惯是20ms)再读端口,如果两次读到的数据一样,说明了是真正的按键,而不是抖动,则进入按键处理程序。
当然,不要跟我说你delay(20)那样去死循环去,真是那样的话,我衷心的建议你先放下手上所有的东西,好好的去了解一下操作系统的分时工作原理,大概知道思想就可以,不需要详细看原理,否则你永远逃不出“菜鸟”这个圈子。
当然我也是菜鸟。
我的意思是,真正的单片机入门,是从学会处理多任务开始的,这个也是学校程序跟公司程序的最大差别。
当然,本文不是专门说这个的,所以也不献丑了。
我的主程序架构是这样的:volatile unsigned char Intrcnt;void InterruptHandle() // 中断服务程序{Intrcnt++; // 1ms 中断1次,可变}void main(void){SysInit();while(1) // 每20ms 执行一次大循环{KeyRead(); // 将每个子程序都扫描一遍KeyProc();Func1();Funt2();……while(1){if (Intrcnt>20) // 一直在等,直到20ms时间到{Intrcnt="0";break; // 返回主循环}}}}貌似扯远了,回到我们刚才的问题,也就是怎么做按键消抖处理。