OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10642|回复: 13

5个IO口实现4*4矩阵键盘

[复制链接]

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
发表于 2014-5-29 17:37:07 | 显示全部楼层 |阅读模式
5金钱


如图,用这个原理图焊了一个4*4键盘,在写驱动的时候遇到了问题,按照网上的说法这个键盘的驱动原理是这样:
 首先,将端口PORT1~PORT5设置为输出,PORT6设置为中断输入,下降沿触发,并从PORT1~PORT5输出“1”。这样,在没有键按下时,三极管截止,PORT6输入“1”。
当有任何键按下时,三极管导通,PORT6输入由“1”变为“0”,也就是有一个下降沿输入,就会触发中断。
进入中断后,将PORT1置为输出,并输出“1”,PORT2~PORT5置为输入,然后读取PORT2~PORT6,
如果与PORT1连接的任一按键按下,PORT6将为“0”,同时:
如果按键S1按下则只有PORT5输入“1”,其余输入为“0”;
如果按键S6按下则只有PORT4输入“1”,其余输入为“0”;
如果按键S11按下则只有PORT3输入“1”,其余输入为“0”;
如果按键S16按下则只有PORT2输入“1”,其余输入为“0”;
如果按键S21按下则所有输入为“0”。
如果与PORT1连接的按键未按下,PORT6输入“1”。
其余的依此类推,这样就可确认是哪个按键按下了 

