打印
[51单片机]

一个关于按键扫描程序的问题

[复制链接]
2651|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
anazel|  楼主 | 2016-7-14 18:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
xyz549040622| | 2016-7-14 22:42 | 只看该作者
按键要灵敏,必须放在中断中。定时器扫描。

使用特权

评论回复
板凳
ayb_ice| | 2016-7-15 06:22 | 只看该作者
去掉毫秒以上的延时,而且保持功能正常,就差不多算入门吧

使用特权

评论回复
地板
McuPlayer| | 2016-7-15 07:29 | 只看该作者
重点是控制好循环周期,特别要记得键盘扫描不要用Delay的方式做消抖

使用特权

评论回复
5
anazel|  楼主 | 2016-7-15 16:45 | 只看该作者
xyz549040622 发表于 2016-7-14 22:42
按键要灵敏,必须放在中断中。定时器扫描。

是利用定时器中断每隔一定时间去扫描一下键盘吗?

使用特权

评论回复
6
lnulibin| | 2016-7-15 18:02 | 只看该作者
xyz549040622 发表于 2016-7-14 22:42
按键要灵敏,必须放在中断中。定时器扫描。

说的对。
按键要灵敏必须放在中断中,定时扫描。得到键码。
后台WHILE中对键码进行处理。

使用特权

评论回复
7
xyz549040622| | 2016-7-15 19:20 | 只看该作者
anazel 发表于 2016-7-15 16:45
是利用定时器中断每隔一定时间去扫描一下键盘吗?

对,一般用状态机来实现,可以坛子里搜索下菜农的零耗时按键。

使用特权

评论回复
8
ningling_21| | 2016-7-16 08:40 | 只看该作者
anazel 发表于 2016-7-15 16:45
是利用定时器中断每隔一定时间去扫描一下键盘吗?

可以用中断也可以不用中断,不用中断时不要用延时去消抖

使用特权

评论回复
9
anazel|  楼主 | 2016-8-2 10:42 | 只看该作者
写了个3*3矩阵扫描程序,然后设定了一个定时中断,中断中每10ms调用一次按键扫描程序,可是出现一个问题,由于仪表是用的液晶屏显示,用中断扫描按键的话液晶屏不能显示东西了,现在只能取消定时中断,把按键扫描程序放在主程序的while循环中,由于按键扫描程序中有个2ms的消抖,感觉这样很占用主程序的时间,有没有其他的解决办法呢?

使用特权

评论回复
10
AKKan| | 2016-8-2 13:06 | 只看该作者
采用中断吧

使用特权

评论回复
11
anazel|  楼主 | 2016-8-2 14:04 | 只看该作者

我试过用定时器中断,每10ms调用一次按键扫描函数,但液晶屏不能正常显示了。

使用特权

评论回复
12
w1a2n3g4| | 2016-8-2 15:23 | 只看该作者
程序贴出来分析

使用特权

评论回复
13
anazel|  楼主 | 2016-8-2 19:40 | 只看该作者
本帖最后由 anazel 于 2016-8-2 19:41 编辑

很普通的矩阵按键扫描程序
/**************************************************************************/
//按键处理函数
//返回按键值
//mode:0 不支持连续按  1,支持连续按
//返回值0:没有然后按键按下
/**************************************************************************/

u16 keyscan(u8 mode)  //实现矩阵键盘。返回值为各按键的键值,此键值由用户自己定义。
{
        u16 KeyVal;         //keyVal为最后返回的键值。
        
        GPIO_Write(GPIOC,(GPIOC->ODR & 0xfff8 | 0x0007)); //先让PC0,PC1,PC2全部输出高。
        
        if((GPIOC->IDR & 0x0070)==0x0000)  //如果PC4,PC5,PC6全为0,则没有键按下。此时,返回值为0.
        {
                return 0;
        }
        else
        {        
            delay_ms(2);    //延时2ms去抖动。
            if((GPIOC->IDR & 0x0070)==0x0000)//如果延时2ms后,PC4到PC6又全为0,则,刚才引脚的电位变化是抖动产生的.
                //key_up = 1;
            return 0;
        }
        
                 
        GPIO_Write(GPIOC,(GPIOC->ODR & 0xfff8 | 0x0001));//让PC2,PC1,PC0输出二进制的001.
        
        switch(GPIOC->IDR & 0x0070)//对PC4,PC5,PC6的值进行判断,以输出不同的键值。
        {
                case 0x0010: KeyVal = 1; break;
                case 0x0020: KeyVal = 2; break;
                case 0x0040: KeyVal = 3; break;
        }
        

        GPIO_Write(GPIOC,(GPIOC->ODR & 0xfff8 | 0x0002));        //让PC2,PC1,PC0输出二进制的010.

        switch(GPIOC->IDR & 0x0070)//对PC4,PC5,PC6的值进行判断,以输出不同的键值。
        {
                case 0x0010: KeyVal=4;  break;
                case 0x0020: KeyVal=5;        break;
                case 0x0040: KeyVal=6;        break;
        }
        
        
        GPIO_Write(GPIOC,(GPIOC->ODR & 0xfff8 | 0x0004));        //让PC2,PC1,PC0输出二进制的100.
        
        switch(GPIOC->IDR & 0x0070)//对PC4,PC5,PC6的值进行判断,以输出不同的键值。
        {
                case 0x0010: KeyVal=7;  break;
                case 0x0020: KeyVal=8;        break;
                case 0x0040: KeyVal=9;        break;
        }
        
        GPIO_Write(GPIOC,(GPIOC->ODR & 0xfff8 | 0x0007)); //先让PC0,PC1,PC2全部输出高。
        
        if (!mode)
        {
                while(GPIOC->IDR & 0x0070);   //如果有键被按下就一直等待
        }
        
        if (KeyVal == 1) SetTime_Flag = 1;
        else if (KeyVal == 3) SetFunction_Flag = 1;
        return KeyVal;               
}

里面有个2ms的消抖延时。

使用特权

评论回复
14
像风儿一样清| | 2016-8-3 15:27 | 只看该作者
总感觉你延时消抖的时间太短了

使用特权

评论回复
15
anazel|  楼主 | 2016-8-3 17:08 | 只看该作者
像风儿一样清 发表于 2016-8-3 15:27
总感觉你延时消抖的时间太短了

经过验证使用正常。

使用特权

评论回复
16
oayzw| | 2016-8-4 11:26 | 只看该作者
把键盘扫描时序、状态图画出来,软件实现很简单,扫描里也不用延时的

使用特权

评论回复
17
ywlzh| | 2016-8-5 16:28 | 只看该作者
实在不想纠结,搞个QP状态机,让软件生成源代码

使用特权

评论回复
18
anazel|  楼主 | 2016-8-5 21:20 | 只看该作者
oayzw 发表于 2016-8-4 11:26
把键盘扫描时序、状态图画出来,软件实现很简单,扫描里也不用延时的

看来只有用状态机才能解决延时问题了。

使用特权

评论回复
19
anazel|  楼主 | 2016-8-15 10:02 | 只看该作者
用状态机的按键扫描程序写出来了,可是有个问题,每10ms进入一次中断调用KeyScan()函数,返回键值,这种用法在小的程序中按键都很灵敏,但我的while程序比较大,因为要显示很多东西,但液晶屏的速度比较慢,这样造成while循环一次时间比较长,还是及时检测不到键值进行处理,这种情况有什么好的办法解决吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

448

帖子

2

粉丝