标题:
一种全新的单片机按键程序写法思路,请大家指教,点评
[打印本页]
作者:
2448289424
时间:
2019-7-21 01:11
标题:
一种全新的单片机按键程序写法思路,请大家指教,点评
最近帖子已经有人在此提到充分利用CPU中断的重要性,,再次我就不要说了。此按键demo支持短按,长按,多个按键同时按下,由于是用扫描的方式,各个按键的按下和松独立处理,不互相干扰,避免要按键死等的情况。对于特殊的按键消抖时间可单独一条线扫描检测。。由于是各个按键,一位位检测,检测到一位就进行处理,之后再进行处理下一位,所以有先后顺序。废话不多说,下面讲思路,有错误的地方大家可以一起学习,探讨,,,,,,,,
按键的最终状态无非就两种,按下或者松开。我用的是STC8单片机,现在的一些增强型或许新型号应该内部都有上拉电阻,,所以我们是按键低电平触发。
对于只作为输入口用于按键检测,,我们可以默认他的IO口状态,不要去操作IO寄存器,,,(如果是即作为输入又作为输出的话,,在读取状态的时候记得先写1,延时2个NOP,再去读,保证读取的准确性),,假设按键没按下去默认就是1了,按键按下去就是0,也就是1->0的过程,,松开的话就是0->1,恢复到最初状态。这里就有两个变化1->0,和0->1,,理解这个之后我们就定义两个变量 value 变化值 buf 最终状态值 我们两个变化1->0,和0->1进行异或就是1,,说明了按键有按下或松开的动作,我们就去执行对应的函数,,执行完后按键的最终只buf也跟着更新,也就是0(按下) 1(松开),,(一直按下的过程)此时端口值0 和buf0 异或就是0 ,咱就不再去执行按键按下的程序,,(松开后的过程)此时端口值1 和buf1 异或就是0 ,咱就不再去执行按键松开的程序,,这样就保证了按下 或者松开 只执行一次动作,,因此加入一些标志位。,结合中断就可以做一些长按功能了。提供的demo里有做了一个实例是长按2秒开关蜂鸣器,,其他的按键按下或者松开的子函数用户自己增加自己需要的功能,,里面只是写了一些简单的点灯功能用于调试,,自己验证了一下程序是可行,,所以提供出来,,大部分都有注释,看看有什么不足之处,在进行修改,,后面会在此基础加入矩阵扫描,原理一样,接着进一步完善demo,做成一个能实现操作常见的外设demo出来,,程序不足之处多多见谅,大家多多批评,一起学习,,,,,下面按键的流程图,也不知道这个画得不到,老感觉自己的表达能力有待提高,,或者也会多发贴,把自己的一些表达能力加强,,
按键流程图.png
(104.75 KB, 下载次数: 74)
下载附件
按键流程图
2019-7-21 01:09 上传
1 file文件夹为项目的硬件端口表 功能书 原理图等资料
2 inc文件 为系统配置文件
3 lib文件 各个外设文件
4 program文件 为项目文件
单片机源程序如下:
#include<stc8.h>
#include <intrins.h>
sbit led1=P0^4;
sbit led2=P0^5;
sbit led3=P0^6;
sbit led4=P0^7;
sbit led5=P1^3;
sbit led6=P1^4;
sbit led7=P1^5;
sbit led8=P1^6;
sbit beep=P1^7;
#define D_ScanLine 2 //定义扫描线的数量,
#define D_ESTTime 10 //单位ms,消除抖动时间。实际以为你外设消抖时间为准
#define P0_key 0xFc //定义用到的端口按键(低电平有效,用到p00 p01)
//#define P1_key 0x00 //定义用到的端口按键(低电平有效,用到8个)
#define P2_key 0x00 //定义用到的端口按键(低电平有效,用到8个)
//#define P3_key 0x00 //定义用到的端口按键(低电平有效,用到8个)
u8 R_key_buf[D_ScanLine]; //定义存储每一行按键变化后最终的数值
u8 R_key_value[D_ScanLine]; //定义存储每一行按键变化中的数值
u8 R_key_douce; //按键消抖时基
u8 R_key_num; //按键编号(对应各个按键函数)
u8 D_ScanLineDec; //当前扫描线
u8 beep_flag; //蜂鸣器标志
u16 beep_time; //计时
//按键消抖
void F_key_douce()
{
if(R_key_douce!=0)
{
R_key_douce=R_key_douce-1;
}
}
//蜂鸣器计时
void F_beep_time()
{
if(beep_flag==1)
{
if(beep_time!=0)
beep_time=beep_time-1;
}
}
//蜂鸣器检测
void F_beep_check()
{
if(beep_flag==1)
{
if(beep_time==0)
{
beep=~beep ;
beep_flag=0;
}
}
}
//对应按键按下子函数
void F_key1_dn()
{
led1=~led1;
}
void F_key2_dn()
{
led2=~led2;
}
void F_key3_dn()
{
led3=~led3;
}
void F_key4_dn()
{
led4=~led4;
}
void F_key5_dn()
{
}
void F_key6_dn()
{
}
void F_key7_dn()
{
}
void F_key8_dn()
{
}
void F_key9_dn()
{
led5=~led5;
}
void F_key10_dn()
{
led6=~led6;
}
void F_key11_dn()
{
led7=~led7;
}
void F_key12_dn()
{
led8=~led8;
}
void F_key13_dn()
{
beep_flag=1;
beep_time=0x07d0; //2秒
}
void F_key14_dn()
{
}
void F_key15_dn()
{
}
void F_key16_dn()
{
}
//------------------------------------------------------
//对应按键松开子函数
void F_key1_up()
{
}
void F_key2_up()
{
// R_key_num=8;
// led=~led;
}
void F_key3_up()
{
// R_key_num=8;
// led=~led;
}
void F_key4_up()
{
// R_key_num=8;
// led=~led;
}
void F_key5_up()
{
// R_key_num=8;
// led=~led;
}
void F_key6_up()
{
// R_key_num=8;
// led=~led;
}
void F_key7_up()
{
// R_key_num=8;
// led=~led;
}
void F_key8_up()
{
// R_key_num=8;
// led1=~led1;
}
void F_key9_up()
{
// R_key_num=8;
// led1=~led1;
}
void F_key10_up()
{
// R_key_num=8;
// led=~led;
}
void F_key11_up()
{
// R_key_num=8;
// led=~led;
}
void F_key12_up()
{
// R_key_num=8;
// led=~led;
}
void F_key13_up()
{
beep_flag=0;
beep_time=0x07d0; //2秒
}
void F_key14_up()
{
// R_key_num=8;
// led=~led;
}
void F_key15_up()
{
// R_key_num=8;
// led=~led;
}
void F_key16_up()
{
// R_key_num=8;
// led=~led;
}
//按键按下总函数
void key_dn()
{
switch(R_key_num+1)
{
case 1:
F_key1_dn();
break;
case 2:
F_key2_dn();
break;
case 3:
F_key3_dn();
break;
case 4:
F_key4_dn();
break;
case 5:
F_key5_dn();
break;
case 6:
F_key6_dn();
break;
case 7:
F_key7_dn();
break;
case 8:
F_key8_dn();
break;
case 9:
F_key9_dn();
break;
case 10:
F_key10_dn();
break;
case 11:
F_key11_dn();
break;
case 12:
F_key12_dn();
break;
case 13:
F_key13_dn();
break;
case 14:
F_key14_dn();
break;
case 15:
F_key15_dn();
break;
case 16:
F_key16_dn();
break;
default:
break;
}
}
//按键松开总函数
void key_up()
{
switch(R_key_num+1)
{
case 1:
F_key1_up();
break;
case 2:
F_key2_up();
break;
case 3:
F_key3_up();
break;
case 4:
F_key4_up();
break;
case 5:
F_key5_up();
break;
case 6:
F_key6_up();
break;
case 7:
F_key7_up();
break;
case 8:
F_key8_up();
break;
case 9:
F_key9_up();
break;
case 10:
F_key10_up();
break;
case 11:
F_key11_up();
break;
case 12:
F_key12_up();
break;
case 13:
F_key13_up();
break;
case 14:
F_key14_up();
break;
case 15:
F_key15_up();
break;
case 16:
F_key16_up();
break;
default:
break;
}
}
void Keyscan_task()
{
u8 ar;
u8 ax;
u8 i;
D_ScanLineDec=D_ScanLineDec+1;
if(D_ScanLineDec==1) //扫描第一条线
{
ar=P0;
ax=P0_key;
ar=ar^ax;
ar=ar|ax; //获取按键值
}
if(D_ScanLineDec==2) //扫描第二条线
{
ar=P2;
ax=P2_key;
ar=ar^ax;
ar=ar|ax; //获取按键值
}
ax=R_key_value[D_ScanLineDec-1]; //跟变化的按键值比较
ax=ar-ax;
if(ax!=0) //不等于0说按键有动作(按下或者松开)
{
R_key_value[D_ScanLineDec-1]=ar; //记录当前的按键值,然后进行消抖
R_key_douce=D_ESTTime; //设置消抖时间
D_ScanLineDec=D_ScanLine; //重新更新扫描线,重新开始扫描
}
else
{
if(R_key_douce==0) //中断消抖,,判断消抖时间到了?
{
ax=R_key_buf[D_ScanLineDec-1]; //把按键变化后值拿出来
ar=R_key_value[D_ScanLineDec-1]; //把变化中的按键值拿出来
ar=ar^ax;
if(ar!=0) //按键发生变化 ar
{
ax=ar&ax;
if(ax!=0) //按键按下
{
for(i=0;i<8;i ++)
{
ax=(ar>>i)&1; //取出具体是哪一位的按键有变化,一次只取一位
if(ax==1)
{
R_key_num=i;
ar=0x01<<i;
R_key_buf[D_ScanLineDec-1]=R_key_buf[D_ScanLineDec-1]^ar; //保存最终的按键值
R_key_value[D_ScanLineDec-1]=R_key_buf[D_ScanLineDec-1]; //保存最终的按键变化值
for(ar=1;ar<=D_ScanLineDec-1;ar++)
{
R_key_num=R_key_num+8;
}
key_dn();
}
}
}
else //按键松开原理同按键按下一样
{
for(i=0;i<8;i ++)
{
ax=(ar>>i)&1;
if(ax==1)
{
R_key_num=i;
ar=0x01<<i;
R_key_buf[D_ScanLineDec-1]=R_key_buf[D_ScanLineDec-1]^ar; //保存最终的按键值
R_key_value[D_ScanLineDec-1]=R_key_buf[D_ScanLineDec-1];
for(ar=1;ar<=D_ScanLineDec-1;ar++)
{
R_key_num=R_key_num+8;
}
key_up();
}
}
}
}
else
{
} /////按键没按下
}
}
}
void F_Keyscan()
{
D_ScanLineDec=0;
while(D_ScanLine-D_ScanLineDec)
{
Keyscan_task();
}
}
void F_Key_buf_value_init()
{
u8 i;
for(i=0;i<D_ScanLine;i ++)
{
R_key_buf[i]=0xff;
R_key_value[i]=0xff;
}
}
复制代码
所有程序51hei打包下载:
STC8 实验3 -按键.rar
(92.31 KB, 下载次数: 19)
2019-7-21 01:11 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
鹏博士PBs
时间:
2019-7-21 10:33
希望可以更简单明了一些
作者:
2448289424
时间:
2019-7-21 14:59
鹏博士PBs 发表于 2019-7-21 10:33
希望可以更简单明了一些
程序上还可以在优化一下,但这个按键思路跟常见的按键触发方法比,我觉得是是比较好的,嘻嘻
作者:
tieq1952
时间:
2019-7-22 07:10
谢谢分享!!!
作者:
zhuyuye
时间:
2019-7-22 08:38
NICE!!!!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1