/* p3_5.c: Matrix keypad scanning * This program scans a 4x4 matrix keypad and returns a unique number * for each key pressed. The number is displayed on the tri-color * LEDs using the code from P2-7. * * PortC 7-4 are connected to the columns and PortC 3-0 are connected * to the rows. */ #include void delayMs(int n); void delayUs(int n); void keypad_init(void); char keypad_getkey(void); void LED_init(void); void LED_set(int value); int main(void) { unsigned char key; keypad_init(); LED_init(); while(1) { key = keypad_getkey(); LED_set(key); /* set LEDs according to the key code */ } } /* this function initializes PortC that is connected to the keypad. * All pins are configured as GPIO input pin with pull-up enabled. */ void keypad_init(void) { SIM->SCGC5 |= 0x0800; /* enable clock to Port C */ PORTC->PCR[0] = 0x103; /* make PTD0 pin as GPIO and enable pullup*/ PORTC->PCR[1] = 0x103; /* make PTD1 pin as GPIO and enable pullup*/ PORTC->PCR[2] = 0x103; /* make PTD2 pin as GPIO and enable pullup*/ PORTC->PCR[3] = 0x103; /* make PTD3 pin as GPIO and enable pullup*/ PORTC->PCR[4] = 0x103; /* make PTD4 pin as GPIO and enable pullup*/ PORTC->PCR[5] = 0x103; /* make PTD5 pin as GPIO and enable pullup*/ PORTC->PCR[6] = 0x103; /* make PTD6 pin as GPIO and enable pullup*/ PORTC->PCR[7] = 0x103; /* make PTD7 pin as GPIO and enable pullup*/ PTD->PDDR = 0x0F; /* make PTD7-0 as input pins */ } /* * This is a non-blocking function to read the keypad. * If a key is pressed, it returns a key code. Otherwise, a zero * is returned. * The upper nibble of Port C is used as input. Pull-ups are enabled * when the keys are not pressed, these pins are pull up high. * The lower nibble of Port C is used as output that drives the keypad rows. * First all rows are driven low and the input pins are read. If no * key is pressed, it will read as all ones. Otherwise, some key is pressed. * If any key is pressed, the program drives one row low at a time and * leave the rest of the rows inactive (float) then read the input pins. * Knowing which row is active and which column is active, the program * can decide which key is pressed. */ char keypad_getkey(void) { int row, col; const char row_select[] = {0x01, 0x02, 0x04, 0x08}; /* one row is active */ /* check to see any key pressed */ PTC->PDDR |= 0x0F; /* enable all rows */ PTC->PCOR = 0x0F; delayUs(2); /* wait for signal return */ col = PTC->PDIR & 0xF0; /* read all columns */ PTC->PDDR = 0; /* disable all rows */ if (col == 0xF0) return 0; /* no key pressed */ /* If a key is pressed, it gets here to find out which key. * It activates one row at a time and read the input to see * which column is active. */ for (row = 0; row < 4; row++) { PTC->PDDR = 0; /* disable all rows */ PTC->PDDR |= row_select[row]; /* enable one row */ PTC->PCOR = row_select[row]; /* drive the active row low */ delayUs(2); /* wait for signal to settle */ col = PTC->PDIR & 0xF0; /* read all columns */ if (col != 0xF0) break; /* if one of the input is low, some key is pressed. */ } PTC->PDDR = 0; /* disable all rows */ if (row == 4) return 0; /* if we get here, no key is pressed */ /* gets here when one of the rows has key pressed, check which column it is */ if (col == 0xE0) return row * 4 + 1; /* key in column 0 */ if (col == 0xD0) return row * 4 + 2; /* key in column 1 */ if (col == 0xB0) return row * 4 + 3; /* key in column 2 */ if (col == 0x70) return row * 4 + 4; /* key in column 3 */ return 0; /* just to be safe */ } /* initialize all three LEDs on the FRDM board */ void LED_init(void) { SIM->SCGC5 |= 0x400; /* enable clock to Port B */ SIM->SCGC5 |= 0x1000; /* enable clock to Port D */ PORTB->PCR[18] = 0x100; /* make PTB18 pin as GPIO */ PTB->PDDR |= 0x40000; /* make PTB18 as output pin */ PTB->PSOR |= 0x40000; /* turn off red LED */ PORTB->PCR[19] = 0x100; /* make PTB19 pin as GPIO */ PTB->PDDR |= 0x80000; /* make PTB19 as output pin */ PTB->PSOR |= 0x80000; /* turn off green LED */ PORTD->PCR[1] = 0x100; /* make PTD1 pin as GPIO */ PTD->PDDR |= 0x02; /* make PTD1 as output pin */ PTD->PSOR |= 0x02; /* turn off blue LED */ } /* turn on or off the LEDs according to bit 2-0 of the value */ void LED_set(int value) { if (value & 1) /* use bit 0 of value to control red LED */ PTB->PCOR = 0x40000; /* turn on red LED */ else PTB->PSOR = 0x40000; /* turn off red LED */ if (value & 2) /* use bit 1 of value to control green LED */ PTB->PCOR = 0x80000; /* turn on green LED */ else PTB->PSOR = 0x80000; /* turn off green LED */ if (value & 4) /* use bit 2 of value to control blue LED */ PTD->PCOR = 0x02; /* turn on blue LED */ else PTD->PSOR = 0x02; /* turn off blue LED */ } /* delay n microseconds * The CPU core clock is set to MCGFLLCLK at 41.94 MHz in SystemInit(). */ void delayUs(int n) { int i; int j; for(i = 0 ; i < n; i++) { for(j = 0; j < 5; j++) ; } }