关于按键去抖等的一些问题,基础(附完整代码、注释)

嘤鸣求友 2013-03-27 09:53:42
/******************************************************************************
XWWK-CC2530A模块按键测试程序
Filename: CC2530KeyTest.c
Target: cc2530
Revised: 2012-01
Revision: 1.0
Description:

问题:两个按键控制不同灯的状态,但是必须轮流按,才起作用,也即是说,单独按一个键,只执行一次。
备注:每个按键我都独立测试过的,硬件上没有问题,独立测试也都可以实现相应功


******************************************************************************/

#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制灯的端口
#define RLED P1_0 //定义LED1为P10口控制
#define GLED P1_1 //定义LED2为P11口控制
//#define KEY1 P1_2 //定义按键为P12口控制(配置XWWk供电底板)

#define KEY1 P0_1
#define KEY2 P2_0
#define KEY3 P1_2

//函数声明
void Delay(uint); //延时函数声明
void InitIO(void); //初始化函数声明
void InitKey(void); //初始化按键函数声明
uchar KeyScan(void); //按键扫描函数声明

uchar Keyvalue = 0 ; //定义变量记录按键动作
uint KeyTouchtimes = 0 ; //定义变量记录按键次数
/****************************
//延时
*****************************/
void Delay(uint n)
{
uint i;
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
}
/****************************
//按键初始化
*****************************/
void InitKey(void)
{
P0SEL &= ~0x01;//按键K1
P0DIR &= ~0x01;
P0INP |= 0x01;

P2SEL &= ~0x00;//按键K2
P2DIR &= ~0x00;
P2INP |= 0x00;

P1SEL &= ~0x04;//按键K3
P1DIR &= ~0x04;
P1INP |= 0x04;



}
/****************************
//初始化程序,将P10、P11、P14定义为输出口,并将LED灯初始化为灭
*****************************/
void InitIO(void)
{
P1DIR |= 0x03; //P10、P11 定义为输出
RLED = 0;
GLED = 0;

}
/*****************************************
//按键动作记录函数
*****************************************/
uchar KeyScan(void)
{
if(KEY1 == 1) //高电平有效
{
Delay(100); //检测到按键
if(KEY1 == 1)
{
while(KEY1); //直到松开按键
return(1);
}
}


if(KEY2 == 1) //高电平有效
{
Delay(100); //检测到按键
if(KEY2 == 1)
{
while(KEY2); //直到松开按键
return(2);
}
}

if(KEY3 == 1) //高电平有效
{
Delay(100); //检测到按键
if(KEY3 == 1)
{
while(KEY3); //直到松开按键
return(3);
}
}

return(0);
}
/***************************
//主函数
***************************/
void main(void)
{
InitIO(); //初始化LED灯控制IO口
InitKey(); //初始化按键控制IO口
while(1)
{
Keyvalue = KeyScan(); //读取按键动作

if(Keyvalue == 1) //按下按键设置为LED3,LED2,LED1倒序流水闪烁
{
GLED = !GLED;
Delay(20000);
// RLED = !RLED;
// Delay(20000);
InitKey();
}

if(Keyvalue == 2) //按下按键设置为LED3,LED2,LED1倒序流水闪烁
{
GLED = !GLED;
Delay(20000);
RLED = !RLED;
Delay(20000);
InitKey();
}


}
}




感谢各位了~
...全文
574 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
xqhrs232 2013-04-11
  • 打赏
  • 举报
回复
好东西,学习了
ymm198606 2013-04-09
  • 打赏
  • 举报
回复
可以将检测按键的IO口配置成外部中断模块,当中断到来时,在中断函数中先进行一定时间的延时,等延时完再去判断当前按键是否处在按键按下的有效状态,如还处在有效状态,则一次按键有效;按键判断较准,误判、漏判几率较少; 缺点:需同时配置3个外部中断;
C_ROOKIES 2013-04-06
  • 打赏
  • 举报
回复
那样你觉得用着方便就写那样,实际写的时候可以用好的示波器看看到底按键按下的时候抖动是多少,多久,网上盛传的不是很准确!
syc62 2013-04-03
  • 打赏
  • 举报
回复
楼主,,小弟我也因为消抖遇到了很大的问题。。。。查了很久才发现是按键按坏了,还有消抖不彻底。。。。不过,用delay方法太浪费时间了。。。。
默寞 2013-03-29
  • 打赏
  • 举报
回复
楼上的对消抖的建议都不错 不过LZ的问题好像不在这 LZ看一下你的Keyvalue变量,该变量只在有键按下时!=0一次,其他情况下都为0,所以你的灯的状态变化只执行一次 可以初始化时先让Keyvalue = 0;然后根据按键给Keyvalue赋其他值并一直保持
of123 2013-03-29
  • 打赏
  • 举报
回复
去抖动有两类方法:

1 采用延时

这种方法的优点是简单易懂。缺点是处理任务比较复杂的应用时,会影响后台例程的运行。比如,人机交互有迟滞感等。

2 采用定时器中断方式

在中断服务中扫描按键,并与公共变量保存的键码比较。

如果发现键状态改变,将一个公共变量清零,更新键码。
如果发现状态持续,累加公共变量。
如果公共变量达到计数阈值(与定时器间隔相乘,就是延迟的时间),就触发按键事件(例如调用键处理例程)。

优点是不影响轮询方式处理的后台事务。并且,也可以和其他定时事件(例如 LED 灯闪烁,也使用一个计数器变量控制灯状态)共用定时器。

缺点是比较复杂。
pnr 2013-03-29
  • 打赏
  • 举报
回复
学习了~
power_mcu 2013-03-28
  • 打赏
  • 举报
回复
不要用延时方法去抖动,这是学校教授的做法。用定时器计时去抖动。
woshi_ziyu 2013-03-27
  • 打赏
  • 举报
回复
if(KEY1 == 1) //高电平有效 { Delay(100); //检测到按键 if(KEY1 == 1) { while(KEY1); //直到松开按键 return(1); } } 去抖可以不用延时 用计数的方法
RACWIN 2013-03-27
  • 打赏
  • 举报
回复
帮顶起来!!1
嘤鸣求友 2013-03-27
  • 打赏
  • 举报
回复
问题在开始的注释里: 问题:两个按键控制不同灯的状态,但是必须轮流按,才起作用,也即是说,单独按一个键,只执行一次。 备注:每个按键我都独立测试过的,硬件上没有问题,独立测试也都可以实现相应功。

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