本文來(lái)源電子發(fā)燒友社區(qū),作者:juby, 帖子地址:https://bbs.elecfans.com/jishu_2008496_1_1.html
獲取按鍵值的方式
圖片來(lái)源程序員小哈自制核心板原理圖


按鍵原理圖



獲取ADC值

1. 引腳初始化

hi_io_set_func(HI_IO_NAME_GPIO_5, HI_IO_FUNC_GPIO_5_GPIO);
ret = hi_gpio_set_dir(HI_GPIO_IDX_5, HI_GPIO_DIR_IN);
if (ret != HI_ERR_SUCCESS) {
printf("===== ERROR ======gpio -> hi_gpio_set_dir1 ret:%drn", ret);
return;
}
2. 獲取ADC值
for (i = 0; i < ADC_TEST_LENGTH; i++) {
ret = hi_adc_read((hi_adc_channel_index)HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_1, HI_ADC_CUR_BAIS_DEFAULT, 0);
if (ret != HI_ERR_SUCCESS) {
printf("ADC Read Failn");
return;
}
g_adc_buf= data;
}

3. 對(duì)數(shù)組中的ADC值進(jìn)行數(shù)據(jù)處理,計(jì)算方法為取這些數(shù)據(jù)的和,然后減去其中的最大值和最小值,然后再取平均值。hi_u32 i;
float vlt_max = 0;
float vlt_min = VLT_MIN;
float vlt_sum = 0;
float vlt_val = 0;
hi_u16 vlt;
for (i = 0; i < data_len; i++) {
vlt = g_adc_buf;
float voltage = hi_adc_convert_to_voltage(vlt);
vlt_max = (voltage > vlt_max) ? voltage : vlt_max;
vlt_min = (voltage < vlt_min) ? voltage : vlt_min;
vlt_sum += voltage;
}
vlt_val = (vlt_sum - vlt_min - vlt_max) / (data_len - 2.0);

串口打印輸出

2. 當(dāng)按下按鍵S2(核心板)時(shí),ADC值的范圍在 0.214 ~ 0.218之間,串口打印輸出如下:

3. 當(dāng)按下按鍵S1(OLED)時(shí),ADC值的范圍在 0.569 ~ 0.573之間,串口打印輸出如下:

4. 當(dāng)按下按鍵S2(OLED)時(shí),ADC值的范圍在 0.970 ~ 0.974之間,串口打印輸出如下:

5. 結(jié)果匯總[td]
6. 按adc值的范圍區(qū)間,判斷按鍵值
{
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S2_CORE;
}
}
if((vlt_val > 0.4) && (vlt_val < 0.7))
{
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S1_OLED;
}
}
if((vlt_val > 0.8) && (vlt_val < 1.1))
{
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S2_OLED;
}
}
if(vlt_val > 3.0)
{
key_flag = 0;
key_status = KEY_EVENT_NONE;
}
7. 編譯腳本文件BUILD.gn
獲得HiBurn軟件1. 解壓DevEcoDeviceTool-1.0.0.zip
2. 將解壓后生成的.vsix文件重命名為.zip結(jié)尾的任意名稱,比如:DevEcoDeviceTool-1.0.0-temp.zip , 然后解壓此文件。

3. 在 devicetool-device-1.0.0.0extensiondevecotools 文件夾下即有HiBurn.exe 文件。

使用HiBurn燒寫.bin文件至Hi3861
和DevEco Device Tool方式對(duì)比
獲取按鍵值的方式
按鍵作為常用的輸入系統(tǒng),如何準(zhǔn)確并高效的獲取按鍵值,是一個(gè)經(jīng)常要面對(duì)的問(wèn)題,常用的按鍵檢測(cè)方式有如下幾種方式:
1. 獨(dú)立按鍵
每個(gè)按鍵的檢測(cè)占用單片機(jī)的一個(gè)GPIO引腳,原理圖如下圖所示:

