/* * Scan keypad and write the keycode to LEDs. * The matrix keypad of the EduBase board is connected to * col 0 - PB12 * col 1 - PB13 * col 2 - PB14 * col 3 - PB15 * row 0 - PC8 * row 1 - PC9 * row 2 - PC10 * row 3 - PC11 * * The four LEDs are connected to * LED3 - PB7 * LED2 - PB6 * LED1 - PB5 * LED0 - PB4 */ #include "STM32F4XX.h" void delay(void); void keypad_init(void); char keypad_getkey(void); void writeLEDs(char n); int readRows(void); void outputEnableCols(char n); void writeCols(char n); int main(void) { char key; /* initialize pins connected to keypad */ keypad_init(); /* initialize LEDs for display */ RCC->AHB1ENR |= 2; /* enable GPIOB clock */ GPIOB->MODER &= ~0x0000ff00; /* clear pin mode */ GPIOB->MODER |= 0x00005500; /* set pins to output mode */ while(1) { key = keypad_getkey(); /* read the keypad */ writeLEDs(key); /* and display the keycode on LEDs */ } } /* use bit 3-0 of parameter n to turn on/off LEDs */ void writeLEDs(char n) { GPIOB->BSRR = 0x00F00000; // turn off all LEDs GPIOB->BSRR = n << 4; // turn on LEDs } /* system clock at 16 MHz delay about 100 us */ void delay(void) { int j; for (j = 0; j < 300; j++) ; /* do nothing */ } /* This function intializes the pins connected to the keypad. */ void keypad_init(void) { /* make rows input first */ RCC->AHB1ENR |= 4; /* enable GPIOC clock */ GPIOC->MODER &= ~0x00FF0000; /* clear pin mode */ /* make columns input */ RCC->AHB1ENR |= 2; /* enable GPIOB clock */ GPIOB->MODER &= ~0xFF000000; /* clear pin mode */ } /* * This is a non-blocking function to read the keypad. * If a key is pressed, it returns a keycode. Otherwise, a zero * is returned. * The keypad is arranged as a 4x4 matrix. There are pull-down * resistors for all pins of the rows on the EduBase board. * When no keys are pressed, these pins are low. * The columns used as output that can be driven high. * First all columns are driven high and the row pins are read. If no * keys are pressed, it reads a zero. Otherwise, some key is pressed. * If any key is pressed, the program drives one column high at a time and * leave the rest of the columns inactive (float) then read the input (row) pins. * Knowing which column is active and which row is active, the program * can decide which key is pressed. */ char keypad_getkey(void) { int row, col; /* check to see any key is pressed first */ outputEnableCols(0xF); /* enable all columns */ writeCols(0xF); /* and drive them high */ delay(); /* wait for signal to settle */ row = readRows(); /* read all rows */ writeCols(0x0); /* discharge all columns */ outputEnableCols(0x0); /* disable all columns */ if (row == 0) return 0; /* if no key pressed, return a zero */ /* If a key is pressed, it gets here to find out which key. * It activates one column at a time and read the rows to see * which is active. */ for (col = 0; col < 4; col++) { outputEnableCols(1 << col); /* enable one column */ writeCols(1 << col); /* turn the active row high */ delay(); /* wait for signal to settle */ row = readRows(); /* read all rows */ writeCols(0x0); /* discharge all columns */ if (row != 0) break; /* if one of the row is low, some key is pressed. */ } outputEnableCols(0x0); /* disable all columns */ if (col == 4) return 0; /* if we get here, no key is pressed */ /* gets here when one of the rows has key pressed. * generate a unique key code and return it. */ if (row == 0x01) return 0 + col; // key in row 0 if (row == 0x02) return 4 + col; // key in row 1 if (row == 0x04) return 8 + col; // key in row 2 if (row == 0x08) return 12 + col; // key in row 3 return 0; /* just to be safe */ } /* enable columns according to bit 3-0 of the parameter n */ void outputEnableCols(char n) { GPIOB->MODER &= ~0xFF000000; /* clear pin mode */ /* make the pin output according to n */ if (n & 1) GPIOB->MODER |= 0x01000000; if (n & 2) GPIOB->MODER |= 0x04000000; if (n & 4) GPIOB->MODER |= 0x10000000; if (n & 1 << 3) GPIOB->MODER |= 0x40000000; } /* write columns high or low according to bit 3-0 of the parameter n */ void writeCols(char n) { GPIOB->BSRR = 0xF0000000; // turn off all column pins GPIOB->BSRR = n << 12; // turn on column pins } /* read rows and return them in bit 3-0 */ int readRows(void) { return (GPIOC->IDR & 0x0F00) >> 8; }