打印
[STM32F1]

求分析,我自己想了个新方法的矩阵键盘程序

[复制链接]
1350|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
freenes|  楼主 | 2015-7-5 17:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
新手学习中,感觉原来按键延时去抖和定时器去抖动都不太理想,就想了新的方法
具体思路如下:
1,依旧循环推挽排,当有按键按下时,下拉输入不为0,这跟经典矩阵键盘程序无异
2,设置一个按下累加变量,和一个松手递减变量,每次扫描有按下则累加变量自加,并刷新递减变量的初值比如500。同时,分辨键值。
3,如果松手或者抖动,则递减变量自减,到0则刷新按下第加变量为0,重新来过
4,如果累加变量超过一定值,比如8000,并且递减变量低于一定值,则表示按键有效并已经松手,则输出值
5,如果一直按下则递减变量不会低于一定值,而第加变量达到一个更大值则表示长按,则输出长按键值

现在的问题是,去抖效果很好,但4*4键盘中输出结果,列正确,排则可能是1、2、3、4排任意结果,而貌似晶振速度越快,错误率越大,就像推挽输出在排上有高电平残留一样,百思不得其解啊。怀疑过IO反转速度跟不上,但加了延时也没用。

虽然用定时器的方法写了另外一个用了,但这段程序是个心结,求高手帮分析,得知缘由方位安心吃饭

u8 Key_Row[]={0x01,0x02,0x04,0x08};
u8 Key_ValueTable[4] [4]={
                                                                                                                        {1,2,3,12},
                                                                                                                        {4,5,6,13},
                                                                                                                        {7,8,9,14},
                                                                                                                        {10,0,11,15}
                                                                                                                        };

u16 Key_Rank =0;
u8 Key_Row_Num;
u8 Key_Value;
u8 Key_Value2;
u16 Key_GrandTotal = 0;
u16 Key_Decline=500;

void MM_GPIO_Config(void);



int main(void)
{
        MM_RCC_HSI64();
        MM_GPIO_Config();
        MM_USART1_Config();
        while(1)
        {
                GPIOA->ODR =(GPIOA->ODR&0xfff0)|(u16)Key_Row[Key_Row_Num];//打开排,用数组循环

                Key_Rank = GPIOA->IDR;//读取端口状态
                Key_Rank &= 0x00f0;//只保留PA4~PA7
               

                if(Key_Rank != 0x0000)//如果不等于0,则表示有端口被拉高了
                {
                        switch (Key_Rank)//判断那个端口被拉高,并结合数组判断键值
                                {                                                                       
                                        case 0x0010 :
                                                Key_Value = Key_ValueTable[Key_Row_Num][0];
                                                break;
                                        case 0x0020 :
                                                Key_Value = Key_ValueTable[Key_Row_Num][1];
                                                break;
                                        case 0x0040 :
                                                Key_Value = Key_ValueTable[Key_Row_Num][2];
                                                break;
                                        case 0x0080 :
                                                Key_Value = Key_ValueTable[Key_Row_Num][3];
                                                break;
                                }
                       
                                        if(Key_GrandTotal < 65535)//防止变量溢出循环
                                        Key_GrandTotal ++ ;//计数被拉高轮询的次数
                                        Key_Decline =400;//按键按下时,每次都给松手抖动刷新初值
                }
                        else if(Key_Decline != 0) //松手减值,
                                        Key_Decline -- ;
                                else //if(Key_GrandTotal<8000)
                                        Key_GrandTotal =0;//如果减值到0了,加值也被清零,重新来过
                       

                        if((Key_GrandTotal > 4000)&&(Key_Decline < 300))//如果记录超过规定次数,表示按键确实按下,且在松手有段时间后执行输出
                {
                        //Key_ValueJudge(Key_Value);
                                printf("%d \r\n",Key_Value);

                        Key_GrandTotal = 0;//清零计数,避免下次错误进入
                }
                if(Key_GrandTotal > 60000)//如果大于规定值,则表示长按
                {
                        //Key_ValueJudge(Key_Value+100);
                                                        printf("%d \r\n",Key_Value+100);

                        Key_GrandTotal = 0;//清零计数,避免下次错误进入
                }
               
                Key_Row_Num ++ ;//排累加
                if(Key_Row_Num == 4)//到头循环
                        Key_Row_Num = 0;

        }
       
}
沙发
fanxsd| | 2015-7-5 23:31 | 只看该作者
顶一下 楼主的创作。感觉好复杂啊!

使用特权

评论回复
板凳
freenes|  楼主 | 2015-7-6 15:03 | 只看该作者
fanxsd 发表于 2015-7-5 23:31
顶一下 楼主的创作。感觉好复杂啊!

谢谢帮顶,期待高手分析

使用特权

评论回复
地板
snowflyin| | 2015-7-6 17:14 | 只看该作者
可用。Key_Row_Num没有初值

使用特权

评论回复
5
icecut| | 2015-7-6 19:59 | 只看该作者
用中断计数才能降低 cpu 利用率

使用特权

评论回复
6
freenes|  楼主 | 2015-7-6 20:52 | 只看该作者
icecut 发表于 2015-7-6 19:59
用中断计数才能降低 cpu 利用率

的确是,这个程序也是突然想到就写了,但偶尔出错,不知道为何就觉得总是个疙瘩

使用特权

评论回复
7
freenes|  楼主 | 2015-7-6 20:54 | 只看该作者
snowflyin 发表于 2015-7-6 17:14
可用。Key_Row_Num没有初值

不明您的意思,付了初值也是偶尔出错,可否再指点一二?

使用特权

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

本版积分规则

3

主题

12

帖子

0

粉丝