佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 6398|回复: 14

【教学】PIC 连接4x4 Keypad , 显示在 16x2 LCD

  [复制链接]
发表于 6-3-2012 08:52 PM | 显示全部楼层 |阅读模式
本帖最后由 pic 于 9-3-2012 11:25 AM 编辑

过去有一些帖子, 示范了怎样用CCS C, 使用 PIC MCU 的ADC, 连接去LCD, USART 等等。。
矩阵键盘 (Keypad ) 倒是还没有说过。。 这里引用CCS C 的 示范程序, EX_LCDKB.C , LCD.C,  KBD.C, 做部分修改后, 在proteus 运行示范。

供网友们参考。 有问题可以发问, 但是请不要离题。

电路图如下, LCD 是接去 16F887 的Port D, Keypad 是接去 Port B,相对的按键, 会显示在LCD 上, 按 [On/C] 键会清除 LCD。
矩阵键盘 的Row (行), 需要电位拉高 pull high,可以用4.7k~10K 的电阻。



CCS C 源码:下载

主程序

  1. // Demo: Keypad 4x4, display on LCD 16x2
  2. // Modified from CCS C Ex_LCDKB.C
  3. // Filename: Cari_LCDKB.C
  4. // Date: 6 Mar 2012
  5. // by: pic@cArI

  6. #include <16F887.h>
  7. #fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP
  8. #use delay(clock=8000000)

  9. #include <mylcd.c>
  10. #include <mykbd.c>

  11. void main() {
  12.    char k;

  13.    lcd_init();
  14.    lcd_putc("\fReady...\n");

  15.    while (TRUE)
  16.    {
  17.       k=kbd_getc();
  18.       if(k!=0)
  19.         if(k=='N')
  20.           lcd_putc('\f');
  21.         else
  22.           lcd_putc(k);
  23.    }
  24. }

复制代码
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 6-3-2012 09:00 PM | 显示全部楼层

myKBD.C

本帖最后由 pic 于 6-3-2012 09:15 PM 编辑

Keypad 的bouncing , 可以设定, 在#define KBD_DEBOUNCE_FACTOR
我修改了 CCS C 原本的 Keypad Scan Driver , KBD.C  (4x3)变成 myKBD.C (4x4)

  1. // Filename: myKBD.C
  2. #define use_portb_kbd TRUE  // 使用 PortB

  3. #if defined(__PCH__)
  4. #if defined use_portb_kbd
  5.    #byte kbd = 0xF81                   // This puts the entire structure
  6. #else
  7.    #byte kbd = 0xF83                   // This puts the entire structure
  8. #endif

  9. #else
  10. #if defined use_portb_kbd
  11.    #byte kbd = 6                  // on to port B (at address 6)
  12. #else
  13.    #byte kbd = 8                 // on to port D (at address 8)
  14. #endif
  15. #endif

  16. #if defined use_portb_kbd
  17.    #define set_tris_kbd(x) set_tris_b(x)
  18. #else
  19.    #define set_tris_kbd(x) set_tris_d(x)
  20. #endif


  21. #define COL0 (1 << 4)   // Col0 接去PortB.4
  22. #define COL1 (1 << 5)   // Col1 接去PortB.5
  23. #define COL2 (1 << 6)   // Col2 接去PortB.6
  24. #define COL3 (1 << 7)   // Col3 接去PortB.7

  25. #define ROW0 (1 << 0)   // ROW0 接去PortB.0
  26. #define ROW1 (1 << 1)   // ROW1 接去PortB.1
  27. #define ROW2 (1 << 2)   // ROW2 接去PortB.2
  28. #define ROW3 (1 << 3)   // ROW3 接去PortB.3


  29. #define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
  30. #define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3)

  31. // Keypad layout:
  32. char const KEYS[4][4] = {{'7','8','9','/'},
  33.                          {'4','5','6','x'},
  34.                          {'1','2','3','-'},
  35.                          {'N','0','=','+'}};

  36. #define KBD_DEBOUNCE_FACTOR 33    // Set this number to apx n/333 where
  37.                                   // n is the number of times you expect
  38.                                   // to call kbd_getc each second


  39. void kbd_init()
  40. {
  41.    port_b_pullups (true);
  42. }

  43. char kbd_getc( ) {
  44.    static BYTE kbd_call_count;
  45.    static int kbd_down;
  46.    static char last_key;
  47.    static BYTE col;

  48.    BYTE kchar;
  49.    BYTE row;

  50.    kchar='\0';
  51.    if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
  52.    {
  53.        switch (col)
  54.        {
  55.          case 0   : set_tris_kbd(ALL_PINS&~COL0);
  56.                     kbd=~COL0&ALL_PINS;
  57.                     break;
  58.          case 1   : set_tris_kbd(ALL_PINS&~COL1);
  59.                     kbd=~COL1&ALL_PINS;
  60.                     break;
  61.          case 2   : set_tris_kbd(ALL_PINS&~COL2);
  62.                     kbd=~COL2&ALL_PINS;
  63.                     break;
  64.          case 3   : set_tris_kbd(ALL_PINS&~COL3);
  65.                     kbd=~COL3&ALL_PINS;
  66.                     break;
  67.        }

  68.        if(kbd_down)
  69.        {
  70.          if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
  71.            kbd_down=FALSE;
  72.            kchar=last_key;
  73.            last_key='\0';
  74.          }
  75.        } else {
  76.           if((kbd & (ALL_ROWS))!=(ALL_ROWS))
  77.           {
  78.              if((kbd & ROW0)==0)
  79.                row=0;
  80.              else if((kbd & ROW1)==0)
  81.                row=1;
  82.              else if((kbd & ROW2)==0)
  83.                row=2;
  84.              else if((kbd & ROW3)==0)
  85.                row=3;
  86.              last_key =KEYS[row][col];
  87.              kbd_down = TRUE;
  88.           }
  89.           else
  90.           {
  91.              ++col;
  92.              if(col==4)
  93.                col=0;
  94.           }
  95.        }
  96.       kbd_call_count=0;
  97.    }
  98.   set_tris_kbd(ALL_PINS);
  99.   return(kchar);
  100. }

