单片机按键程序
单片机51 去抖按键程序
#define START_TIMER1 TR1=1
#define STOP_TIMER10 TR1=0
#define KD_VAL 15
sbit Ktemph=P1^0;
sbit Ktempl=P1^1;
sbit Ktime=P1^2;
sbit Kset=P1^3;
unsigned char Irbufnum;
unsigned char Irbuf[6];
unsigned char Recposi;
unsigned int idata Irbuffer[50];
unsigned char Kscanbuf[8];
unsigned char Kscan[8];
unsigned char Kcount[8];
RCAP2L = 0XB8 ;
TR2=1;
EX0=1;/*ÔÊÐíÍⲿ0ÖжÏ*/
EA = 1;/*¿ªÈ«¾ÖÖжÏ*/
TR0=0;
TMOD|=1<<4;/*¼ÆʱÆ÷1×÷Ϊ16λ*/
ET1=1;
TH1=0xf8;
TL1=0xcc;
TR1=1;
PX0=1;/*ÍⲿÖжÏ0ÓÅÏÈ*/
IT0=1;/*ϽµÑØ´¥·¢ÖжÏ*/
/*ET0=1;*/
/*ES = 1;*//*ÔÊÐí´®ÐпÚÖжÏ*/
TCLK = 1 ; /*¶¨Ê±Æ÷2ÓÃ×÷²¨ÌØÂÊ·¢ÉúÆ÷*/
RCLK = 1 ;
/*¾§Õñ 22.1184 £¬ 6T £¬²¨ÌØÂÊ9600*/
RCAP2H = 0xff ;
单片机按键-长按-短按-连发-双击-抬起-按下
/******************************************************************************** 功能:获取按键状态 参数:无 返回值:按键状态 STAT_DOWN 按键按下
/* 每个按键都包括自己的属性 */ /*按键属性定义*/
typedef struct {
StatEnum_TypeDefstat; unsigned char KeyNum; unsigned short CountMs; unsigned short ShakeTimeMs; unsigned short LongClickTimeMs; unsigned short ContinueSendTimeMs; unsigned short DoubleClickTimeMs; unsigned char (*GetKeyStat)(void); }KeyAttribute_TypeDef;
void KeyAttributeZeroInit(void); void RefreshKeyStat_1_Ms(KeyAttribute_TypeDef *pKeyAttribute); unsigned short GetKeyVal(void);
#endif
/****************************************************************************************************************************** keyfunc.c
STAT_UP 按键未按下 说明:每个按键必须包括一个此类型的函数[unsigned char (*)(void)]然后用按键属性中的
单片机按键程序研究
• 87•单片机按键程序的编写各种教材上都有介绍,但在工程应用上却存在某些不足。
本文通过工程实践,从多种按键程序各自特点进行了研究,以几种优选程序供各位单片机使用者参考。
为了能说明问题,以下分析均以图1常开按钮开关与单片机硬件的连接为准。
许多的按键程序设计思想是等待键释放才执行按键按下后的动作,这虽然解决了按键被按住不放而引发的问题。
“待键释放”编程思想在程序比较短小的情况下问题还不突出,较大型些的程序则一直在反复等待键释放不仅电路灵敏度降低且会让单片机工作状态不稳甚至“死机”。
为此,实际使用中的按键程序一般都不采用等键释放的编程思想。
图1 按键与P1口连接图1 设置标志位以记录按键状态程序的主要部分及注释如下:void main( ){ bit flag=0;//定义按键标志位变量,初态为0while(1)//让程序在语句4至语句9之间不断循环{if(0==K1&&flag==0)//按键接通并且标志位是0时 {delayms(10);//延时10ms,避开键抖动 if(0==K1){//二次确认键被按下flag=1;//标志位置1,防止一次按键被重复执行 {按键对应语句}}//在此安排按键后要执行的动作语句if(1==K1)flag=0;}}//键释放标志位置0该编写方法好处是在按键被长按住不放时,不会重复执行“按键对应语句”且按键刚被按下“按键对应语句”即被执行。
而且若要记录同一按键被按下了几次也容易实现:只要在上例程序的语句8改为:count=(count+1)%9;(count 是无符号全局变量)并在语句9后面添加以下的语句:switch(count){ case 1:按第1次键要执行的语句;break ; case 2:按第2次键要执行的语句;break ;……}}}2 同时判别几个按键状态根据图1写出按键函数:void key( )//按键函数{P1=P1|0X0F;//置P1低四位为高电平if(Pre_key==(P1&0X0F))return; //按键状态不变时提前结束按键函数Pre_key=P1&0X0F;//保存当前新的按键状态if(!K1){//如果四个键中是K1被按下delayms(10)//10ms消键抖if(!K1){//二次确认K1被按下K1按下后要执行的语句}}}K2、K3、K4被按下程序也同语句5至语句8类似编写,不再赘述。
单片机按键程序设计
单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```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` 函数中编写了按键按下时的处理代码。
单片机按键连按长按汇编程序
单片机按键连按长按汇编程序;=============================================================== ;程序编写人:兰建文;编写地点:51hei培训机构;时间:6月7日下午星期日;功能:本程序实现P0口的对2个数码管显示0到99,一个按键实现一次;按键只递加1次,到99回到0,按着不动不影响数码管动态显示;任何时;刻,任何一个按键,若按键连续按键3次,每次间隔时间不大于1秒,循;环显示0到9回到0。
若间隔时间大于1秒,显示加1,低电平亮;P2口实现对数码管的片选功能;=============================================================== ;==========================系统程序============================= ;=========================开始初始化============================ SHUCHU EQU P0 ;定义P0口为输出口PIANXUAN EQU P2 ;定义P2口为片选口SHUZI EQU 30H ;设置处理数据存放地址JIANBIT0 BIT 20H.0 ;设置按键标志位XIAN0 BIT 20H.2 ;显示标志位T_BIT BIT 21H.0 ;设置中断定时器0标志位LIANAN BIT 20H.1 ;设置连按标志位BIT4 BIT 20H.2MODE EQU 01HSHU EQU 40H;========================程序开始==============================ORG 00H ;程序开始LJMP START ;跳到STARTORG 0BH ;中断定时器0入口地址JMP T0_1 ;跳到定时器0服务程序ORG 0030H ;入口地址;=========================主程序=============================== START:MOV SP,#60H ;移开指针MOV SHUZI,#00 ;数据初始化MOV DPTR,#TAB ;查表初始化MOV P1,#0F8H ;设置P1.0口为输入CALL INIT ;开中断CLR JIANBIT0 ;按键标志位清0CLR LIANAN ;连按标志位清0CLR BIT4SETB T_BIT ;中断标志位置1MOV SHU,#0MOV R2,#0MOV R3,#0MOV R4,#0MOV R5,#200MAIN:JNB T_BIT,MAIN ;等待中断CLR T_BIT ;中断标志位清0JB BIT4,VVINC R3CJNE R3,#25,XXMOV R3,#00MOV R2,#0JMP DDXX:CJNE R2,#3,VVSETB LIANANMOV R2,#00DD:CLR BIT4VV:JB LIANAN,XUNHUAN ;判断是否有连按CC:CALL JISUAN ;计算分离十位和个位CALL DISPLAY ;显示个位和十位JNB JIANBIT0,PANDUAN;按键标志位=1判断P1.3口,若为0则判断按键是否抬起JNB P1.3,XIANSHI0 ;若没抬起(P1.3=0)则调到XIANSHI0 SETB BIT4INC R2MOV R3,#0CLR JIANBIT0 ;按键标志位清0CLR XIAN0 ;显示标志位清0JMP MAIN ;返回MAINPANDUAN:JB P1.3,MAIN ;若按键抬起则返回MAIN,若没有抬起按键标志位清0 SETB JIANBIT0JMP MAINXIANSHI0:JB XIAN0,MAINSETB XIAN0 ;显示标志位清0CALL JIACHULI ;加处理JMP MAINXUNHUAN:MOV A,SHUCJNE A,#10,KKKMOV SHU,#0CLR LIANANMOV A,SHUKKK: MOVC A,@A+DPTR ;查表MOV SHUCHU,AMOV PIANXUAN,#05INC R4CJNE R4,#50,OUTTINC SHUMOV R4,#0OUTT:JMP MAIN;====================定时中断0服务子程序======================== ;输入:无;输出:无;实现的功能:实现定时20MS,影响标志位T_BIT;=============================================================== T0_1:MOV TMOD,#MODE ;定时器1工作方式1MOV TL0,#0E0H ;设置定时初值MOV TH0,#0B1HSETB T_BIT ;定时标志位清0RETI;========================中断设置子程序========================= ;输入:无;输出:无;实现的功能:初始化设置定时器,设置初值;===============================================================INIT:MOV TMOD,#MODE ;定时器0工作方式1MOV TL0,#0E0HMOV TH0,#0B1HMOV IE,#82H ;开定时器中断0SETB TR0 ;开定时器0RET;========================计算子程序============================= ;输入:30H;输出:"A和B";实现的功能:把30H的数据的十位和个位分离出来;=============================================================== JISUAN:MOV A,SHUZI ;数据放在A中MOV B,#10 ;除数放在B中DIV AB ;商放在A中,余数放在B中RET;========================显示子程序============================= ;输入:"A";输出:"P0口";实现的功能:把A的数输出到P0口显示,十位和个位分开显示;=============================================================== DISPLAY:MOVC A,@A+DPTR ;查表MOV SHUCHU,A ;显示十位MOV PIANXUAN,#04H ;片选CALL DELAY ;查表MOV SHUCHU,#0FFH ;关闭数码管MOV A,BMOVC A,@A+DPTR ;查表MOV SHUCHU,A ;显示个位MOV PIANXUAN,#05H ;片选CALL DELAY ;延时MOV SHUCHU,#0FFH ;关闭数码管RET;======================加处理子程序============================= ;输入:无;输出:无;实现的功能:把30H地址加1;=============================================================== JIACHULI:MOV A,SHUZICJNE A,#99,L0 ;若A不等于9,则跳到LL MOV A,#00JMP L1L0:INC A ;自加一L1:MOV SHUZI,ARET;========================延时程序===============================;输入;无;输出: 无;实现的功能:延时一段时间;=============================================================== DELAY:MOV R6,#80L7:MOV R7,#80L8:DJNZ R7,L8DJNZ R6,L7RET;=====================共阳查表数据============================== TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H;=======================程序结束================================ END一个按键控制一个灯,要求按一下按键,灯亮一直亮,再按一下按键灯灭,要带按键的去抖程序。
单片机按键程序的编写
一般情况下,如果多个按键每个都直接接在单片机的 I/O 上的话会占用很多的 I/O 资源。比 较合理的一种做法是,按照行列接成矩阵的形式。按键接在每一个的行列的相交处。这样对 于 m 行 n 列的矩阵,可以接的按键总数是 m*n。这里我们以常见的 4*4 矩阵键盘来讲解矩阵 键盘的编程。
/******************************************
* 此模块所需相关支持库
*
******************************************/
#include"regx52.h"
#define uint8 unsigned char
#define uint16 unsigned int
bit bdata StartScan = 0 ;//此变量需放在定时中断中置位
else
{
//SHOW_ICON
}
}
}
每次执行读键盘函数时,只是对一些标志进行判断,然后退出。因此能够充分的利用 CPU 的资源。同时可以处理连发按键。此按键扫描按键函数可以直接放在主函数中。如果感觉按 键太过灵敏或者迟钝则改一下相关消抖动的宏定义即可。此函数也可以通过中断标志位进行 定时的扫描。此时,需要添加一个定时标志位,并将相关消抖动的和连击时间的宏定义改小 即可。然后在主程序类似下面这样写即可
这个流程是好多教科书上的做法。可惜,误导了好多人。为什么呢。因为它根本就没有考虑 实际情况。我们根据这幅流程图来写它的代码看看。
unsigned char v_ReadKey_f( void )
{
unsigned char KeyPress ;
51单片机使用状态机的键盘程序
}
default://其它
{
step = _Key1_up;//单键抬起消抖
#define Key_Down 0x3D //下箭头
#define Key_Add 0x3B //加
#define Key_Sub 0x37 //减
#define Key_Enter 0x2F //回车
传入参数:无
返回参数:无
设 计:莫汉伟 amo73@
修改日期:2007-10-12
备 注:详细功能和处理算法请参照本文件相关的流程图和文档
**************************************************************************/
#define KeyBuffLen 8 //定义键值环形缓冲区长度为8(缓冲区大小可自由定义,只要大于0即可)
//定义一个键盘缓冲区结构体
struct Struct_KeyBoardBuff
{
u8 buff[KeyBuffLen];//键值环形缓冲区
u8 in; //写键值指示(定时器中断写)
u8 Read_Key(void)
{
u8 Value;
if(Key.out != Key.in)
{
Value=Key.buff[Key.out++];//"读"还没有追上"写",缓冲区有键值,读之
if(Key.out >= KeyBuffLen) //如果"读"跑到了队列尾部,则重新跳回原点
u8 out; //读键值指示(用户读)
基于51单片机按键长按短按效果源程序
基于51单片机按键长按短按效果源程序[复制链接]* 实验名称:多位数按键加减** 晶振:12MHZ* 内容:按键加减数字,多个数码管显示,使用定时器做数码管动态扫描** 并区别长按短按效果,完全可以应用的实际生产中** ---------------------------------------------------------------*/#include<reg52.h> //包含头文件,一般情况不需要改动,//头文件包含特殊功能寄存器的定义sbit KEY_ADD=P3^3; //定义按键输入端口S17sbit KEY_DEC=P3^2; //S18#define DataPort P1 //定义数据端口程序中遇到DataPort 则用P1 替换sbit LATCH1=P2^0;//定义锁存使能端口段锁存sbit LATCH2=P2^1;// 位锁存sbit P35 = P3^5;//这是为了关闭开发板上的点阵实际应用去掉unsigned char code HEYAO_DuanMa[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};// 显示段码值0123456789unsigned char code HEYAO_WeiMa[]={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};//分别对应相应的数码管点亮,即位码unsigned char TempData[8]={0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF};//存储显示值的全局变量void DelayUs2x(unsigned char t);//函数声明void DelayMs(unsigned char t);void Init_Timer0(void);void Display(unsigned char FirstBit,unsigned char Num);/*------------------------------------------------主函数------------------------------------------------*/void main (void){unsigned char num=0,key_press_num;P35=0; //这是为了关闭开发板上的点阵实际应用去掉KEY_ADD=1; //按键输入端口电平置高KEY_DEC=1;Init_Timer0();while (1) //主循环{if(!KEY_ADD) //如果检测到低电平,说明按键按下DelayMs(10); //延时去抖,一般10-20msif(!KEY_ADD) //再次确认按键是否按下,没有按下则退出{while(!KEY_ADD){key_press_num++;DelayMs(10); //10x200=2000ms=2sif(key_press_num==200) //大约2s{key_press_num=0; //如果达到长按键标准//则进入长按键动作while(!KEY_ADD) //这里用于识别是否按//键还在按下,如果按//下执行相关动作,否则退出{if(num<99) //加操作num++;//即时把显示数据处理,如果去掉下面2//句处理信息,实际上看不到渐变效果,//而是看到跳变效果//用户可以自行屏蔽测试//分解显示信息,如要显示68,则68/10=6 68%10=8 TempData[0]=HEYAO_DuanMa[num/10];TempData[1]=HEYAO_DuanMa[num%10];DelayMs(50);//用于调节长按循环操作//的速度,可以自行调整此值以便达到最佳效果}}}key_press_num=0;//防止累加造成错误识别if(num<99) //加操作num++;}}if(!KEY_DEC) //如果检测到低电平,说明按键按下{DelayMs(10); //延时去抖,一般10-20msif(!KEY_DEC) //再次确认按键是否按下,没有//按下则退出{while(!KEY_DEC)key_press_num++;DelayMs(10);if(key_press_num==200) //大约2s{key_press_num=0;while(!KEY_DEC){if(num>0) //减操作num--;//分解显示信息,如要显示68,则68/10=6 68%10=8 TempData[0]=HEYAO_DuanMa[num/10];TempData[1]=HEYAO_DuanMa[num%10];DelayMs(50);//用于调节长按循环操作的速度}}}key_press_num=0;//防止累加造成错误识别if(num>0) //减操作num--;}}//分解显示信息,如要显示68,则68/10=6 68%10=8 TempData[0]=HEYAO_DuanMa[num/10];TempData[1]=HEYAO_DuanMa[num%10];// Display(0,8); //显示全部8位//主循环中添加其他需要一直工作的程序}}/*------------------------------------------------uS延时函数,含有输入参数unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,精确延时请使用汇编,大致延时长度如下T=tx2+5 uS------------------------------------------------*/void DelayUs2x(unsigned char t){while(--t);}/*------------------------------------------------mS延时函数,含有输入参数unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------*/void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/*------------------------------------------------显示函数,用于动态扫描数码管输入参数FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示如输入0表示从第一个显示。
单片机的按键功能是什么
单片机的按键功能是什么你们知道单片机的每个按键的具体功能吗?下面是店铺收集整理关于单片机的每个按键的具体功能的资料以供大家参考学习,希望大家喜欢。
·单片机的每个按键的具体功能介绍键盘的分类:键盘分编码键盘和非编码键盘。
键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘;而靠软件编程来识别的称为非编码键盘。
在单片机组成的各种系统中,用的最多的是非编码键盘。
也有用到编码键盘的。
非编码键盘有分为:独立键盘和行列式(又称为矩阵式)键盘。
本文主要讨论矩阵键盘(独立键盘比较简单可以与此类比),下面是矩阵键盘的电路连接图。
按键的扫描,主要是对每一个按键所编码的识别与确定。
如上图:按键所接口为P2口,置“0”则按键有效。
当P2口检测到值为P2=0x7e时,S1有效。
低四位用来确定行按键,高四行用来确定列按键。
基本的编程思想是:先设定P2口为0xfe,确定第一行按键有效,然后将P2口的值与0xf0按位与(&),然后检测P2口的值是否为0xf0,这样就屏蔽了低四位的电位改变(因为无论之后低四位怎样变化,低四位与0相与总是0)。
然后如果P2口得值不为0xf0时,则证明高四位有电位改变。
则检测此时的P2口得值,就可以确定是哪个按键被按下了。
如按键S1,它编码是P2=0x7e,也就是当P2口检测到值为P2=0x7e时,S1有效。
需要注意的是:按键按下时有一个前后抖动时间,如下图(a)所示。
如果单片机检测到的是抖动部分,则无法按键判断是否有效,所以我们需要加入防抖程序。
注:也可以通过硬件防抖,如上图(b)。
功能:矩阵键盘(按相应的按键,数码管从0~F的显示)单片机:AT89S52#include <reg52.h>#define uint unsigned int#define uchar unsigned charsbit DAT=P0^3;sbit CLK=P0^2;uchar temp,h;void delay(uint); //延迟程序void sendbyte(uchar); //数码管显示void keyscan(); //按键扫描uchar code tab[]={0xed,0x09,0xbc,0x9d,0x59,0xd5,0xf5,0x0d,0xfd,0xdd,0x7d,0xf1,0xe4,0xb9,0xf4,0x74,0x00} ; //0-F, 全灭void main (void){sendbyte(16); //初始时数码管无显示while(1){keyscan(); //按键扫描}}void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=100;y>0;y--);}void sendbyte(uchar byte){uchar num,c;num=tab[byte];for(c=0;c<8;c++){CLK=0;DAT=num&0x01;CLK=1;num>>=1; //右移位赋值}}void keyscan(){/*第一行按键的扫描*/P2=0xfe; //确定第一行的按键有效temp=P2; //将其赋给一个变量(处理I/O口时,一般先赋值给一个变量,然后通过处理变量来处理I/O口)temp=temp&0xf0; //用于检测第一行的哪个按键按下while(temp!=0xf0) /*这个部分只要是用来消除按下抖动的*/{delay(5);temp=P2;temp=temp&0xf0;while(temp!=0xf0) //这个地方,已经消除了按下抖动,P2口的值已经确定temp=P2; //将P2口得值赋给变量switch(temp) //这个switch语句,用来确定哪一个按键按下时,数码管的显示值{case 0x7e:h=0;break; //这个break很重要,表示如果有匹配的值,就跳出switch语句,防止程序跳不出来。
单片机经典长短按程序
新型的按键扫描程序不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为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; // 1Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C 语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
单片机按键 长按 短按
switch(key_num){
case 1:key_ret = 5;break;
case 2:key_ret = 6;break;
case 3:key_ret = 7;break;
case 4:key_ret = 8;break;
}
}
else{/*短按有效*/
}
ห้องสมุดไป่ตู้}
}
return key_ret;
}
if(key_flag){/*松手*/
key_flag = 0;
switch(key_num){
case 1:key_ret = 1;break;
case 2:key_ret = 2;break;
case 3:key_ret = 3;break;
case 4:key_ret = 4;break;
static bit key_flag = 0;
if((!SET)||(!KUP)||(!KDN)||(!KOK)){/*判断是否有键按下*/
if(++del_count==5){/*计数消抖*/
del_count = 0;
if(++tim_count>4){/*长按识别*/
key_flag = 0;/*短按无效*/
key_flag = 1;/*短按标志位*/
if(!SET)key_num = 1;/*一下用于识别按键*/
if(!KUP)key_num = 2;
if(!KDN)key_num = 3;
if(!KOK)key_num = 4;
单片机按键处理技巧及编程方式
单片机按键处理技巧及编程方式2010-10-23 15:01从这一章开始,我们步入按键程序设计的殿堂。
在基于单片机为核心构成的应用系统中,用户输入是必不可少的一部分。
输入可以分很多种情况,譬如有的系统支持PS2键盘的接口,有的系统输入是基于编码器,有的系统输入是基于串口或者USB或者其它输入通道等等。
在各种输入途径中,更常见的是,基于单个按键或者由单个键盘按照一定排列构成的矩阵键盘(行列键盘)。
我们这一篇章主要讨论的对象就是基于单个按键的程序设计,以及矩阵键盘的程序编写。
◎按键检测的原理常见的独立按键的外观如下,相信大家并不陌生,各种常见的开发板学习板上随处可以看到他们的身影。
(原文件名:1.jpg)引用图片总共有四个引脚,一般情况下,处于同一边的两个引脚内部是连接在一起的,如何分辨两个引脚是否处在同一边呢?可以将按键翻转过来,处于同一边的两个引脚,有一条突起的线将他们连接一起,以标示它们俩是相连的。
如果无法观察得到,用数字万用表的二极管挡位检测一下即可。
搞清楚这点非常重要,对于我们画PCB的时候的封装很有益。
它们和我们的单片机系统的I/O口连接一般如下:(原文件名:2.jpg)引用图片对于单片机I/O内部有上拉电阻的微控制器而言,还可以省掉外部的那个上拉电阻。
简单分析一下按键检测的原理。
当按键没有按下的时候,单片机I/O通过上拉电阻R接到VCC,我们在程序中读取该I/O的电平的时候,其值为1(高电平); 当按键S按下的时候,该I/O被短接到GND,在程序中读取该I/O的电平的时候,其值为0(低电平) 。
这样,按键的按下与否,就和与该按键相连的I/O的电平的变化相对应起来。
结论:我们在程序中通过检测到该I/O口电平的变化与否,即可以知道按键是否被按下,从而做出相应的响应。
一切看起来很美好,是这样的吗?◎现实并非理想在我们通过上面的按键检测原理得出上述的结论的时候,其实忽略了一个重要的问题,那就是现实中按键按下时候的电平变化状态。
51单片机-独立按键
查询方式
单片机不断的扫描键盘判断按键是否动作 特点:硬件简单,但需要单片出中断请求,单片机响应中断请求后转按键 识别程序
特点:硬件复杂,需要中断电路,但不占用CPU资源
单片机处理按键的流程
单片机处理按键动作需要以下步骤:
按键识别
单片机在识别按键时,IO口工作在输入状态:
按键弹起,IO口电平5V
Vcc
按键按下,IO口电平0V
单片机读取IO口的状态
即可知按键的状态
单片机
按键抖动
实际的按键在被按下或抬起时,由于机械 触点的弹性作用,在闭合或断开的瞬间均伴随有 一连串的抖动现象。
理想波形
实际波形
按下抖动
稳定闭合
释放抖动
完整的按键过程包括: 1. 释放状态 2. 按下抖动阶段 3. 完全按下状态 4. 释放抖动阶段 5. 释放状态
按键防抖
防抖措施:
硬件防抖
在按键输出端加RS或施密特触发器 去抖效果好、电路复杂、成本高
软件防抖
利用软件进行延时(10ms) 电路简单、成本低、但占用CPU时间
键盘的工作方式
判断按键是否按下 按键按下时的防抖 识别哪个按键按下,判断键值 判断按键是否放开 送出键值,处理按键动作
练习:单片机按键查询操作,8个按键对应8个LED灯, K1对应D1,K2对应D2,K3对应D3,……,查询按键, 按下某一个按键后对应的LED亮起,再按一次关闭。
基于单片机的电容感应式触摸按键原理与程序——C程序
/******************************************************************************
STC单片机电容感应按键C程序---------原创作者wannenggong
******************************************************************************/
{
R=0;
RV=GetADCResult(ee-1);
R=(FLG[ee-1]-RV);
if(R>=0x17 && R<=0x1d)
R=ee;
else
{R=0;ee++;}
if(ee>2)ee=1;
switch(R)
{
case 1://K1
{f1=1;f2=0;}
break;
case 2://K2
{f2=1;f1=0;}
{
uchar e;
Delay(50);//延时等待系统稳定很有必要
for(e=0;e<2;e++)
{
FLG[e]=GetADCResult(e);
Delay(5);
}
}
/*****************开关控制函数****************************************/
void key_control(void)
经过上篇文章的介绍,基于单片机的电容感应式触摸按键的实现方法也就没什么神秘的了,而且其控制程序也就呼之欲出了,核心就是用STC单片机的片内ADC实时的进行数据转换与比对判断,但虽然原理简单,但编程思路还是要啰嗦几句,想法是先设置一个空数组作为键值数据暂存器,每次上电运行时,经过短暂的等待,待电源和系统稳定后,扫描一次键盘,将无操作时的键值加以记录,而后循环扫描键盘与之对比,当差值符合条件是,判断为有键按下,同时返回键号及键控指令。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
******************************************************************************/ #include <reg51.h> #include "cdef.h" #define PORT_0 P3 //P3.3 直接接按键 //去抖动的时间(待定) #define c_wobble_time 100 //等待按键进入连击的时间(待定) ,该常数在设计时要比按键按下的常规时间长一点, //并且小于 5 秒 #define c_keyover_time 20000 //等待按键抬起的连击时间 #define c_keyquick_time 2000 byte BUT_bNum=0;//延时
******************************************************************************/ void main(void) { while(1) { BUT_bNum=BUT_bCheck(); } }
5
嵌入式应用软件园,版权所有,请勿转载/销售。
4
嵌入式应用软件园,版权所有,请勿转载/销售。
PORT_0|=0x40; nc=PORT_0&0x40; if(nc==0x40)//没有按键按下 { key_count=0;// 去抖变量清 0 keyover_time=c_keyover_time; } else { if(key_count==c_wobble_time)//去抖的时间结束则键值加 1. { key_value++; if(key_value==8) key_value=0; return key_value;//则键值加 1 } else { if(key_count>c_wobble_time)//进入连击状态. { key_count=0;//去抖变量清 0 keyover_time=c_keyquick_time;//将处于连击模式 } } } } /****************************************************************************** 函数名:main 输 入:无 输 调 描 出:无 用:BUT_bCheck() 述:只是为了编译的需要,用户可以删去。将 Check_key()用到自己的代码中。
/****************************************************************************** 声 明: 版权所有,嵌入式应用软件园。 此文件只限购买者个人使用,请勿在互联网中传播,如有侵权,将追究相应 责任。 如需单片机代码/技术支持,请访问:嵌入式应用软件园 ******************************************************************************/
如需源代码/此代码技术支持,请访请勿转载/销售。
第 3 章 按键用途
按键有很多类型,按键也是嵌入式应用中常用的元件。接触式的 按键,是通过识别其逻辑电平,来判断按键的按下还是抬起。 如果单片机的 IO 口自带上拉电阻,那么可以将按键直接接到一 个 IO 口上,而不需要再接上拉电阻。按键的另一端直接接地。这样, 按键按下后,读到的逻辑电平是 0,没有按下,读到的就是 1。
2
嵌入式应用软件园,版权所有,请勿转载/销售。
第 1 章 程序功能
我的按键程序中,按键是接在 P3.3 上的,P3 自带上接电阻。按 键在使用中, 必须去除抖动。 去除抖动可以通过软件和硬件两种方法。 这里使用软件方法。 按键的返回值, 用户可以自己选择的。 可以返回按键按下的次数, 按一下,次数加一,按着不放,次数会连续增加;也可以返回按键被 按下的标志,这个标志,可以持续一个 LOOP。 此代码,不仅可以用于单个按键,也可以用于多个按键。
键 的时间超 5 秒后,确认并返回键值。 ******************************************************************************/ byte BUT_bCheck(void) { static byte key_value=0;// 按键值初始键值 key_value=0 static byte key_count=0;//key_count 用于计数去抖 static word keyover_time=c_keyover_time; byte nc=0;//key_flag,进入按键设置的标志。
/****************************************************************************** 函数名:Check_key 输 入:无 输 调 描 出:返回键值 用: 述:按下按键 5 秒后,LED 数码管闪烁,松开按键后,每按一次转换一个数字,松开按
嵌入式应用软件园,版权所有,请勿转载/销售。
按键程序
作者: 嵌入式应用软件园
1
嵌入式应用软件园,版权所有,请勿转载/销售。
目
录
第 1 章 程序功能 ................................................................................... 3 第 2 章 按键程序 ................................................................................... 4 第 3 章 按键用途 ................................................................................... 7
3
嵌入式应用软件园,版权所有,请勿转载/销售。
第 2 章 按键程序
/****************************************************************************** 模 块: 文件名:Button.c 作 者:嵌入式应用软件园 修 订: 版本号 1.0 原因 初始版本
7