单片机按键程序

合集下载

单片机51 去抖按键程序

单片机51 去抖按键程序
#define STOP_TIMER0 TR0=0
#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 ;

单片机按键-长按-短按-连发-双击-抬起-按下

单片机按键-长按-短按-连发-双击-抬起-按下
KeyAttribute_TypeDef KeyAttributeZero;
/******************************************************************************** 功能:获取按键状态 参数:无 返回值:按键状态 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单片机使用状态机的键盘程序

51单片机使用状态机的键盘程序
break;
}
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单片机按键长按短按效果源程序

基于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表示从第一个显示。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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
相关文档
最新文档