旋轉(zhuǎn)編碼器是一種位置傳感器,可將旋鈕的角位置(旋轉(zhuǎn))轉(zhuǎn)換為用于確定旋鈕旋轉(zhuǎn)方向的輸出信號(hào)。
由于其堅(jiān)固性和良好的數(shù)字控制;它們被用于許多應(yīng)用中,包括機(jī)器人技術(shù),CNC機(jī)器和打印機(jī)。
旋轉(zhuǎn)編碼器有兩種類(lèi)型-絕對(duì)式和增量式。絕對(duì)編碼器為我們提供旋鈕的精確位置(以度為單位),而增量編碼器報(bào)告軸已移動(dòng)了多少增量。
編碼器內(nèi)部是一個(gè)槽形磁盤(pán),該磁盤(pán)連接到公共接地引腳C以及兩個(gè)接觸針A和B。旋轉(zhuǎn)旋鈕時(shí),A和B根據(jù)旋轉(zhuǎn)旋鈕的方向以特定順序與公共接地引腳C接觸。
當(dāng)它們接觸公共接地時(shí),它們會(huì)產(chǎn)生信號(hào)。當(dāng)一個(gè)引腳先于另一引腳接觸時(shí),這些信號(hào)就會(huì)彼此錯(cuò)開(kāi)90°。這稱(chēng)為正交編碼。

順時(shí)針旋轉(zhuǎn)旋鈕時(shí),首先連接A引腳,然后連接B引腳。逆時(shí)針旋轉(zhuǎn)旋鈕時(shí),首先連接B引腳,然后連接A引腳。
通過(guò)跟蹤每個(gè)引腳何時(shí)與地面連接或與地面斷開(kāi),我們可以使用這些信號(hào)變化來(lái)確定旋鈕的旋轉(zhuǎn)方向。您可以通過(guò)在A(yíng)更改狀態(tài)時(shí)觀(guān)察B的狀態(tài)來(lái)做到這一點(diǎn)。
我們搭建電路,如下:


1
載入方案
簡(jiǎn)介
我們使用的開(kāi)發(fā)板是 R128-Devkit,需要開(kāi)發(fā) C906 核心的應(yīng)用程序,所以載入方案選擇r128s2_module_c906。
?
$ source envsetup.sh $ lunch_rtos 1

?
2
GPIO驅(qū)動(dòng)
勾選
mrtos_menuconfig?找到下列驅(qū)動(dòng)
?
Drivers Options ?---> ? ?soc related device drivers ?---> ? ? ? ? ? ?GPIO devices ---> ? ? ? ? ? ? ? ?[*] enable GPIO driver ? ? ? ? ? ? ? ?[*] enbale GPIO hal APIs Test command

?
3
程序編寫(xiě)
簡(jiǎn)介
打開(kāi)你喜歡的編輯器,在以下目錄修改文件:
?
lichee/rtos/projects/r128s2/module_c906/src/main.c