复制代码
回复

使用道具 举报

 楼主| 发表于 6-3-2012 09:04 PM | 显示全部楼层

myLCD.C

修改了 CCS C 原本的 LCD Driver, LCD.C 变成 myLCD.C , 改变了 RS, RW , Enable的接线。

  1. ////                             myLCD.C                               ////
  2. ////                 Driver for common LCD modules                     ////
  3. ////  lcd_init()   Must be called before any other function.           ////
  4. ////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
  5. ////                     The following have special meaning:           ////
  6. ////                      \f  Clear display                            ////
  7. ////                      \n  Go to start of second line               ////
  8. ////                      \b  Move back one position                   ////
  9. ////                                                                   ////
  10. ////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
  11. ////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////

  12. //     D0  rs
  13. //     D1  rw
  14. //     D2  enable
  15. //     D4  D4
  16. //     D5  D5
  17. //     D6  D6
  18. //     D7  D7

  19. struct lcd_pin_map {                 // This structure is overlayed
  20.            BOOLEAN rs;               // on to an I/O port to gain
  21.            BOOLEAN rw;               // access to the LCD pins.
  22.            BOOLEAN enable;           // The bits are allocated from
  23.            BOOLEAN unused;           // low order up.  ENABLE will
  24.            int     data : 4;         // be pin B0.
  25.         } lcd;


  26. #if defined(__PCH__)
  27. #if defined use_portb_lcd
  28.    #byte lcd = 0xF81                   // This puts the entire structure
  29. #else
  30.    #byte lcd = 0xF83                   // This puts the entire structure
  31. #endif
  32. #else
  33. #if defined use_portb_lcd
  34.    #byte lcd = 6                  // on to port B (at address 6)
  35. #else
  36.    #byte lcd = 8                 // on to port D (at address 8)
  37. #endif
  38. #endif

  39. #if defined use_portb_lcd
  40.    #define set_tris_lcd(x) set_tris_b(x)
  41. #else
  42.    #define set_tris_lcd(x) set_tris_d(x)
  43. #endif


  44. #define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
  45. #define lcd_line_two 0x40    // LCD RAM address for the second line


  46. BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
  47.                              // These bytes need to be sent to the LCD
  48.                              // to start it up.

  49.                              // The following are used for setting
  50.                              // the I/O port direction register.

  51. struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
  52. struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in


  53. BYTE lcd_read_byte() {
  54.       BYTE low,high;
  55.       set_tris_lcd(LCD_READ);
  56.       lcd.rw = 1;
  57.       delay_cycles(1);
  58.       lcd.enable = 1;
  59.       delay_cycles(1);
  60.       high = lcd.data;
  61.       lcd.enable = 0;
  62.       delay_cycles(1);
  63.       lcd.enable = 1;
  64.       delay_us(1);
  65.       low = lcd.data;
  66.       lcd.enable = 0;
  67.       set_tris_lcd(LCD_WRITE);
  68.       return( (high<<4) | low);
  69. }


  70. void lcd_send_nibble( BYTE n ) {
  71.       lcd.data = n;
  72.       delay_cycles(1);
  73.       lcd.enable = 1;
  74.       delay_us(2);
  75.       lcd.enable = 0;
  76. }


  77. void lcd_send_byte( BYTE address, BYTE n ) {

  78.       lcd.rs = 0;
  79.       while ( bit_test(lcd_read_byte(),7) ) ;
  80.       lcd.rs = address;
  81.       delay_cycles(1);
  82.       lcd.rw = 0;
  83.       delay_cycles(1);
  84.       lcd.enable = 0;
  85.       lcd_send_nibble(n >> 4);
  86.       lcd_send_nibble(n & 0xf);
  87. }


  88. void lcd_init() {
  89.     BYTE i;
  90.     set_tris_lcd(LCD_WRITE);
  91.     lcd.rs = 0;
  92.     lcd.rw = 0;
  93.     lcd.enable = 0;
  94.     delay_ms(15);
  95.     for(i=1;i<=3;++i) {
  96.        lcd_send_nibble(3);
  97.        delay_ms(5);
  98.     }
  99.     lcd_send_nibble(2);
  100.     for(i=0;i<=3;++i)
  101.        lcd_send_byte(0,LCD_INIT_STRING[i]);
  102. }


  103. void lcd_gotoxy( BYTE x, BYTE y) {
  104.    BYTE address;

  105.    if(y!=1)
  106.      address=lcd_line_two;
  107.    else
  108.      address=0;
  109.    address+=x-1;
  110.    lcd_send_byte(0,0x80|address);
  111. }

  112. void lcd_putc( char c) {
  113.    switch (c) {
  114.      case '\f'   : lcd_send_byte(0,1);
  115.                    delay_ms(2);
  116.                                            break;
  117.      case '\n'   : lcd_gotoxy(1,2);        break;
  118.      case '\b'   : lcd_send_byte(0,0x10);  break;
  119.      default     : lcd_send_byte(1,c);     break;
  120.    }
  121. }

  122. char lcd_getc( BYTE x, BYTE y) {
  123.    char value;

  124.     lcd_gotoxy(x,y);
  125.     while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
  126.     lcd.rs=1;
  127.     value = lcd_read_byte();
  128.     lcd.rs=0;
  129.     return(value);
  130. }
