旋轉(zhuǎn)編碼器是一種位置傳感器,可將旋鈕的角位置(旋轉(zhuǎn))轉(zhuǎn)換為用于確定旋鈕旋轉(zhuǎn)方向的輸出信號。
由于其堅固性和良好的數(shù)字控制;它們被用于許多應(yīng)用中,包括機(jī)器人技術(shù),CNC機(jī)器和打印機(jī)。
旋轉(zhuǎn)編碼器有兩種類型-絕對式和增量式。絕對編碼器為我們提供旋鈕的精確位置(以度為單位),而增量編碼器報告軸已移動了多少增量。
編碼器內(nèi)部是一個槽形磁盤,該磁盤連接到公共接地引腳C以及兩個接觸針A和B。旋轉(zhuǎn)旋鈕時,A和B根據(jù)旋轉(zhuǎn)旋鈕的方向以特定順序與公共接地引腳C接觸。
當(dāng)它們接觸公共接地時,它們會產(chǎn)生信號。當(dāng)一個引腳先于另一引腳接觸時,這些信號就會彼此錯開90°。這稱為正交編碼。
順時針旋轉(zhuǎn)旋鈕時,首先連接A引腳,然后連接B引腳。逆時針旋轉(zhuǎn)旋鈕時,首先連接B引腳,然后連接A引腳。
通過跟蹤每個引腳何時與地面連接或與地面斷開,我們可以使用這些信號變化來確定旋鈕的旋轉(zhuǎn)方向。您可以通過在A更改狀態(tài)時觀察B的狀態(tài)來做到這一點(diǎn)。
我們搭建電路,如下:
1
載入方案
簡介
我們使用的開發(fā)板是 R128-Devkit,需要開發(fā) C906 核心的應(yīng)用程序,所以載入方案選擇r128s2_module_c906。
?
$ source envsetup.sh $ lunch_rtos 1
?
2
GPIO驅(qū)動
勾選
mrtos_menuconfig?找到下列驅(qū)動
?
Drivers Options ?---> ? ?soc related device drivers ?---> ? ? ? ? ? ?GPIO devices ---> ? ? ? ? ? ? ? ?[*] enable GPIO driver ? ? ? ? ? ? ? ?[*] enbale GPIO hal APIs Test command
?
3
程序編寫
簡介
打開你喜歡的編輯器,在以下目錄修改文件:
?
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);來設(shè)置。這里我們設(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);?來設(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);來設(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);來獲取 GPIO 的電平gpio_data_t gpio_data; hal_gpio_get_data(GPIOA(25), &gpio_data);?
5、申請配置中斷
使用
hal_gpio_to_irq方法來申請中斷號hal_gpio_irq_request綁定中斷服務(wù),啟用中斷hal_gpio_irq_enable這里配置一個// 存放中斷號 uint32_t irq_clk; // 申請中斷號 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)全局變量存儲 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 中斷號 ? ?uint32_t irq_clk, irq_dt; ? ?// 申請 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); ? ?} ? ?// 申請 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); } 編輯:黃飛
?
評論
查看更多