用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);//这个在串口助手中换行
}
} 小弟初次在本论坛上发贴子,文笔不是很好,大家凑活着看 mark 有创意,不过你是不是对分压电阻的精度要求很高啊?
再者,如果两个或者两个以上的按键按下,你能确定出来吗? 不错呀 记号 不错·!可尝试用一个IO口实现6万5千5百35个按键的检测。。。 这个可以检测多个按键,至于电阻精度要求,可以自己计算。
http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_589752VPKNOF.JPG
AD-KEY (原文件名:AD-KEY.JPG) mark! 泼点冷水,正式产品不建议用AD按键!主要是国内的按键质量太水,出货的时候好好的,半年下来,大量的返修,烦死了,血泪教训! 缺少文件!!!main.h里面是什么内容?不能忽悠群众哦! mark mark!还是首次听说AD按键这种设计方式! mark……
顶一个… 好想法!!! {:smile:}mark 嗯,通过检测电压值来判断对应的按键,很多都是这样做的 MP3上好多都是这样的 不明觉厉! mark.......... 本帖最后由 stm8s 于 2014-3-9 21:27 编辑
工控AD说再可靠也不用到时候都不知是怎么死的 AD做不了组合按键
页:
[1]