圖片來(lái)源程序員小哈自制核心板原理圖
我們以BTN1按鍵為例,當(dāng)按鍵沒有按下的時(shí)候,網(wǎng)絡(luò)標(biāo)號(hào)KEY1處的電壓被10K的上拉電阻拉至3.3V,PB14(KEY1)引腳設(shè)為輸入引腳后,程序中讀取該引腳的值將為1,當(dāng)按鍵按下之后,網(wǎng)絡(luò)標(biāo)號(hào)KEY1處接地,讀取該輸入引腳的值將為0,進(jìn)而通過(guò)此電路實(shí)現(xiàn)的獨(dú)立按鍵,可以區(qū)分按鍵彈起和按下兩種不同的狀態(tài)。
獨(dú)立按鍵的每個(gè)按鍵的工作不會(huì)影響其他I/O的狀態(tài)。獨(dú)立按鍵缺點(diǎn)是浪費(fèi)MCU管腳,優(yōu)點(diǎn)是編程比較簡(jiǎn)單。
獨(dú)立按鍵的實(shí)現(xiàn)原理詳見我們之前分享的網(wǎng)文:基于鴻蒙OS的按鍵驅(qū)動(dòng)
2. 矩陣按鍵
矩陣按鍵又稱為矩陣鍵盤或稱行列鍵盤,其實(shí)現(xiàn)的原理我們之前分享過(guò)如下網(wǎng)文:
矩陣鍵盤的行列掃描原理詳解
這種行列式鍵盤結(jié)構(gòu)能有效地提高單片機(jī)系統(tǒng)中I/O口的利用率。在MCU管腳有限的情況下,矩陣按鍵大大的節(jié)省了I/O資源。
3. ADC分壓鍵盤
利用電阻串聯(lián)分壓的原理實(shí)現(xiàn)一個(gè)ADC管腳去檢測(cè)多個(gè)按鍵。
按鍵被按下之后,與ADC引腳相連的點(diǎn)的電壓會(huì)隨著參與分壓的電阻變化而變化,我們只要讓每個(gè)按鍵按下之后的電壓處于不同的區(qū)間,我們理論上就能夠?qū)⒏鱾€(gè)按鍵區(qū)分開。
為了避免由于ADC精度、電阻的誤差或者溫漂等因素造成的按鍵檢測(cè)失效,提高按鍵檢測(cè)的可靠性,我們可以減少按鍵數(shù)量,適當(dāng)放寬各個(gè)按鍵檢測(cè)的電壓范圍。
經(jīng)過(guò)上面的分析,獨(dú)立按鍵的方式是最浪費(fèi)GPIO口,矩陣按鍵的效率適中,而ADC分壓實(shí)現(xiàn)的鍵盤使用的GPIO引腳最少。
ADC檢測(cè)按鍵原理
如果Vcc = 3.3V ,那么沒有按鍵被按下時(shí),ADC為3.3V,如果有按鍵被按下:
[td]
被按下的按鍵 | ADC值 |
Key1 | 0 V |
Key2 | 1.65 V |
Key3 | 2.2 V |
Key4 | 2.475 V |
Key5 | 2.64 V |
Key6 | 2.75 V |
我們由上可以看到,一串相同電阻(10K)組成的多個(gè)按鍵,相連按鍵之間的電壓差越來(lái)越小,不利于繼續(xù)進(jìn)行擴(kuò)展。

如果 +5V 換成 3.3V ,那么沒有按鍵被按下時(shí),ADC為3.3V,如果有按鍵被按下:
[td]
被按下的按鍵 | ADC值 |
sw1 | 0 V |
sw2 | 0.163 V |
sw3 | 0.503 V |
sw4 | 0.819 V |
sw5 | 1.157 V |
sw6 | 1.487 V |
由上我們看出,這組電阻組成的多個(gè)按鍵檢測(cè)電路,相連按鍵之間的電壓差值基本在0.3V左右,可以在此電路基礎(chǔ)上繼續(xù)進(jìn)行擴(kuò)展,設(shè)計(jì)成更多的按鍵掃描電路。
有了上面的經(jīng)驗(yàn),大家算一下下圖中,不同按鍵按下的話,ADC的值應(yīng)該為多少呢?

按鍵原理圖