复制代码
回复

使用道具 举报

发表于 7-3-2012 09:32 AM | 显示全部楼层
谢谢版主的无私奉献,上了一个宝贵一课!
回复

使用道具 举报

发表于 7-3-2012 07:18 PM | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

发表于 9-3-2012 01:49 AM | 显示全部楼层
回复 3# pic

那个myKBD.c 我copy到完,可是有error哦***Error128"myKBD.c"Line6(5,9):A #DEVICE required before this line
   
那个myLCD.c 我copy到完,也是有error哦***Error128"myKBD.c"Line21(1,8):A #DEVICE required before this line
回复

使用道具 举报

Follow Us
 楼主| 发表于 9-3-2012 11:19 AM | 显示全部楼层
回复  pic

那个myKBD.c 我copy到完,可是有error哦***Error128"myKBD.c"Line6(5,9):A #DEVICE required ...
Harry88 发表于 9-3-2012 01:49 AM

那些file 要放在同一个folder。
直接给你源码吧
下载CCS C源码
回复

使用道具 举报

发表于 12-3-2012 12:23 AM | 显示全部楼层
好贴~谢谢楼主的分享  
回复

使用道具 举报


ADVERTISEMENT

发表于 12-3-2012 12:31 AM | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 12-3-2012 03:51 PM | 显示全部楼层
谢谢楼主的分享。。。
回复

使用道具 举报

发表于 12-3-2012 06:12 PM | 显示全部楼层
谢谢分享。。
我不是很会PIC。。慢慢学着。。
对了,我可以问看版主你会不会arduino?
回复

使用道具 举报

 楼主| 发表于 12-3-2012 06:39 PM | 显示全部楼层
谢谢分享。。
我不是很会PIC。。慢慢学着。。
对了,我可以问看版主你会不会arduino?
希椏 发表于 12-3-2012 06:12 PM

没有接触过, 但是未来会买了玩玩体验。。。

Arduino 适合给不是很会电子的朋友, 比如读机械工程的, 业余爱好者,
他们想要控制一些东西, 但是又不要很深入, 不是做商业用途的,
就依赖模块, 要什么功能 , 就买特定的模块, 应用人家已经写好的程序,
做出一些控制。

好处是速成, 缺点是会依赖模块, 仰赖人家写的程序 library。
ok, 离题了。
回复

使用道具 举报

发表于 12-3-2012 10:43 PM | 显示全部楼层
没有接触过, 但是未来会买了玩玩体验。。。

Arduino 适合给不是很会电子的朋友, 比如读机械工程的, ...
pic 发表于 12-3-2012 06:39 PM


好的,谢谢你!

我也会试学PIC,因为现在假期当中。。

希望能把握时机。。
回复

使用道具 举报

发表于 13-3-2012 08:40 PM | 显示全部楼层
很深奥,你能解释一下?
回复

使用道具 举报

发表于 13-3-2012 11:46 PM | 显示全部楼层
谢谢楼主分享~
回复

使用道具 举报

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

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 29-3-2024 02:05 PM , Processed in 0.072171 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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