我这样写之后,发现在触发中断后进入中断处理要扫描首先就要重置IO口,我焊的4*4用PA0~3作为IO控制,PA4作为中断IO口,进入中断后将PA0先置为输出高,PA1~3置为输入0,这样判断PA4口是否为0,是的话在进行下一步,不是就直接重置下一个IO口为输出,问题出在重置了IO口之后按照网上以及个人的理解,由于CPU处理速度特别快,假如上图的S16按下,重置后PA0输出高,其他输入都为0,然后由于按键还没松开,所以PA2又会变为1,PA6应该一直为0,但是结果却是重置IO后,PA1的值为1,PA6的值也为1,其他都为0,所以得不到按键值,纠结了两天了,很后悔昨天就该来论坛问的,结果觉得论坛太慢,又耽误一天的时间,我已经用jtag和示波器调试了,结果就是我说的那样,并且用万用表都测过了硬件本身没问题,希望尽快有大神帮助解决。
下面附上源码
[mw_shl_code=c,true]/* ********************************************************************************************************* * Embedded Systems Building Blocks * Complete and Ready-to-Use Modules in C * * KEY 4*4 Module Driver * * (c) Copyright 2014, Fisher * * Filename : key44.c * Programmer : Fisher ********************************************************************************************************* * DESCRIPTION * * 这个模块提供5个IO口组成扩展的4*4键盘的驱动程序,能够很容易地扩展到更大的键盘模块 * 提供的接口: * 消耗的IO口:PA 0~3 4列下拉输入 * PA 4 中断IO口,上拉输入,下降沿触发 ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include "key44.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" u8 key = 16; /*$PAGE*/ /* ********************************************************************************************************* * 按键扫描函数 * * 描述: 此函数是按键识别的核心程序 * 参数: 无 * 返回值:按键值 ********************************************************************************************************* */ u8 MatrixKey_Decode() { u8 i = 0; u16 res = 0; /* 暂存读取的寄存器的值 */ for (i = 0; i < 4; i++) { GPIOA->CRL &= 0XFFFF0000; /* PA0~3设置成输入 */ GPIOA->CRL |= 0X00008888; GPIOA->ODR &= ~0X0F; /* PA0~3下拉 */ // GPIOA->ODR |= 1 << 4; /* PA4上拉 */ GPIOA->CRL |= 0X03 << (i * 4); /* PA(i)设置为输出模式     */ GPIOA->ODR |= 1 << i; /* PA(i)上拉 */ // delay_ms(1000); printf("i: %d \n",i); res = GPIOA->ODR; printf("res: %x \n",res); if (PORT_EXIT == 1) continue; /* 按键不在当前列 */ res &= 0X0F; /* 得到PA0~3的值 */ res &= ~(1 << i); /* 将输出口的值清零 */ switch (res) { // case 0: return ((3 - i) * 4 + i); /* 行列值相等,处于矩阵键盘对角线上 */ case 1: return (0 * 4 + i); /* 第一行 */ case 2: return (1 * 4 + i); /* 第二行 */ case 4: return (2 * 4 + i); /* 第三行 */ case 8: return (3 * 4 + i); /* 第四行 */ } } return 16; } /*$PAGE*/ /* ********************************************************************************************************* * 中断4服务程序 * * 描述: 此函数为中断4的服务程序 * 参数: 无 * 返回值:无 ********************************************************************************************************* */ void EXTI4_IRQHandler(void) { delay_ms(10); /* 消抖 */ LED_GRE = !LED_GRE; /* 这里为中断处理的部分 */ key = MatrixKey_Decode(); delay_ms(200); LED_GRE = !LED_GRE; /* ** 重新设置中断IO上拉输入 以及其他IO输出高, ** 注意这几句必须放在清除中断标志位之前,否则会出现进入中断后出不去的现象 */ GPIOA->CRL &= 0XFFF00000; GPIOA->CRL |= 0XFFF83333; /* PA0~3设置成输出 PA4输入 */ GPIOA->ODR |= 0X1F; /* PA0~3默认输出高 PA4上拉输入 */ EXTI->R = 1 << 4; /* 清除LINE4上的中断标志位 */ } /* ********************************************************************************************************* * 中断初始化程序 * * 描述: 此函数为中断4初始化程序,初始化PA4为中断输入. * 参数: 无 * 返回值:无 ********************************************************************************************************* */ void EXTIX_Init(void) { RCC->APB2ENR |= 1 << 2; /* 使能PORTA时钟 */ JTAG_Set(JTAG_SWD_ENABLE); /* 关闭JTAG和SWD */ GPIOA->CRL &= 0XFFF00000; GPIOA->CRL |= 0XFFF83333; /* PA0~3设置成输出 PA4输入 */ GPIOA->ODR |= 0X1F; /* PA0~3默认输出高 PA4上拉输入 */ Ex_NVIC_Config(GPIO_A, 4, FTIR); /* 下降沿触发 */ MY_NVIC_Init(2, 1, EXTI4_IRQChannel, 2); /* 抢占2,子优先级1,组2 */ } [/mw_shl_code]
还有就是进入按键处理那个函数的for循环的第一句执行之后,PA4就会由0变为1,我都没设置PA4啊这一步,不知道怎么会影响到它的,希望弄过的帮忙解决一下,唉

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-5-29 22:27:36 | 显示全部楼层
是不是有外部电路,将PA4拉高了?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
 楼主| 发表于 2014-5-30 01:32:20 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
我搭在示波器上调试了,一运行for循环里面那一句就会出现PA4变高,可是我电路图完全按照那个图练的,我用万用表测了,按键按下的时候IO口状态都正确啊,就是运行代码这里就会出问题,是什么原因呢,难道没人做过这种键盘吗
回复

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
 楼主| 发表于 2014-5-30 10:34:42 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
我想了一下你说的,每次执行完那一句之后0~3IO口重置,这个时候如上图,S16处于按下状态,那么本应该P1输出高,P2输入高,P6输入低,但是现在实际情况是P1输出高,P2输入低,P6输入高(P6由0跳变道1),那么也就是说执行完那一句之后IO口状态呗重置,并且即使按键还处于按下的状态,P1输出的高电平也通不到P2那里和三极管那里,这是什么原因
回复

使用道具 举报

1

主题

93

帖子

0

精华

初级会员

Rank: 2

积分
194
金钱
194
注册时间
2014-3-12
在线时间
9 小时
发表于 2014-5-30 20:47:35 | 显示全部楼层
6个IO实现25个按键的扫描:
http://wenku.baidu.com/view/ca55abf8c8d376eeaeaa3160.html
功夫再高、也怕羊刀
回复

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
 楼主| 发表于 2014-5-30 21:10:38 | 显示全部楼层
回复【5楼】加速度:
---------------------------------
很感谢共享的资料,不过这里面的25个按键是按扫描法来的,和我这个原理图不一样,我这个是一个作为中断口的,
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-5-31 00:56:06 | 显示全部楼层
回复【4楼】Fisher:
---------------------------------
你测量下各个IO的电平状态吧。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

93

帖子

0

精华

初级会员

Rank: 2

积分
194
金钱
194
注册时间
2014-3-12
在线时间
9 小时
发表于 2014-5-31 11:01:58 | 显示全部楼层
回复【6楼】Fisher:
---------------------------------
共同学习~
功夫再高、也怕羊刀
回复

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
 楼主| 发表于 2014-5-31 11:20:34 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
测了啊,就是执行到中断里面重置IO后电平就会跳转,但是按理说重置的时候我PA0~3都先设为0,然后在从PA0到PA4设置为1,所以这里应该所有电平都会先跳转到0,然后有一个在跳转为1,但是其他都跳转为0了,按键所在的那一列(比如PA0)却一直是高电平,难道是因为CPU太快了?重置后比如按下的是S16,那么PA1,2都应该是高电平,而我测得只有PA1是高,PA1输出高但是在按键这里却不通,不知道为什么
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-5-31 22:25:06 | 显示全部楼层
回复【9楼】Fisher:
---------------------------------
 我看你代码貌似可以啊(输出1),不能输出1,得检查下硬件了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

6

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2013-9-15
在线时间
0 小时
 楼主| 发表于 2014-5-31 22:36:00 | 显示全部楼层
回复【10楼】正点原子:
---------------------------------
可是我用万用表测电压又没问题,纠结啊
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2015-4-28
在线时间
0 小时
发表于 2015-5-20 17:57:29 | 显示全部楼层
回复【11楼】Fisher:
---------------------------------
楼主,你解决你说的问题了吗?好期待你的正解啊
热心,笨
回复

使用道具 举报

0

主题

19

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2015-5-13
在线时间
1 小时
发表于 2015-5-29 14:23:42 | 显示全部楼层
回复【3楼】Fisher:
---------------------------------你好,你这个问题解决了吗?
回复

使用道具 举报

0

主题

7

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1064
金钱
1064
注册时间
2015-11-12
在线时间
105 小时
发表于 2015-11-12 09:21:41 | 显示全部楼层
这个按键电路及程序花了半天时间已调通
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 05:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表