核心板左下角的按鍵S2的原理圖:

OLED板上的按鍵1和按鍵2的原理圖:

由上面兩個(gè)原理圖可知,三個(gè)按鍵都是與GPIO05這個(gè)引腳相連,根據(jù)上面ADC分壓的原理我們可知,當(dāng)三個(gè)按鍵按下時(shí),GPIO05處的理論電壓如下:
[td]
被按下的按鍵 | 理論電壓 |
常態(tài)(沒有按鍵按下時(shí)) | 3.3 V |
S2(核心板) | 0V |
S1(OLED) | (1/(4.7+1))*3.3=0.579 V |
S2(OLED) | (2/(4.7+1+1))*3.3=0.985 V |
官方手冊(cè)ADC功能描述如下:

1. 引腳初始化

由于GPIO5默認(rèn)被復(fù)用為串口引腳,我們這里要想使用ADC功能,而上圖表格中沒有對(duì)應(yīng)的ADC復(fù)用信號(hào),所以我們只需要將GPIO_05設(shè)為普通GPIO輸入引腳即可。初始化代碼如下:
(hi_void)hi_gpio_init();hi_io_set_func(HI_IO_NAME_GPIO_5, HI_IO_FUNC_GPIO_5_GPIO);
ret = hi_gpio_set_dir(HI_GPIO_IDX_5, HI_GPIO_DIR_IN);
if (ret != HI_ERR_SUCCESS) {
printf("===== ERROR ======gpio -> hi_gpio_set_dir1 ret:%drn", ret);
return;
}
2. 獲取ADC值
這里使用hi_adc_read函數(shù)獲取adc的值,為了使得到的數(shù)據(jù)相對(duì)準(zhǔn)確,我們對(duì)數(shù)據(jù)進(jìn)行多次采集,然后將得到的數(shù)據(jù)緩存到數(shù)組中,然后再對(duì)數(shù)組中的數(shù)據(jù)進(jìn)行集中處理。
memset_s(g_adc_buf, sizeof(g_adc_buf), 0x0, sizeof(g_adc_buf));for (i = 0; i < ADC_TEST_LENGTH; i++) {
ret = hi_adc_read((hi_adc_channel_index)HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_1, HI_ADC_CUR_BAIS_DEFAULT, 0);
if (ret != HI_ERR_SUCCESS) {
printf("ADC Read Failn");
return;
}
g_adc_buf= data;
}
其中函數(shù)hi_adc_read在如下文件中實(shí)現(xiàn):
vendorhisihi3861hi3861platformdriversadchi_adc.c

3. 對(duì)數(shù)組中的ADC值進(jìn)行數(shù)據(jù)處理,計(jì)算方法為取這些數(shù)據(jù)的和,然后減去其中的最大值和最小值,然后再取平均值。hi_u32 i;
float vlt_max = 0;
float vlt_min = VLT_MIN;
float vlt_sum = 0;
float vlt_val = 0;
hi_u16 vlt;
for (i = 0; i < data_len; i++) {
vlt = g_adc_buf;
float voltage = hi_adc_convert_to_voltage(vlt);
vlt_max = (voltage > vlt_max) ? voltage : vlt_max;
vlt_min = (voltage < vlt_min) ? voltage : vlt_min;
vlt_sum += voltage;
}
vlt_val = (vlt_sum - vlt_min - vlt_max) / (data_len - 2.0);
其中函數(shù)hi_adc_convert_to_voltage的實(shí)現(xiàn)位于:vendorhisihi3861hi3861platformdriversadchi_adc.c

串口打印輸出
為了按鍵能夠準(zhǔn)確識(shí)別,我們首先要知道各個(gè)按鍵被按下時(shí),ADC的值的范圍,我們?cè)诔绦蛑蝎@取GPIO5 引腳處的ADC值,利用下面的函數(shù)進(jìn)行打印輸出,進(jìn)而觀察各種狀態(tài)下,ADC的值是多少:
printf("KEY adc value is %f rn",key_adc_value);
具體打印輸出如下:
1. 常態(tài)沒有按鍵按下時(shí),ADC值的范圍在 3.262 ~ 3.266之間,串口打印輸出如下:
2. 當(dāng)按下按鍵S2(核心板)時(shí),ADC值的范圍在 0.214 ~ 0.218之間,串口打印輸出如下:

