0

我已经编写了用于在 Atmega 328 中读取键盘矩阵的代码。但是我没有得到连接到 Row0 和 Column0 的键的结果。其余所有 3 个键都被正确检测到。下面是代码。我无法弄清楚问题是什么。一定有一个小问题。键盘工作正常,我单独测试过。

 #include "cloudECommon.h"

#define ROW_DDR DDRD          //I/O Port to which rows are connected
#define ROW_PORT PORTD        // I/O Port to which rows are connected
#define COLUMN_PIN PIND     // I/O Port to which columns are connected
#define COLUMN_DDR DDRD
#define NUM_ROWS 2          // Number of rows in the keypad
#define NUM_COLS 2          // number of columns in the keypad


unsigned char rowBitNumbers[NUM_ROWS] = {0,1};  // Assign port bit numbers  based on the hardware connectivity
unsigned char columnBitNumbers[NUM_COLS] = {6,7};  // Assign port bit numbers based on the hardware connectivity

// keyAssignments gives the value of the key pressed. This sends out character value to the calling portion.

unsigned char keyAssignments[NUM_ROWS][NUM_COLS] = {
                                                        {'3', 'A'},
                                                        {'6', 'B'},
                                                   };



void CL_delayMS(unsigned int delayMS)
{
      while(delayMS--) 
      {
          _delay_ms(1);
      }
}

int initializeKeyPad(void)
{
    unsigned char loopCnt;

    for(loopCnt=rowBitNumbers[0];loopCnt<=rowBitNumbers[NUM_ROWS-1];loopCnt++)
    {
        ROW_DDR &= ~(1<<loopCnt);     // Set direction as input 
        ROW_PORT &= ~(1<<loopCnt);   // Keep all rows in high impudence by writing 0. External pull ups are connected.

    }

    // Set all columns as inputs
    for(loopCnt=columnBitNumbers[0]; loopCnt<=columnBitNumbers[NUM_COLS-1]; loopCnt++)
    {
        COLUMN_DDR &= ~(1<<loopCnt);           

    }
    return 0;
}


// The following function just reads the state of the switch from the key matrix 
// If detected, returns true. Or returns false.

unsigned char readSwitch(unsigned char columnNum)
{
    //check if key is pressed. If pressed, wait until it is released. 
    if(!(COLUMN_PIN & (1<<columnNum)))
    {
        //wait for release
        //while(!(COLUMN_PIN & (1<<columnNum)));

        //Key De bounce.
        // Need to change this implementation. Time is getting wasted. Even after releasing, CPU will wait for KEY_DEBOUNCE_TIME

        CL_delayMS(KEY_DEBOUNCE_TIME);
        if(!(COLUMN_PIN & (1<<columnNum)))
        {
            return (1);
        }

    }
        return(0);
}

// Function to read the key that is being pressed.
// Returns the value of the key pressed.
// First one row will be set low and then all the columns are read. 
// Process is repeated for all the rows.

unsigned char getKey(void)
{
    unsigned char key='\0';  // If '\0' is returned, no key is pressed.
    unsigned char rowLoopCount;
    unsigned char columnLoopCount;

    //Loop for maximum rows configured
    for(rowLoopCount=rowBitNumbers[0];rowLoopCount<=rowBitNumbers[NUM_ROWS-1];rowLoopCount++)
    { 

        // Make the Row as output port. So row will be low at this moment
        ROW_DDR|=(1<<rowBitNumbers[rowLoopCount]);
        //CL_delayMS(1);    // Wait for 1 msec. 


        // Repeat for columns. Read each column.
        for(columnLoopCount=columnBitNumbers[0];columnLoopCount<=columnBitNumbers[NUM_COLS-1] ;columnLoopCount++)
        {
            if(readSwitch(columnLoopCount))
            {
                key=(keyAssignments[rowLoopCount][columnLoopCount]);
            }
        }

        // Change the direction as input so that port goes to high impedance
        ROW_DDR &=  ~(1<<rowBitNumbers[rowLoopCount]);

    }
    return(key);

    }
4

2 回答 2

1

仔细看看你的循环,可能它们不覆盖 (0,0) 对,而是从 (1,1) 开始。

于 2015-06-08T09:23:50.493 回答
0

发现了错误。getKey() 函数存在一些问题。以下是代码(可能未优化)。此外,我正在使用开放式收集器行并使用 DDR 动态更改方向,以避免在多次按键的情况下键盘短路。不确定这是否是正确的方法。

  /*
 * keypad.c
 *
 * Created: 30-05-2015 07:09:51
 *  
 */ 
