0

No idea why it won't work. Don't know where to start.

I've look up everywhere to figure this out. I'm using an STM32F446RE controller with uVision software.

The basic objective of this project is 2. Write the complete code for printing the pressed key on Debug (printf) Viewer window using the functions in the prelab assignment. 3. Run your program that prompts the user to press a key on the keypad. 4. Read the keypad and print the number (or symbol) of the key that was pressed to the Debug (printf) Viewer window.

The pins I am "trying" to use for the row are 0,2,4,6 and the pins I am trying to use for the column are 8,10,12. Can't use HAL library.

#include "stm32f4xx.h"
#include <stdio.h>

void delay(void);
void delayMs(int n);
void keypad_init(void);
char keypad_getkey(void);

int main(void)
{
    unsigned char key;
    keypad_init();


    while(1)
    {
        key = keypad_getkey(); //Function call to return key value
        if(key != 0)
        {
            printf("KEY PRESSED: %c",key); //print key
        }
    }
}
void keypad_init(void)
{
    RCC->AHB1ENR |= (1<<2); //enable clock C
    GPIOC->MODER &= ~(uint32_t)(0x0333333); //clear pin mode to input
    GPIOC->PUPDR = 0x01110000; //Enable pull up for column pins 8,10,12
}
char keypad_getkey(void)
{
    int row,col;
    const int row_mode[] = {0x00000001,0x00000010,0x0000100,0x00001000}; //One row is output pins 0,2,4,6
    const int row_low[] = {0x00010000,0x00040000,0x00100000,0x00400000}; //One row is low pins 0,2,4,6
    const int row_high[] = {0x00000001,0x00000004,0x00000010,0x00000040}; //One row is high pins 0,2,4,6
    const char keypad[4][3] =
    {
        {'1', '2', '3'},
        {'4', '5', '6'},
        {'7', '8', '9'},
        {'*', '0', '#'}
    };

    GPIOC->MODER = 0x00001111; //All row pins as output
    GPIOC->BSRR = 0x00000055; //All pins as low for row
    delay();
    col = GPIOC->IDR & 0x0055; //Read all the column pins
    GPIOC->MODER &= ~0x00003333; //Disable all row pins
    if(col==0x0055) //if columns are high than no key is pressed
        return 0;

    for(row=0; row<4; row++)
    {
        GPIOC->MODER &= ~0x00003333; //disable row pins drive
        GPIOC->MODER |= row_mode[row]; //enable one row at a time
        GPIOC->BSRR = row_low[row]; //drive the active row low
        delay();
        col = GPIOC->IDR & 0x0055; //Read all the columns
        GPIOC->BSRR = row_high[row]; //Make active row High
        if(col != 0x0055) //if an input is low a key is pressed
            break;
    }
    GPIOC->BSRR = 0x00000055; //drive all rows high
    GPIOC->MODER &= ~0x00003333; //disable them
    if (row == 4)
        return 0;

    for (int i = 0; i < 3; i++)   //Check matrix table to determine output
    {
        if (col == 0x0E00 >> i)
            return keypad[row][i];
    }
    return 0;
}
void delay(void)
{
    int i;
    for (i = 0; i < 20; i++) ;
}
GucciDonut
  • 19
  • 1
  • 1
    Minimize your program to the simplest experiment you can think of, like driving a single row and measure the pins. The next steps would be to sequence all row pins and measure that with an oscilloscope (or delay a lot and use a multimeter), then reading and printing the level of a single column while putting high and low levels on its pin, then extend this to all columns. And so on. The art of development needs incremental baby steps. – the busybee Mar 01 '23 at 07:38
  • Aside: Your `delay()` function doesn't do anything and will likely be optimised away by the compiler, unless you do `volatile int i`. Even then, it's not a great delay routine. – pmacfarlane Mar 01 '23 at 21:53
  • `GPIOC->BSRR = 0x00000055; //All pins as low for row` seems odd. Is the comment wrong? Does this not set the pins high? – pmacfarlane Mar 01 '23 at 22:01

0 Answers0