3. 當(dāng)按下按鍵S1(OLED)時(shí),ADC值的范圍在 0.569 ~ 0.573之間,串口打印輸出如下:

4. 當(dāng)按下按鍵S2(OLED)時(shí),ADC值的范圍在 0.970 ~ 0.974之間,串口打印輸出如下:

5. 結(jié)果匯總[td]
被按下的按鍵 | 理論電壓 | 實(shí)際電壓 |
常態(tài)(沒有按鍵按下時(shí)) | 3.3 V | 3.266 V |
S2(核心板) | 0V | 0.214 V |
S1(OLED) | (1/(4.7+1))*3.3=0.579 V | 0.573 V |
S2(OLED) | (2/(4.7+1+1))*3.3=0.985 V | 0.973 V |
由上可以看出,理論值跟實(shí)際值偏差不是很大,而且值相對(duì)穩(wěn)定,我們只需要在實(shí)際值基礎(chǔ)上增加一個(gè)偏差,比如0.15 V,即可區(qū)分出板子上的三個(gè)按鍵。
[td]
被按下的按鍵 | 理論電壓 | 實(shí)際電壓 | 判斷區(qū)間 |
常態(tài)(沒有按鍵按下時(shí)) | 3.3 V | 3.266 V | vlt_val > 3 V |
S2(核心板) | 0V | 0.214 V | vlt_val < 0.3 V |
S1(OLED) | 0.579 V | 0.573 V | 0.4 V < vlt_val < 0.7 V |
S2(OLED) | 0.985 V | 0.973 V | 0.8 V < vlt_val < 1.1 V |
具體判斷的實(shí)現(xiàn)如下:
if(vlt_val < 0.3)){
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S2_CORE;
}
}
if((vlt_val > 0.4) && (vlt_val < 0.7))
{
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S1_OLED;
}
}
if((vlt_val > 0.8) && (vlt_val < 1.1))
{
if(key_flag == 0)
{
key_flag = 1;
key_status = KEY_EVENT_S2_OLED;
}
}
if(vlt_val > 3.0)
{
key_flag = 0;
key_status = KEY_EVENT_NONE;
}
7. 編譯腳本文件BUILD.gn
工程中兩個(gè)編譯使用的BUILD.gn腳本文件具體實(shí)現(xiàn)如下圖所示:

獲得HiBurn軟件1. 解壓DevEcoDeviceTool-1.0.0.zip


3. 在 devicetool-device-1.0.0.0extensiondevecotools 文件夾下即有HiBurn.exe 文件。

使用HiBurn燒寫.bin文件至Hi3861

- 選擇Hi3861核心板對(duì)應(yīng)的串口,點(diǎn)擊“Select file”按鈕,選擇要下載的固件文件:Hi3861_wifiiot_app_allinone.bin,我們打開此文件之后,會(huì)發(fā)現(xiàn)下面列表中出現(xiàn)了三個(gè)文件,實(shí)際上這個(gè).bin文件由列表中的三個(gè)文件組成。勾選“Auto burn”復(fù)選框,然后選擇“Connect”按鈕,進(jìn)入如下待下載界面:

- 復(fù)位核心板模塊,進(jìn)入下載模式,下載完成后點(diǎn)擊“Disconnect”按鈕斷開連接。

使用HiBurn燒錄相對(duì)于VSCode中使用DevEco Device Tool燒錄而言,好處主要有以下幾點(diǎn):
1. 不依賴VSCode,所以下面網(wǎng)文的配置過(guò)程可以省略了;
HarmonyOS智能設(shè)備開發(fā)工具—DevEco Device Tool 安裝配置
2. 下載速度更快,HiBurn.exe最大波特率可以設(shè)置到4000000,而DevEco Device Tool最大只能為921600,是它的4.34倍;
HiBurn方式燒錄的缺點(diǎn)主要是:
1. 燒錄完成標(biāo)志不是很明顯,需要認(rèn)真觀察;2. 燒錄完成之后需要手動(dòng)點(diǎn)Disconnect,主動(dòng)斷開連接,否則將一直占用此串口;如果再未斷開的情況下,再次按了一下RESET按鍵,HiBurn軟件將會(huì)再一次對(duì)固件進(jìn)行燒錄。結(jié)果展示
依次按三次Hi3861開發(fā)套件上的三個(gè)按鍵S2(CORE)、S1(OLED)、S2(OLED),串口打印輸出如下:

