搜索
bottom↓
回复: 6

github上4个IO扫12键方法,可测任意组合键,不懂示意图附猜想

[复制链接]

出0入0汤圆

发表于 2013-1-4 02:09:50 | 显示全部楼层 |阅读模式
本帖最后由 fish47 于 2013-1-4 12:58 编辑

项目说明
This is a small example to show how to decode a
12-button matrix using only 4 I/O pins of a microcontroller.
One key consists of a switch and a diode.
All combination of simultaneously pressed keys can be decoded.

项目地址
https://github.com/vogelchr/avr-matrix

电路+扫描方法
二楼有相关代码


请不要看我的下面猜想电路图,以免先入为主,如果你能想出示意图具体所指电路,请分享,谢谢。

我的猜想图


但貌似这是不能检测任意组合键,留意下图


假如同时按下的键是 红+黑,在第二轮扫描,由于粉红色通路,会出现误判,效果就像把 蓝 键也按下一样。

还有,我感觉上面的源码第71行,应该是
  1. c >>= (KBD_P0-1);
复制代码
不知道是不他写错。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2013-1-4 08:23:26 | 显示全部楼层
本帖最后由 hefq 于 2013-1-4 08:50 编辑
  1. #ifndef _MATRIX2_H_
  2. #define _MATRIX2_H_
  3. #include <stdint.h>
  4. /* see drawing in matrix2.c */
  5. /* bits set in return of matrix2_scan for   the indicated buttons */
  6. #define MATRIX2_A   0x2000
  7. #define MATRIX2_B   0x4000
  8. #define MATRIX2_C   0x8000
  9. #define MATRIX2_D   0x0100
  10. #define MATRIX2_E   0x0400
  11. #define MATRIX2_F   0x0800
  12. #define MATRIX2_G   0x0010
  13. #define MATRIX2_H   0x0020
  14. #define MATRIX2_I   0x0080
  15. #define MATRIX2_J   0x0001
  16. #define MATRIX2_K   0x0002
  17. #define MATRIX2_L   0x0004
  18. uint16_t
  19. extern matrix2_scan(void);
  20. #endif
复制代码
  1. #include "matrix2.h"
  2. #include <avr/io.h>
  3. #define KBD_PORT    PORTC
  4. #define KBD_PIN     PINC
  5. #define KBD_DDR     DDRC
  6. #define KBD_P0      1
  7. #define KBD_MASK    (_BV(KBD_P0)|_BV(KBD_P0+1)|_BV(KBD_P0+2)|_BV(KBD_P0+3))
  8. /* This function is scanning a key matrix connected to four IO ports
  9. * in the following way:
  10. *
  11. *           +------------------------------------+
  12. *           | +-------------------------+        |
  13. *           | | +--------------+        |        |
  14. *           | | | +---+        |        |        |
  15. *           | | | |   |        |a       |b       |c
  16. *   (P0)----|-|-|-+---|--------X--------X--------X
  17. *           | | |     |d       |        |e       |f
  18. *   (P1)----|-|-+-----X--------|--------X--------X
  19. *           | |       |g       |h       |        |i
  20. *   (P2)----|-+-------X--------X--------|--------X
  21. *           |         |j       |k       |l         
  22. *   (P3)----+---------X--------X--------X
  23. *
  24. *   The keys are marked by X, they consist of a push
  25. *   button and a diode,e.g.:
  26. *
  27. *         (b)
  28. *          |                           _|_
  29. *    (a)---X--- is equivalent to (a)---o o--|<|--(b)
  30. *          |
  31. *
  32. *   The port bits have to be consecutive, starting at
  33. *   the bit number KBD_P0, the port has to be adjusted
  34. *   in the defines above, e.g. for port C1..C4 define
  35. *   KBD_PIN to be PINC, KBD_DDR to be DDRC, KBD_PORT to
  36. *   be KBD_PORTC and KBD_P0 to be 1.
  37. *
  38. *   The return value of this function will be a 16bit word
  39. *   with 12 bits corresponding to the indicated key
  40. *   locations, 4 bits are constantly 0:
  41. *
  42. *
  43. */
  44. uint16_t
  45. matrix2_scan(void){
  46.         uint16_t ret=0;
  47.         uint8_t bit=_BV(KBD_P0);
  48.         uint8_t c;
  49.         do {
  50.                 ret <<= 4;
  51.                 KBD_PORT = ((KBD_PORT |  KBD_MASK  ) & (~bit));
  52.                 KBD_DDR  = ((KBD_DDR  & (~KBD_MASK)) |   bit );
  53.                 /* the internal pullups are too weak for my
  54.                    slow diodes, therefore I wait for an awfully
  55.                    long time! Check on the 'scope' for yourself. */
  56.                 c=0;
  57.                 while(--c)
  58.                         __asm__("nop;\n");
  59.                 c = KBD_PIN; /* get input bits, 0 means key pressed */
  60.                 c  |= bit;       /* mask out current column */
  61.                 c >>= KBD_P0;    /* shift bits to 0..3 */
  62.                 c   = ~c & 0x0f; /* pressed buttons are 1 */
  63.                 ret |= c;
  64.                 if( bit == _BV(KBD_P0+3) )
  65.                         break;
  66.                 bit <<= 1;
  67.         } while(1);
  68.         return ret;
  69. }
