mtswz213 发表于 2010-4-20 19:58:15

用AD做的键盘,在一个开发板上用的,比较可靠,代码比较全

这是我做的一个小项目,是一个电能表开发板,用一个类似于遥控器的东西采集电表数据,由于种种原因只能用HT46F49E单片机,有AD,但IO口不是很多,要做一个4*6的键盘,如果用普通的那种矩阵键盘,IO口不肯定不够,于是就想到了AD键盘,舍也不说了,上图:
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_547800.JPG
4*6的键盘,图画的不是很好看,大家揍活着看 (原文件名:key.JPG)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_547801.jpg
把这个键盘分解了看也就是跟这个类似 (原文件名:ourdev_543627.jpg)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_547802.jpg
没用这个键盘,主要是考虑到用这个AD必须有一个比较准的参考电压,而这个单片机参考电压就是电源电压 (原文件名:ourdev_200564.jpg)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_547803.JPG
这个是当AD采集的值,然后用串口发到电脑上用EXCEL做的表,由这个图可以看出,有按键时,电压上升的很快,释放时电压下降的慢一点,按下时电压比较平稳,因此要滤波,AD采样两次,如果电压值相等才认为AD采样有效 (原文件名:ad.JPG)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_547804.JPG
这个是键盘做好后用串口采集的键盘值 (原文件名:123.JPG)





上代码:(1)这个是键盘头文件,放在KEYBOARD.h中:
void ini_adc();
void start_adc();
unsigned char get_key();

#define key1h        222
#define key1l        212
#define key2h        185
#define key2l        175
#define key3h        148
#define key3l        138
#define key4h        113
#define key4l        103
#define key5h        77
#define key5l        67
#define key6h        41
#define key6l        31
#define nokeyh        6
#define nokeyl        0




(2):这个是键盘处理程序,放在KEYBOARD.c中:
#include "HT46F49E.h"
#include "KEYBOARD.h"
void ini_adc()
{
        _pb=_pbc|0b00001111;
        _acsr=2;//选择ADC的转换速度为SYS/8
        _adcr=0b111111;//使能PB0—PB3为ADC通道,但未设置当前ADC是那个通道
}
/*下面的这个函数是讲读取某一通道的KEY值,且有滤波程序*/
unsigned char get_key_volu(unsigned char channel)
{
        unsigned char temp,t;
        unsigned char key_buffer;
get_err:
        for(t=0;t<2;t++)
        {
                _adcr=0b01111000;//ADC通道归零,start=0
                _adcr=0b11111000|channel;//设置ADC转换通道,start=1
                _adcr=_adcr&0b01111111;//开始ADC转换,start=0
                while(_eocb);//等待ADC转换结束
                temp=_adrh;
                if(temp<nokeyh)key_buffer=25;
                else if(temp<key1h&&temp>key1l)key_buffer=1;
                else if(temp<key2h&&temp>key2l)key_buffer=2;
                else if(temp<key3h&&temp>key3l)key_buffer=3;
                else if(temp<key4h&&temp>key4l)key_buffer=4;
                else if(temp<key5h&&temp>key5l)key_buffer=5;
                else if(temp<key6h&&temp>key6l)key_buffer=6;
                else goto get_err;//如果不为上述值,则扫描出错,返加扫描
        }
        if(key_buffer!=key_buffer)goto get_err;//如果两次扫描值不等,则重新扫描
        return key_buffer;//只到两值相等才返回键值
}
unsigned char get_key()
{       
        unsigned char channel,t;
        unsigned char key_buffer,eok;//eok为end_of_key
no_key:
        key_buffer=get_key_volu(channel);
        /*******如果key_buffer为25则反回,扫描下一行********/
        if(key_buffer==25)
        {
                channel++;
                if(channel>3)
                {
                        channel=0;
                }
                goto no_key;
        }
        /******如果有值,算出KEY值*******/
        switch(channel)
        {
                case 1: key_buffer=key_buffer+6;break;
                case 2: key_buffer=key_buffer+12;break;
                case 3: key_buffer=key_buffer+18;break;
                default: break;
        }
        /******等释放key后再返加值**************/
end_of_key:                       
        for(channel=0;channel<4;channel++)
        {
                eok=get_key_volu(channel);
                if(eok!=25)goto end_of_key;
        }
        channel=0;
        return key_buffer;
}


(3)这个是测试程序的主程序:
#include "main.h"
unsigned char bin;

void main()
{
        unsigned char test;
        unsigned char t;
        unsigned char wc[]="The UART is ready";
        ini_uart();
        ini_adc();
        for(t=0;t<17;t++)
        {
                uart_tran(wc);
        }
        uart_tran(0x0d);uart_tran(0x0a);//这个在串口助手中换行
        while(1)
        {
                test=get_key();
                        if(test>19)
                        {
                                bin=50;
                                bin=(28+test);
                        }
                        else if(test>9)
                        {
                                bin=49;
                                bin=(38+test);
                        }
                        else
                        {
                                bin=0;
                                bin=test+48;
                        }
                        if(bin!=0)uart_tran(bin);
                        uart_tran(bin);
                        uart_tran(0x0d);uart_tran(0x0a);//这个在串口助手中换行
        }
}

mtswz213 发表于 2010-4-20 20:02:32

小弟初次在本论坛上发贴子,文笔不是很好,大家凑活着看

ilearnit 发表于 2010-4-27 09:04:56

mark

zjj841011 发表于 2010-4-27 09:33:03

有创意,不过你是不是对分压电阻的精度要求很高啊?
再者,如果两个或者两个以上的按键按下,你能确定出来吗?

coolwater 发表于 2010-9-29 12:09:26

不错呀

zxpt 发表于 2010-10-6 15:47:30

记号

baozhen1989 发表于 2010-10-14 11:39:03

不错·!可尝试用一个IO口实现6万5千5百35个按键的检测。。。

chenhuayuan 发表于 2010-10-14 12:00:54

这个可以检测多个按键,至于电阻精度要求,可以自己计算。

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_589752VPKNOF.JPG
AD-KEY (原文件名:AD-KEY.JPG)

dachun 发表于 2010-10-14 13:17:06

mark!

feiyue 发表于 2010-10-14 13:23:33

泼点冷水,正式产品不建议用AD按键!主要是国内的按键质量太水,出货的时候好好的,半年下来,大量的返修,烦死了,血泪教训!

Erics 发表于 2011-4-14 21:42:53

缺少文件!!!main.h里面是什么内容?不能忽悠群众哦!

hongxp 发表于 2011-10-31 22:54:55

mark

Benjamin.F 发表于 2011-11-16 20:18:44

mark!还是首次听说AD按键这种设计方式!

xiefy21 发表于 2013-8-13 22:42:28

mark……
顶一个…

我是谁712 发表于 2013-10-5 12:45:55

好想法!!!

lcmdw 发表于 2013-10-5 15:06:19

{:smile:}mark

zxd08 发表于 2013-10-8 14:33:18

嗯,通过检测电压值来判断对应的按键,很多都是这样做的

lulinchen 发表于 2013-10-8 14:34:46

MP3上好多都是这样的

zlxd1990 发表于 2014-3-9 13:42:36

不明觉厉!

机器人天空 发表于 2014-3-9 21:23:48

mark..........

stm8s 发表于 2014-3-9 21:25:03

本帖最后由 stm8s 于 2014-3-9 21:27 编辑

工控AD说再可靠也不用到时候都不知是怎么死的

waothom 发表于 2014-4-8 11:55:11

AD做不了组合按键
页: [1]
查看完整版本: 用AD做的键盘,在一个开发板上用的,比较可靠,代码比较全