ADC獲取的電壓波動(dòng)在我們?cè)O(shè)定的范圍內(nèi),所以我們看到能夠正確的識(shí)別對(duì)應(yīng)的按鍵。
小結(jié)
學(xué)習(xí)實(shí)現(xiàn)的思想,自己可以使用自己的板子實(shí)現(xiàn)一下,無(wú)論51單片機(jī)還是STM32作為主控,實(shí)現(xiàn)的原理都是一樣的,文中提供的代碼,除了獲取ADC值的方式不一樣外,其他代碼都是可以通用參考的。
參考網(wǎng)文
https://bbs.elecfans.com/jishu_2000829_1_1.html
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。
舉報(bào)投訴
-
wi-fi
+關(guān)注
關(guān)注
14文章
2230瀏覽量
126467 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
2054瀏覽量
32172 -
HiSpark
+關(guān)注
關(guān)注
1文章
156瀏覽量
7315
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
熱點(diǎn)推薦
Wi-Fi 8要來(lái)了!未來(lái)Wi-Fi技術(shù)演進(jìn)方向揭秘
產(chǎn)品銷售中,雖然Wi-Fi 7產(chǎn)品的銷量份額快速?gòu)哪瓿醯膫€(gè)位數(shù)百分比增長(zhǎng)至14%,但Wi-Fi 6產(chǎn)品的銷量份額依然穩(wěn)定在60%左右。如果從存量設(shè)備來(lái)看,那么Wi-Fi 7路由器的占比將遠(yuǎn)遠(yuǎn)小于這個(gè)數(shù)。 ? 智能手機(jī)等終端設(shè)備已

Wi-Fi HaLow如何突破傳統(tǒng)Wi-Fi性能瓶頸?
視頻推薦在萬(wàn)物互聯(lián)的時(shí)代,傳統(tǒng)Wi-Fi在覆蓋范圍、功耗、連接數(shù)上漸顯不足。而Wi-FiHaLow的誕生,正在用黑科技打破傳統(tǒng)Wi-Fi的性能瓶頸!今天,我們一起來(lái)探究

