一、簡介
在嵌入式系統產品開發中,按鍵板的設計是最基本的,也是項目評估階段必須要考慮的問題。其實現方式有很多種,具體使用那一種就需要結合可用IO數量,并綜合考慮成本,做出最終選擇。傳統的按鍵檢測方法是一個按鍵對應一個GPIO口,進行高低電平輸入檢測。可是在GPIO口緊缺的情況下,不得不需要一個有效的解決方案,其中ADC檢測實現按鍵功能是一種相對有效的解決方案。
ADC檢測實現簡單實用的按鍵方法:僅需要一個ADC和若干個電阻就可實現多個按鍵的輸入檢測。工作原理:按下按鍵時,通過電阻分壓得到不同的電壓值,ADC采集在各個范圍內的值來判定是哪個按鍵按下。
本文采用RK2206芯片自帶的逐次逼近寄存器型模數轉換器(Successive-Approximation Analog to Digital Converter),是一種常用的A/D轉換結構,其較低的功耗表現,不錯的轉換速率,在有低功耗要求(可穿戴設備、物聯網)的數據采集場景下廣泛應用。
二、硬件電路設計
ADC檢測實現簡單實用的按鍵方法:僅需要一個ADC和若干個電阻就可實現多個按鍵的輸入檢測。工作原理:按下按鍵時,通過電阻分壓得到不同的電壓值,ADC采集在各個范圍內的值來判定是哪個按鍵按下。
模塊整體硬件電路如下圖所示,電路中包含了1根ADC引腳和4個按鍵。
圖1 硬件電路圖
其中,4個按鍵分別連接不同的電阻。當按鍵按下時,USER_KEY_ADC檢測到不同的電壓。具體如下所示:
表1 按鍵對應電壓表
USER_KEY_ADC引腳連接到RK2206芯片的GPIO0_C5,如下圖所示:
圖2 USER_KEY_ADC引腳的硬件電路圖
三、ADC接口
ADC相應接口頭文件在:
/device/rockchip/rk2206/adapter/include/lz_hardware.h
RK2206芯片提供以下兩大類接口:
(1)初始化、銷毀ADC;
(2)ADC讀操作。
具體接口如PPT所示。以下我們詳細講解這些接口。
(1)LzSaradcInit
該函數主要功能是SARADC設備初始化。
int LzSaradcInit(void);
成功返回LZ_HARDWARE_SUCCESS, 其余為失敗。
(2)LzSaradcDeinit
該函數主要功能是SARADC設備釋放。
int LzSaradcDeinit(void);
成功返回LZ_HARDWARE_SUCCESS, 其余為失敗。
(3)LzSaradcReadValue
該函數主要功能是SARADC設備讀取。
int LzSaradcReadValue(unsigned int chn, unsigned int *val);
參數chn:ADC通道id;
參數val:讀取值。
成功返回LZ_HARDWARE_SUCCESS, 其余為失敗。
四、程序設計
ADC按鍵程序每1秒通過GPIO0_PC5讀取一次按鍵電壓,通過電壓數值判斷當前是哪個按鍵被按下,并打印出該按鍵名稱。
如圖所示為ADC按鍵主程序流程圖,開機LiteOS系統初始化后,進入主程序先初始化ADC設備。程序進入主循環,1秒獲取一次ADC采樣電壓,判斷:
(1)采樣電壓在0.00~0.11V之間,則當前是按下Key1,打印Key1;
(2)采樣電壓在0.45~0.65V之間,則當前是按下Key2,打印Key2;
(3)采樣電壓在0.90~1.1V之間,則當前是按下Key3,打印Key3;
(4)采樣電壓在1.55~1.75V之間,則當前是按下Key4,打印Key4;
(5)當前無按鍵。
圖3主程序流程圖
void adc_process()
{
float voltage;
/* 初始化adc設備 */
adc_dev_init();
while (1)
{
printf("***************Adc Example*************\r\n");
/*獲取電壓值*/
voltage = adc_get_voltage();
printf("vlt:%.3fV\n", voltage);
if ((0.11 >= voltage) && (voltage >= 0.00))
{
printf("\tKey1\n");
}
else if ((0.65 >= voltage) && (voltage >= 0.45))
{
printf("\tKey2\n");
}
else if ((1.1 >= voltage) && (voltage >= 0.9))
{
printf("\tKey3\n");
}
else if ((1.75 >= voltage) && (voltage >= 1.55))
{
printf("\tKey4\n");
}
/* 睡眠1秒 */
LOS_Msleep(1000);
}
}
ADC初始化程序主要分為ADC初始化和配置ADC參考電壓為外部電壓兩部分:
static unsigned int adc_dev_init()
{
unsigned int ret = 0;
uint32_t *pGrfSocCon29 = (uint32_t *)(0x41050000U + 0x274U);
uint32_t ulValue;
ret = DevIoInit(m_adcKey);
if (ret != LZ_HARDWARE_SUCCESS)
{
printf("%s, %s, %d: ADC Key IO Init fail\n", __FILE__, __func__, __LINE__);
return __LINE__;
}
ret = LzSaradcInit();
if (ret != LZ_HARDWARE_SUCCESS) {
printf("%s, %s, %d: ADC Init fail\n", __FILE__, __func__, __LINE__);
return __LINE__;
}
/* 設置saradc的電壓信號,選擇AVDD */
ulValue = *pGrfSocCon29;
ulValue &= ~(0x1 << 4);
ulValue |= ((0x1 << 4) << 16);
*pGrfSocCon29 = ulValue;
return 0;
}
RK2206芯片采用一種逐次逼近寄存器型模數轉換器(Successive-Approximation Analog to Digital Converter),是一種常用的A/D轉換結構,其較低的功耗表現,還不錯的轉換速率,在有低功耗要求(可穿戴設備、物聯網)的數據采集場景下廣泛應用。該ADC采用10bit采樣,最高電壓為3.3V。簡而言之,ADC采樣讀取的數據,bit[0~9]有效,且最高數值0x400(即1024)代表實際電壓差3.3V,也就是說1個數值等于3.3V / 1024 = 0.003222V。
static float adc_get_voltage()
{
unsigned int ret = LZ_HARDWARE_SUCCESS;
unsigned int data = 0;
ret = LzSaradcReadValue(ADC_CHANNEL, &data);
if (ret != LZ_HARDWARE_SUCCESS)
{
printf("%s, %s, %d: ADC Read Fail\n", __FILE__, __func__, __LINE__);
return 0.0;
}
return (float)(data * 3.3 / 1024.0);
}
五、編譯過程
1、打開sdk下面路徑的文件
/vendor/lockzhiner/rk2206/samples/b1_adc/adc_example.c
注意:Gitee上的ADC案例為通用案例,請大家根據上述的需求修改相關源代碼。
2、修改編譯腳本
修改 vendor/lockzhiner/rk2206/sample 路徑下 BUILD.gn 文件,指定 adc_example 參與編譯。
“./b0_adc:adc_example”,
修改 device/lockzhiner/rk2206/sdk_liteos 路徑下 Makefile 文件,添加 -ladc_example 參與編譯。
hardware_LIBS = -lhal_iothardware -lhardware -ladc_example
3、編譯固件
hb set -root .
hb set
hb build -f
4、燒寫固件
5、通過串口查看結果
運行結果
***************Adc Example*************
vlt:3.297V
***************Adc Example*************
vlt:3.297V
***************Adc Example*************
vlt:3.297V
***************Adc Example*************
vlt:3.297V
***************Adc Example*************
vlt:3.297V
***************Adc Example*************
vlt:3.297V
……
-
嵌入式開發
+關注
關注
18文章
1006瀏覽量
47349 -
OpenHarmony
+關注
關注
25文章
3545瀏覽量
15728 -
凌智電子
+關注
關注
1文章
21瀏覽量
1040
發布評論請先 登錄
相關推薦
評論