Matrix Switch Hooked to PIC16f886

Discussion in 'Embedded Systems and Microcontrollers' started by beeson76, Oct 18, 2010.

  1. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Included is my schematic.

    Just a few questions about this setup. I would like to use the Internal Pullups on PORTB. I have just a small hobby box to put it in and really have no room for external resistors. Does this program look right for the schematic. The program seems to work on a PIC simulator (PIC simulator 1.3), but doesn't seem to work in the real world:)

    I read from this forum that I must have MCLR enabled to use the weak pullups on PORTB. So that is why that is so in the configuration line for the chip.

    The LCD is "wired: correctly and initializes and displays text so I'm pretty sure the problem is the program side of things. Can someone please look at this and critique it. I appreciate any help anyone can provide. Here is the code for the Main.c

    Code ( (Unknown Language)):
    1.  
    2. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3. //
    4. //This program controls a Matrix Switch.  The Switch consists of 3 columns and 4 rows.
    5. //Whenever a button is pushed, that button is displayed on an LCD Display.
    6. //PIC16F886 Microcontroller from Microchip is being used.
    7. //
    8. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    9.  
    10. #include <htc.h>
    11. #include "lcd.h"
    12.  
    13. #define  KEY_PORT               PORTB                               //Defining PORTB as KEY_PORT                           
    14. #define  KEY_SET(bits)          KEY_PORT |= (bits)                  //Defining KEY_SET as
    15. #define  KEY_CLR                KEY_PORT &=~ (bits)                 //Defining Key_CLR as KEY_PORT = KEY_PORT &~ (bits)
    16. #define  KEY_FLP(bits)          KEY_PORT ^= (bits)                  //Defining KEY_FLP as KEY_PORT = KEY_PORT ^ (bits)
    17. #define  KEY_IN(bits)           TRISB |= (bits)                     //Defining KEY_IN as TRISB = TRISB | (bits)
    18. #define  KEY_OUT(bits)          TRISB &=~ (bits)                    //Defining KEY_OUT as TRISB = TRISB &~ (bits)
    19. #define  KEY_COL                0b10000011                          //Defining KEY_COL as high,low,low,low,low,low,high,high
    20. #define  KEY_ROW                0b01111000                          //Defining KYE_ROW as low,high,high,high,high,low,low,low
    21. #define  DelayS(T)              {unsigned char i; for (i = 0; i < T * 10; i++) __delay_ms(100);}    //Delay Macro
    22. #define  _XTAL_FREQ             4000000                             //Needs to be set for __delay_ms
    23.  
    24.  
    25. /////CONFIGURATION FUSE//////////////////////////////////////////////////////////////////////////////////////////////////////////
    26. //Master Clear Reset enabled & Internal RC No Clock & Watchdog Timer Disable & Power Up Timer On & Brown Out Reset Disabled &
    27. // Low Voltage Porgramming Disabled & Code Unprotect
    28. //
    29. __CONFIG (MCLREN & INTIO & WDTDIS & PWRTEN & BORDIS & LVPDIS & UNPROTECT);
    30. //
    31. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    32.  
    33.  
    34.  
    35.  
    36. unsigned char key_read(unsigned char in_bits, unsigned char out_bits)
    37.     {
    38.         KEY_IN(in_bits);
    39.         KEY_SET(out_bits);
    40.         KEY_OUT(out_bits);
    41.         return KEY_PORT & in_bits;
    42.     }
    43.  
    44. unsigned char key_detect(void)
    45.     {
    46.         unsigned char tmp1, tmp2;
    47.         tmp2 = key_read(KEY_ROW, KEY_COL);
    48.         tmp1 = key_read(KEY_COL, KEY_ROW);
    49.         return tmp1 | tmp2;
    50.     }
    51.  
    52. main ()                                        
    53. {                                                                              
    54.  
    55. PORTA = 0x00;                                       //PORTA is cleared and set low
    56. PORTB = 0x00;                                       //PORTB is cleared and set low
    57. PORTC = 0x00;                                       //PORTA is cleared and set low
    58. TRISA = 0x00;                                       //Set PORTA to outputs
    59. TRISB = 0xFF;                                       //Set PORTB to inputs
    60. TRISC = 0x00;                                       //Set PORTC to outputs
    61. RBPU = 0;                                           //Internal PORTB Pullups enabled
    62. ANSEL = 0;                                          //Initialize A/D Ports off
    63. ANSELH = 0;                                         //Initialize ........
    64. CM1CON0 = 0;                                        //Initialize Comparator 1 off
    65. CM2CON0 = 0;                                        //Initialize Comparator 2 off
    66.  
    67. OPTION = 0b01010101;                                //OPTION REG
    68.                                                     //xbxxxxx101  1:64
    69.                                                     //xbxxxx0xxx  Prescaler set to Timer0
    70.                                                     //xbxxx1xxxx  (T0SE) set to Increment on high-to-low transition on T0CKI pin
    71.                                                     //xbxx0xxxxx  (T0CS) Internal instruction cycle clock
    72.                                                     //xbx1xxxxxx  (INTEDG) Interrupt on rising edge of INT pin
    73.                                                     //xb0xxxxxxx  (RBPU) PORTB pull-ups are enabled by individual PORT latch values
    74.  
    75. lcd_init();                                         //LCD Display is Initialized...See if LCD.C file
    76.  
    77. /////IGNORE THIS -- ONLY A TEST//////////////////////////////////////////////////////////////////////////////////////////////////
    78. //Only a test to see if LCD is Initialized and Display Text
    79. //while (1 == 1)
    80. //{
    81. // 
    82. //  lcd_clear();
    83. //  lcd_goto(0);
    84. //  lcd_puts("Hello World");
    85. //  __delay_ms(150);
    86. //  lcd_goto(40);
    87. //  lcd_puts("LCD Iniatlized");
    88. //  __delay_ms(150);
    89. //}
    90. //}                                                 //Everything After this would be commented out
    91. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    92.  
    93. char key;                                           //Creating a local Variable called "key" to hold value of key is pressed
    94.  
    95. while (key_detect() == 1)                           //Loops When Key is Pressed
    96. continue;
    97. {
    98.  
    99. key = key_detect();                                 //Referring to key_detect() function.  Returns key pressed.
    100.  
    101. switch (key)                                        //Switch Statement for "key"
    102.     {
    103.         case 0b00100001:                            //Column 1 Row 4--Switch 12
    104.             lcd_goto(0);
    105.             lcd_puts("Switch 1");
    106.             //DelayS(1);
    107.             lcd_clear();
    108.             break;
    109.         case 0b01000001:                            //Column 1 Row 3--Switch 11
    110.             lcd_goto(0);
    111.             lcd_puts("Switch 2");
    112.             //DelayS(1);
    113.             lcd_clear();
    114.             break;
    115.         case 0b00010001:                            //Column 1 Row 2--Switch 10
    116.             lcd_goto(0);
    117.             lcd_puts("Switch 3");
    118.             //DelayS(1);
    119.             lcd_clear();
    120.             break;
    121.         case 0b00001001:                            //Column 1 Row 1--Switch 9
    122.             lcd_goto(0);
    123.             lcd_puts("Switch 4");
    124.             //DelayS(1);
    125.             lcd_clear();
    126.             break;
    127.         case 0b00100010:                            //Column 2 Row 4--Switch 8
    128.             lcd_goto(0);
    129.             lcd_puts("Switch 5");
    130.             //DelayS(1);
    131.             lcd_clear();
    132.             break;
    133.         case 0b01000010:                            //Column 2 Row 3--Switch 7
    134.             lcd_goto(0);
    135.             lcd_puts("Switch 6");
    136.             //DelayS(1);
    137.             lcd_clear();
    138.             break;
    139.         case 0b00010010:                            //Column 2 Row 2--Switch 6
    140.             lcd_goto(0);
    141.             lcd_puts("Switch 7");
    142.             //DelayS(1);
    143.             lcd_clear();
    144.             break;
    145.         case 0b00001010:                            //Column 2 Row 1--Switch 5
    146.             lcd_goto(0);
    147.             lcd_puts("Switch 8");
    148.             //DelayS(1);
    149.             lcd_clear();
    150.             break;
    151.         case 0b10100000:                            //Column 3 Row 4--Switch 4
    152.             lcd_goto(0);
    153.             lcd_puts("Switch 9");
    154.             //DelayS(1);
    155.             lcd_clear();
    156.             break;
    157.         case 0b11000000:                            //Column 3 Row 3--Switch 3
    158.             lcd_goto(0);
    159.             lcd_puts("Switch 10");
    160.             //DelayS(1);
    161.             lcd_clear();
    162.             break;
    163.         case 0b10010000:                            //Column 3 Row 2--Switch 2
    164.             lcd_goto(0);
    165.             lcd_puts("Switch 11");
    166.             //DelayS(1);
    167.             lcd_clear();
    168.             break;
    169.         case 0b10001000:                            //Column 3 Row 1--Switch 1
    170.             lcd_goto(0);
    171.             lcd_puts("Switch 12");
    172.             //DelayS(1);
    173.             lcd_clear();
    174.             break;
    175.     }
    176.  
    177.  
    178. }
    179. }
    180.  
    181.  
    182.  
    183.  
    Thanks
     
    Last edited: Oct 19, 2010
  2. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    For the PORTB to be used, should I have all of PORTB as inputs and set high or set low? Thanks for any replies.

    Mike
     
  3. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Can anyone provide sample code for what I am trying to do with this project.

    I have read much, but have found no code example in C. That would probably help me the most.

    Thanks.
     
  4. wannaBinventor

    Member

    Apr 8, 2010
    179
    4
    I don't know C so I'm not 100% sure of what you are doing, but TRISB shouldn't all be inputs. It's been a little while since I wrote/used my assembly keypad code, but I think you need to have 3 outputs for the columns and 4 inputs for the rows.

    You set high all rows but one and then have the program go down the rows looking for a low input (which will have been generated if the button in that row is pressed while to column is cleared low). Then set that column's pin and clear the next.
     
  5. Potato Pudding

    Well-Known Member

    Jun 11, 2010
    684
    92
    Actually I think the whole point of weak pull ups is that they are a high outputlevel&impedance layered on an input. They are meant for a switch to pull them low.

    That is almost exactly what the weak pull ups would avoid - maybe.

    I haven't gotten the hang of C either so I didn't look close at your code. I will try and work out how I think they could be used.

    What a matrix does normally is sequentially strobe the outputs (3 columns) as mentioned by Wanna and then you check the inputs (4 rows) and matching which column was strobed with which input is switched low tells you which key was pressed.

    They weak pull ups will allow a similar type of system but resistors or diodes will be needed.

    Instead of the strobe you have the B inputs and interrupts.

    You do need to isolate the different columns of switches somehow so that the column pulled low does not pull all of the other columns low. Those were strobed outputs but now they are all inputs with a weak pullup.

    The rows are connected to all the columns in the strobed matrix switch, and you can't exactly do that the same way when all columns are inputs.

    If you only need 9 buttons in your keypad then just connect one to each of the Port B inputs with the pullup and one to the E3 pin which also has a pullup.

    That is the only way to get away without any resistors or diodes for crosstalk isolation.

    But I don't care how small your case is. Putting some surface mount resistors or diodes in the signal paths will not hurt your space requirements. Just your eyes when you are working with them.
     
  6. beeson76

    Thread Starter Member

    Apr 19, 2010
    185
    1
    Thanks for the replies. I will post the code in various stages so anyone can use it. Thanks.
     
Loading...