AVR键盘代码问题

时间:2015-06-07 09:59:58

标签: avr avr-gcc atmega16

我已经编写了用于在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);

    }

2 个答案:

答案 0 :(得分:1)

仔细观察你的循环,可能是它们不覆盖(0,0)对但是从(1,1)开始就像。

答案 1 :(得分: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);

    }