?
4
頭文件
引入
?
#include?
5
使用GPIO
配置引腳
1、配置 GPIO 的上下拉狀態(tài)
使用?
hal_gpio_set_pull (gpio_pin_t pin, gpio_pull_status_t pull);來(lái)設(shè)置。這里我們?cè)O(shè)置 PA25 引腳為默認(rèn)上拉狀態(tài)。hal_gpio_set_pull(GPIOA(25), GPIO_PULL_UP);?
2、配置 GPIO 輸入輸出模式
使用?
hal_gpio_set_direction (gpio_pin_t pin, gpio_direction_t direction);?來(lái)設(shè)置 GPIO 的輸入輸出模式,這里配置為輸入模式。hal_gpio_set_direction(GPIOA(25), GPIO_DIRECTION_INPUT);?
3、配置 GPIO 的 MUX 功能
GPIO 通常有多種功能,需要配置 MUX 選擇需要的功能,使用?
hal_gpio_pinmux_set_function (gpio_pin_t pin, gpio_muxsel_t function_index);來(lái)設(shè)置 GPIO 的復(fù)用功能,這里配置為GPIO 輸入模式(GPIO_MUXSEL_IN)hal_gpio_pinmux_set_function(GPIOA(25), GPIO_MUXSEL_IN);?
4、獲取 GPIO 的電平
使用?
int hal_gpio_get_data (gpio_pin_t pin, gpio_data_t *data);來(lái)獲取 GPIO 的電平gpio_data_t gpio_data; hal_gpio_get_data(GPIOA(25), &gpio_data);?
5、申請(qǐng)配置中斷
使用
hal_gpio_to_irq方法來(lái)申請(qǐng)中斷號(hào)hal_gpio_irq_request綁定中斷服務(wù),啟用中斷hal_gpio_irq_enable這里配置一個(gè)// 存放中斷號(hào) uint32_t irq_clk; // 申請(qǐng)中斷號(hào) ret = hal_gpio_to_irq(ENC_CLK, &irq_clk); if (ret < 0){ ? ?printf("gpio to irq error, irq num:%d error num: %d ", irq_clk, ret); } // 綁定中斷處理函數(shù) ret = hal_gpio_irq_request(irq_clk, gpio_irq_encode, IRQ_TYPE_EDGE_BOTH, NULL); if (ret < 0){ ? ?printf("request irq error, irq num:%d error num: %d ", irq_clk, ret); } // 啟用中斷 ret = hal_gpio_irq_enable(irq_clk); if (ret < 0){ ? ?printf("request irq error, error num: %d ", ret); }?
6
完整實(shí)驗(yàn)代碼
及結(jié)果
?
#include#include #include #include #include "interrupt.h" #include #include #include #include #include #include "FreeRTOS.h" #include "task.h" #include "tinatest.h" extern int amp_init(void); // 定義旋轉(zhuǎn)編碼器的引腳 #define ENC_CLK GPIOA(24) #define ENC_DT GPIOA(25) #define ENC_SW GPIOA(29) // 相關(guān)全局變量存儲(chǔ) int encode_counter = 0; int encode_current_clk; int encode_lask_clk; int current_dir = 0; // 編碼器中斷處理函數(shù) static hal_irqreturn_t gpio_irq_encode(void *data) { ? ?// 獲取引腳的高低電平狀態(tài) ? ?gpio_data_t clk_value = GPIO_DATA_LOW; ? ?gpio_data_t dt_value = GPIO_DATA_LOW; ? ?hal_gpio_get_data(ENC_DT, &dt_value); ? ?hal_gpio_get_data(ENC_CLK, &clk_value); ? ?// 判斷當(dāng)前數(shù)據(jù)狀態(tài) ? ?encode_current_clk = clk_value; ? ?if (encode_current_clk != encode_lask_clk && encode_current_clk == 1){ ? ? ? ?// 判斷正反轉(zhuǎn) ? ? ? ?if (dt_value != encode_current_clk) { ? ? ? ? ? ?// 正轉(zhuǎn) ? ? ? ? ? ?encode_counter ++; ? ? ? ? ? ?current_dir = 1; ? ? ? ?} else { ? ? ? ? ? ?// 反轉(zhuǎn) ? ? ? ? ? ?encode_counter --; ? ? ? ? ? ?current_dir = -1; ? ? ? ?} ? ? ? ?printf("Direction = %d, Counter = %d ", current_dir, encode_counter); ? ?} ? ?// 刷新當(dāng)前狀態(tài) ? ?encode_lask_clk = encode_current_clk; ? ?return 0; } void cpu0_app_entry(void *param) { ? ?int ret = 0; ? ?// 初始化系統(tǒng)資源 ? ?amp_init(); ? ?// A24 -> CLK, A25 -> DT. A29 -> SW ? ?hal_gpio_set_pull(ENC_CLK, GPIO_PULL_DOWN_DISABLED); ? ?hal_gpio_set_direction(ENC_CLK, GPIO_DIRECTION_INPUT); ? ?hal_gpio_pinmux_set_function(ENC_CLK, GPIO_MUXSEL_IN); ? ?// 獲取初始編碼器 CLK 狀態(tài) ? ?gpio_data_t clk_data; ? ?hal_gpio_get_data(ENC_CLK, &clk_data); ? ?encode_lask_clk = clk_data; ? ?hal_gpio_set_pull(ENC_DT, GPIO_PULL_DOWN_DISABLED); ? ?hal_gpio_set_direction(ENC_DT, GPIO_DIRECTION_INPUT); ? ?hal_gpio_pinmux_set_function(ENC_DT, GPIO_MUXSEL_IN); ? ?// 存放 CLK,DT 中斷號(hào) ? ?uint32_t irq_clk, irq_dt; ? ?// 申請(qǐng) ENC_CLK 為中斷引腳,跳變觸發(fā) ? ?ret = hal_gpio_to_irq(ENC_CLK, &irq_clk); ? ?if (ret < 0){ ? ? ? ?printf("gpio to irq error, irq num:%d error num: %d ", irq_clk, ret); ? ?} ? ?// 綁定中斷處理函數(shù) ? ?ret = hal_gpio_irq_request(irq_clk, gpio_irq_encode, IRQ_TYPE_EDGE_BOTH, NULL); ? ?if (ret < 0){ ? ? ? ?printf("request irq error, irq num:%d error num: %d ", irq_clk, ret); ? ?} ? ?// 啟用中斷 ? ?ret = hal_gpio_irq_enable(irq_clk); ? ?if (ret < 0){ ? ? ? ?printf("request irq error, error num: %d ", ret); ? ?} ? ?// 申請(qǐng) ENC_DT 為中斷引腳,跳變觸發(fā) ? ?ret = hal_gpio_to_irq(ENC_DT, &irq_dt); ? ?if (ret < 0){ ? ? ? ?printf("gpio to irq error, irq num:%d error num: %d ", irq_dt, ret); ? ?} ? ?// 綁定中斷處理函數(shù) ? ?ret = hal_gpio_irq_request(irq_dt, gpio_irq_encode, IRQ_TYPE_EDGE_BOTH, NULL); ? ?if (ret < 0){ ? ? ? ?printf("request irq error, irq num:%d error num: %d ", irq_dt, ret); ? ?} ? ?// 啟用中斷 ? ?ret = hal_gpio_irq_enable(irq_dt); ? ?if (ret < 0){ ? ? ? ?printf("request irq error, error num: %d ", ret); ? ?} ? ?vTaskDelete(NULL); } 編輯:黃飛
?
電子發(fā)燒友App























評(píng)論