复制代码
  1. #include <avr/io.h>
  2. #include <avr/pgmspace.h>
  3. #include "matrixtest.c"
  4. /* put one single byte out onto the serial port */
  5. static void
  6. putserial(unsigned char c){
  7.         /* wait for Uart DataRegister to become Empty (UDRE) */
  8.         while(!(UCSR0A & _BV(UDRE0)));
  9.         UDR0 = c;
  10. }
  11. /* convert 0..9,10..15 to '0'..'9','A'..'F' */
  12. static unsigned char
  13. nibble_to_char(unsigned char c){
  14.         c &= 0x0f;
  15.         if(c>=10)
  16.                 c+= ('A'-'0'-10);
  17.         return c+'0';
  18. }
  19. static void
  20. putnibble(unsigned char c){
  21.         putserial(nibble_to_char(c));
  22. }
  23. static void
  24. puthexword(uint16_t v){
  25.         putnibble((v>>12)&0x0f);
  26.         putnibble((v>> 8)&0x0f);
  27.         putnibble((v>> 4)&0x0f);
  28.         putnibble( v     &0x0f);
  29. }
  30. /* this wastes memory, but the M328 is completely   empty anyway... */
  31. struct keynames {
  32.         uint16_t v;
  33.         char name;
  34. } keynames[]={
  35.         { MATRIX2_A, 'A' },
  36.         { MATRIX2_B, 'B' },
  37.         { MATRIX2_C, 'C' },
  38.         { MATRIX2_D, 'D' },
  39.         { MATRIX2_E, 'E' },
  40.         { MATRIX2_F, 'F' },
  41.         { MATRIX2_G, 'G' },
  42.         { MATRIX2_H, 'H' },
  43.         { MATRIX2_I, 'I' },
  44.         { MATRIX2_J, 'J' },
  45.         { MATRIX2_K, 'K' },
  46.         { MATRIX2_L, 'L' }
  47. };
  48. int
  49. main(void){
  50.         uint16_t ctr;
  51.         uint16_t oldkeys,newkeys;
  52.         int i;        UBRR0 = 103; /* 9k6 bps @ 16 MHz */
  53.         UCSR0B = _BV(RXEN0)|_BV(TXEN0);
  54.         UCSR0C = _BV(UCSZ01)|_BV(UCSZ00);
  55.         for(;;){
  56.                 newkeys = matrix2_scan();
  57.                 if(newkeys != oldkeys){
  58.                         ctr=255;
  59.                 }
  60.                 oldkeys = newkeys;
  61.                 if(ctr)
  62.                         ctr--;
  63.                 if(ctr==1){
  64.                         putserial('\r');
  65.                         putserial('\n');
  66.                         puthexword(newkeys);
  67.                         putserial(' ');
  68.                         for(i=0;i<12;i++){
  69.                                 if(newkeys & keynames[i].v)
  70.                                         putserial(keynames[i].name);
  71.                                 else
  72.                                         putserial('-');
  73.                                 putserial(' ');
  74.                         }
  75.                 }
  76.         }
  77. }