#include "cloudECommon.h"

#define ROW_DDR DDRD          //I/O Port to which rows are connected
#define ROW_PORT PORTD        // I/O Port to which rows are connected
#define COLUMN_PIN PIND     // I/O Port to which columns are connected
#define COLUMN_DDR DDRD
#define NUM_ROWS 2          // Number of rows in the keypad
#define NUM_COLS 2          // number of columns in the keypad


unsigned char rowBitNumbers[NUM_ROWS] = {2,3};  // Assign port bit numbers  based on the hardware connectivity
unsigned char columnBitNumbers[NUM_COLS] = {0,1};  // Assign port bit numbers based on the hardware connectivity

// keyAssignments gives the value of the key pressed. This sends out character value to the calling portion.

unsigned char keyAssignments[NUM_ROWS][NUM_COLS] = {
                                                        {'3', 'A'},
                                                        {'6', 'B'},
                                                   };

/*
unsigned char keyAssignments[NUM_ROWS][NUM_COLS] = {
                                                        {'1','2','3','A'},
                                                        {'4','5','6','B'},
                                                        {'7','8','9','C'},
                                                        {'*','0','#','D'},
                                                    };
                                                    */


void CL_delayMS(unsigned int delayMS)
{
      while(delayMS--) 
      {
          _delay_ms(1);
      }
}

int initializeKeyPad(void)
{
    unsigned char loopCnt;

    for(loopCnt=rowBitNumbers[0];loopCnt<=rowBitNumbers[NUM_ROWS-1];loopCnt++)
    {
        ROW_DDR &= ~(1<<loopCnt);     // Set direction as input 
        ROW_PORT &= ~(1<<loopCnt);   // Keep all rows in high impudence by writing 0. External pull ups are connected.

    }

    // Set all columns as inputs
    for(loopCnt=columnBitNumbers[0]; loopCnt<=columnBitNumbers[NUM_COLS-1]; loopCnt++)
    {
        COLUMN_DDR &= ~(1<<loopCnt);           

    }
    return 0;
}


// The following function just reads the state of the switch from the key matrix 
// If detected, returns true. Or returns false.

unsigned char readSwitch(unsigned char columnNum)
{
    //check if key is pressed. If pressed, wait until it is released. 
    if(!(COLUMN_PIN & (1<<columnNum)))
    {
        //wait for release
        //while(!(COLUMN_PIN & (1<<columnNum)));

        //Key De bounce.
        // Need to change this implementation. Time is getting wasted. Even after releasing, CPU will wait for KEY_DEBOUNCE_TIME

        CL_delayMS(KEY_DEBOUNCE_TIME);
        if(!(COLUMN_PIN & (1<<columnNum)))
        {
            return (1);
        }

    }
        return(0);
}

// Function to read the key that is being pressed.
// Returns the value of the key pressed.
// First one row will be set low and then all the columns are read. 
// Process is repeated for all the rows.

unsigned char getKey(void)
{
    unsigned char key='\0';  // If '\0' is returned, no key is pressed.
    unsigned char rowLoopCount;
    unsigned char columnLoopCount;

    //Loop for maximum rows configured
    for(rowLoopCount=rowBitNumbers[0];rowLoopCount<=rowBitNumbers[NUM_ROWS-1];rowLoopCount++)
    { 

        // Make the Row as output port. So row will be low at this moment
        ROW_DDR|=(1<<rowBitNumbers[rowLoopCount-rowBitNumbers[0]]);

        // Repeat for columns. Read each column.
        for(columnLoopCount=columnBitNumbers[0];columnLoopCount<=columnBitNumbers[NUM_COLS-1] ;columnLoopCount++)
        {
            if(readSwitch(columnLoopCount))
            {
                // Since keyAssignments[][] is always starts from 0  and rowBitNumbers[] or columnBitNumbers[]
                //may not start from 0, we need to subtract the BitNumbers offset.
                key=(keyAssignments[rowLoopCount-rowBitNumbers[0]][columnLoopCount-columnBitNumbers[0]]);
            }
        }

        // Change the direction as input so that port goes to high impedance
        ROW_DDR &=  ~(1<<rowBitNumbers[rowLoopCount-rowBitNumbers[0]]);
    }
    return(key);

    }
于 2015-06-08T16:08:36.070 回答