基于 Wi-Fi 的定位服務(wù)
GNSS 的低精度模式也會(huì)比 Wi-Fi 和蜂窩定位服務(wù)提供更好的定位精度,因此在測(cè)量中使用了低精度模式,我們可以看到 GNSS 與其他定位服務(wù) “最接近 ”的功耗差異。結(jié)果確實(shí)證明了這一假設(shè)
發(fā)表于 04-17 15:16
nRF Cloud Wi-Fi 定位服務(wù)
中實(shí)現(xiàn)高性能和超低功耗。對(duì)于 Wi-Fi 定位請(qǐng)求,nRF Cloud 可借助 Wi-Fi 數(shù)據(jù)庫(kù)計(jì)算設(shè)備位置,該數(shù)據(jù)庫(kù)包含不同 Wi-Fi 網(wǎng)絡(luò)的坐標(biāo)。然后,設(shè)備位置將從 nRF C
發(fā)表于 04-17 15:07
Wi-Fi 定位服務(wù)
Wi-Fi 是一種著名的無(wú)線網(wǎng)絡(luò)技術(shù),用于設(shè)備的局域網(wǎng)和互聯(lián)網(wǎng)接入。Wi-Fi 通過(guò) Wi-Fi 網(wǎng)絡(luò)為家庭、辦公室和學(xué)校等環(huán)境提供便捷的無(wú)線互聯(lián)網(wǎng)接入服務(wù)。
發(fā)表于 04-17 15:01
還不知道Nordic 有Wi-Fi 6+BLE組合?
今天給大家分享一款非常有意思的Wi-Fi 6模塊——PTR5303。
一、模塊簡(jiǎn)介
PTR5303是一款緊湊型低功耗Wi-Fi 6模塊,基于
發(fā)表于 03-12 15:20
華為海思正式進(jìn)入Wi-Fi FEM賽道?
三伍微來(lái)說(shuō),這是一個(gè)新的機(jī)遇。
也許很多人會(huì)很驚訝,海思怎么會(huì)進(jìn)入Wi-Fi FEM賽道?其實(shí),海思進(jìn)入Wi-Fi FEM賽道可以追溯到10多年前,最早在新加坡設(shè)立了
發(fā)表于 12-11 17:42
摩爾斯微電子發(fā)布Wi-Fi HaLow評(píng)估套件,加速物聯(lián)網(wǎng)開發(fā)
近日,全球領(lǐng)先的Wi-Fi HaLow解決方案提供商摩爾斯微電子正式推出一款開創(chuàng)性的評(píng)估套件——MM6108-EKH05。這款完全整合的開發(fā)平臺(tái),旨在推動(dòng)各行業(yè)物聯(lián)網(wǎng)解決方案的快速發(fā)展
從Wi-Fi 4到Wi-Fi 7:網(wǎng)速飆升40倍的無(wú)線革命
1 Wi-Fi技術(shù)的快速發(fā)展 每一代新的Wi-Fi協(xié)議發(fā)布,都會(huì)帶來(lái)更高的無(wú)線速率。 ? 從Wi-Fi 4到Wi-Fi 7:無(wú)線網(wǎng)絡(luò)技術(shù)顯著

Wi-Fi 7有哪些底層技術(shù)優(yōu)勢(shì)
您在多個(gè)Wi-Fi行業(yè)活動(dòng)中代表LitePoint。Wi-Fi 7帶來(lái)了哪些新穎且有趣的特點(diǎn)?
Wi-Fi 7與Wi-Fi 6E有什么區(qū)別
也許很多人還在考慮是否要將使用的Wi-Fi設(shè)備升級(jí)到Wi-Fi 6或Wi-Fi 6E,而這些標(biāo)準(zhǔn)的繼任者卻已經(jīng)開始“登堂入室”了。Wi-Fi 7是新
如何記住ESP8266中的Wi-Fi憑據(jù)?
您好,我正在與ESP8266合作,在公司進(jìn)行一個(gè)項(xiàng)目。在成功智能配置后,我無(wú)法記住 Wi-Fi 憑據(jù)。ESP8266軟件版本如下:
在GMR
AT版本:1.2.0.0(Jul 1, 2016 20
發(fā)表于 07-15 07:07
為什么ESP8266沒有檢測(cè)到Wi-Fi的SSID?
你好,我的ESP8266沒有檢測(cè)到我家Wi-Fi的SSID。我嘗試打開我的 iPhone 熱點(diǎn),我可以正常查看和連接(我也成功連接到 MQTT)。相反,沒有辦法看到我家的Wi-Fi。
我有一
發(fā)表于 07-09 06:44
未來(lái)的Wi-Fi路由器
廠家加入開始?xì)r(jià),Wi-Fi FEM由于廠家眾多,價(jià)格一降再降,直接殺到成本價(jià)以下,DC-DC電源芯片也好不到哪里去,供應(yīng)商的上市年度報(bào)和季度報(bào)也是不堪入眼。 除了跟著主芯片從Wi-Fi4升級(jí)到
ESP32 D0WDQ6設(shè)計(jì)的板子,ADC2與Wi-Fi驅(qū)動(dòng)程序可以同時(shí)工作嗎?
硬件改版復(fù)雜一點(diǎn),所以請(qǐng)教下大家,可以操作下軟件(但是不關(guān)閉Wi-Fi),把ADC2用起來(lái)嗎,ADC2好幾個(gè)通道,Wi-Fi都使用到了嗎?煩
發(fā)表于 06-20 08:17
評(píng)論