zsmbj的笔记 https://bbs.21ic.com/?10673 [收藏] [复制] [RSS]

日志

我设计的用AVR的n个io实现的n×n个键盘的方案

已有 628 次阅读2006-11-16 15:48 |系统分类:单片机| 按键, 扫描

电路如图,下面的例子用4个io实现16个按键的方案。

原理:
AVR单片机内部的IO上拉电阻大约在36K欧姆,初始化设置4列IO为输入,并启动内部上拉电阻。

当没有任何按键按下时,任何一个IO的输入电压为:
Vin =(1000K+2K)/(1000 K+2K+36K)×Vcc= 0.965×Vcc。
这个电压对于单片机来说算是高电平。

当其中一个按键按下后,该列的输出电压变成:
Vin =2K /(2K+36K)×Vcc= 0.052×Vcc。
这个电压对于单片机来说算是低电平。

单片机可以启动按键电平改变中断,或者扫描检测IO。当该IO由高变成低后,则说明该列有一个按键按下,单片机记录PC口的PIN值。
然后单片机取消内部的上拉电阻,并将变低的列输出高电平,输出管脚高电平为Vcc,其负载电阻为2K,与该2K电阻连接的1M电阻将另外一路输入变成高电平,其余为低电平。再次读取PC口的PIN值。根据2次读取得值来判断按键.

下面举一个具体的例子,说明一个按键的读取。
1、    初始化,4个IO设置成为输入,带内部上拉电阻。
2、    如按键9被按下,则PC1管脚变成低电平,单片机读取PC口,键值为1101。
3、    单片机取消内部上拉,并将PC1设置成为输出高电平,如果按键9仍然按下,则与按键9相连的2K电阻R3输出为高电平,与2K连接的1M电阻R7输出也为高,其他口由于1M和2K电阻的下拉则输出为低,单片机读取PC口,键值为0110。
4、    将键值1左移4位和键值2相加:键值为11010110,等于0xd6。
5、    根据键值表查到按键的相应键值。

键值表如下:

按键名称    键值        按键名称    键值    
1    01111001    0x79    7    01111100    0x7c
2    10110101    0xb5    8    10110100    0xb4
3    11010011    0xd3    9    11010110    0xd6
a    11100001    0xe1    c    11100101    0xe5
4    01111010    0x7a    *    01111000    0x78
5    10110110    0xb6    0    10111100    0xbc
6    11010010    0xd2    #    11011010    0xda
b    11100011    0xe3    d    11101001    0xe9
没有按键    11110000    0xf0            

 


 

程序如下:

 

//winavr20060421
//last edit 2006/11/12
//copyright by zsmbj

#define    KeyDir        DDRC
#define    KeyPort        PORTC
#define    KeyVal        PINC
#define    NoKey        0xff

unsigned char    PROGMEM    KEYTAB2[17][2]={
            {0xf0,0xff},
            {0x79,'1'},{0xb5,'2'},{0xd3,'3'},{0xe1,'a'},
            {0x7a,'4'},{0xb6,'5'},{0xd2,'6'},{0xe3,'b'},
            {0x7c,'7'},{0xb4,'8'},{0xd6,'9'},{0xe5,'c'},
            {0x78,'*'},{0xbc,'0'},{0xda,'#'},{0xe9,'d'}
            };  
unsigned char GetPortkey2(void)
{
    unsigned char        i,getkey;
    unsigned char        temp_getkey = NoKey        ;


    KeyPort |= 0x0f;                //key input with pullup
    KeyDir &= 0xf0;                //PC low 4 bit input
    asm("nop");
    asm("nop");
    getkey  = KeyVal & 0x0f;        //get 4 bit

    KeyPort &= 0xf0;                //key input without pullup
    KeyDir |= ~getkey;                //
    asm("nop");
    asm("nop");
    getkey <<= 4;                    //
    getkey += KeyVal & 0x0f;        //get 4 bit

    KeyPort |= 0x0f;                 //key input with pullup
    KeyDir &= 0xf0;                //PC low 4 bit input
    
    for(i=0;i<17;i++)                //scan key value
    {
        if( getkey == pgm_read_byte(KEYTAB2[0]) )
        {
            temp_getkey= pgm_read_byte(KEYTAB2[1]);    //get key value
            break;
        }
    }
    return temp_getkey;
}

路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新日志

评论 (0 个评论)