2012年3月24日 星期六
實用技巧 -- 使用一個ADC Port來實現多顆按鍵的判別
在之前的文章有稍微提到可利用一個ADC port來實現16個按鍵的判別, 這個技術被廣泛的應用在各類的3C或家電產品,
電路的接法請看下圖
它的動作原理是當沒有任何按鍵被按下時, Adc_Key這個loop沒有任何的電壓, 所以經由ADC讀到的值為0(R17和C16構成RC filter, 這很重要, 不然ADC的值也許會因為noise voltage而跳來跳去, 造成不穩定的adc value), 假設現在SW3被按下, Adc_key的電壓=R18/(R10+R18)*5=4.545V , 轉成8bit的ADC值=(4.545/5)*256=232左右, 轉成10bit的ADC值=(4.545/5)*1024=930左右, 這是理論值, 如果實際得到的值小於這個數字, 代表你的ADC module裡的Chold電容並沒有被充飽就啟動了ADC轉換, 才會得到實際數字小於理論數字, 更改一下ADC轉換的clock, 或delay一下, 應該就可以解決, 當然也有可能是因為layout或noise造成這種現象, 但是這種現象並不會影嚮按鍵判斷的功能, 而其它的按鍵以此類推 ...
有了硬體, 再會就是軟體了, 這也是很重要的一環, 底下是一個應用的例子, 先看一下主程式部份
void main()
{
int1 Adc_Read=0;
unsigned long CH1_ADC_Value=0;
setup_adc_ports(AN0); //指定AN0為ADC port
setup_adc(ADC_CLOCK_INTERNAL); //設定ADC轉換的時間
set_adc_channel(0); //啟動AN0的ADC function
do{
delay_ms(10);
CH1_ADC_Value=read_adc();
if ( (CH1_ADC_Value >=100) && (Adc_Read==0) ) //以Adc_Read來代表已讀取Adc Value
{
Adc_Read=1;
AdcKeyCheck(CH1_ADC_Value);
}
else if( (CH1_ADC_Value <=100) && (Adc_Read==1))
Adc_Read=0; //沒按鍵時, 清除adc_read指標
} while(True);
}
現來看一下當讀取到adc的值時, 呼叫AdcKeyCheck這個副函式來判別到底是那一個鍵被按下
void AdcKeyCheck(unsigned long AdcValue)
{
printf("\n\rADC Value=%Lu",AdcValue);
if ((AdcValue <= 835) & (AdcValue >= 735))
printf("\n\r You Press UP Key!!! ADC Value=%Lu",AdcValue);
else if ((AdcValue <= 206) & (AdcValue >= 106))
printf("\n\r You Press Down Key!!! ADC Value=%Lu",AdcValue);
else if ((AdcValue <= 650) & (AdcValue >= 550))
printf("\n\r You Press Left Key!!! ADC Value=%Lu",AdcValue);
else if ((AdcValue <= 349) & (AdcValue >= 249))
printf("\n\r You Press Right Key!!! ADC Value=%Lu",AdcValue);
else if ((AdcValue <= 492) & (AdcValue >= 392))
printf("\n\r You Press Enter Key!!! ADC Value=%Lu",AdcValue);
}
如果以上的AdcValue跟你實際看到的不同, 也不用緊張, 改成你看到的實際值並不會影嚮到按鍵檢查的功能, 我目前是設定
AdcValue的中心值+/- 50, 這是我個人的慣用值, 目前使用起來並沒有遇到按鍵失靈的問題, 和大家分享這個實用的小技巧
訂閱:
張貼留言 (Atom)
如果有2顆按鍵同時按下的話會造成誤判耶
回覆刪除有辦法按鍵1按下值為512;按鍵2按下為256;2顆同時按下變768嗎?
你可以算一下歐姆定律,兩顆同時按下等於是並聯電阻
刪除複合按鍵用ADC的方法較難, 請改用HC74165, 並列輸入序列輸出, 用這個方法, 單按複合按鍵都很簡單, 你可以試看看
回覆刪除