复制代码
  1. This is a small example to show how to decode a
  2. 12-button matrix using only 4 I/O pins of a microcontroller.
  3. One key consists of a switch and a diode.
  4. All combination of simultaneously pressed keys can be decoded.
  5. The example compiles for an Arduino duemilanove, as is it's using
  6. the signals marked as Analog 1..Analog 4 (PortC1..4).
  7. Simple test shows the following output on ttyUSB0@9600 bps:
  8. +------ output of the matrix_scan function
  9. |
  10. |   +-- "Human readable" key numbers
  11. |   |
  12. V   V

  13. 2000 A - - - - - - - - - - -
  14. 0000 - - - - - - - - - - - -
  15. 4000 - B - - - - - - - - - -
  16. 0000 - - - - - - - - - - - -
  17. 8000 - - C - - - - - - - - -
  18. 0000 - - - - - - - - - - - -
  19. 0100 - - - D - - - - - - - -
  20. 0000 - - - - - - - - - - - -
  21. 0400 - - - - E - - - - - - -
  22. 0000 - - - - - - - - - - - -
  23. 0800 - - - - - F - - - - - -
  24. 0000 - - - - - - - - - - - -
  25. 0010 - - - - - - G - - - - -
  26. 0000 - - - - - - - - - - - -
  27. 0020 - - - - - - - H - - - -
  28. 0000 - - - - - - - - - - - -
  29. 0080 - - - - - - - - I - - -
  30. 0000 - - - - - - - - - - - -
  31. 0001 - - - - - - - - - J - -
  32. 0000 - - - - - - - - - - - -
  33. 0002 - - - - - - - - - - K -
  34. 0000 - - - - - - - - - - - -
  35. 0004 - - - - - - - - - - - L
  36. 0000 - - - - - - - - - - - -
  37. 0000 - - - - - - - - - - - -
  38. 0010 - - - - - - G - - - - -   <-- two buttons
  39. 0012 - - - - - - G - - - K -   <-- simultaneously
复制代码
帮你转载过来

出0入0汤圆

发表于 2013-1-4 09:41:38 | 显示全部楼层
楼主的按键接法不对 但是看源代码中的接法  又不是很清楚该具体怎么接 不过感觉楼主的应该是错的

出0入0汤圆

发表于 2013-1-4 16:35:02 | 显示全部楼层
电路和代码都正确,但得注意电平高低,原文没有给出供电电压,这里需要注意单片机检测两个二极管的叠加压降必须为高电平才行,3.3V供电应该没问题,5V供电就危险了。

出0入0汤圆

 楼主| 发表于 2013-1-4 16:57:22 | 显示全部楼层
surken 发表于 2013-1-4 16:35
电路和代码都正确,但得注意电平高低,原文没有给出供电电压,这里需要注意单片机检测两个二极管的叠加压降 ...

附m8的电气特性



3.3v也不保证行得通,假设二极管压降为x,串1个二极管为低电平,串2个为高电平,那么就是:
x < 3.3*0.2
2x > 3.3*0.6

没有这样的二极管吧?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-1-17 09:25:21 来自手机 | 显示全部楼层
没有阅读代码,通过电路图推测,每次扫描12次的话可以做到任意组合

出0入0汤圆

发表于 2013-1-17 09:28:48 来自手机 | 显示全部楼层
将一个口做输入,另三个依次给高电平。依次类推,四个口逐个做为输入
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 04:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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