• 正文
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

RVMCU課堂「17」: 手把手教你玩轉(zhuǎn)RVSTAR—正交編碼器接口篇

2021/05/31
202
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

上期內(nèi)容我們介紹了定時器PWM輸出功能,本期內(nèi)容來介紹一下定時器的正交譯碼器功能(編碼器接口)。正交譯碼器是和正交編碼器外設(shè)配合使用的,可對編碼器輸入的脈沖進(jìn)行計(jì)數(shù)進(jìn)而實(shí)現(xiàn)速度測量,本期內(nèi)容我們通過一個使用旋轉(zhuǎn)編碼器的計(jì)數(shù)小實(shí)驗(yàn),來初步了解它的應(yīng)用方法。

系統(tǒng)環(huán)境

Windows 10-64bit

軟件平臺

NucleiStudio IDE 202102版

PlatformIO IDE

硬件需求

RV-STAR開發(fā)板

旋轉(zhuǎn)編碼器

正交編碼器

正交編碼器(Quadrature Encoder)是一種用于測量旋轉(zhuǎn)速度和方向的傳感器。常見的正交編碼器有兩個輸出信號:A信道和B信道。每個信道可以對運(yùn)動進(jìn)行測量并產(chǎn)生數(shù)字脈沖,這兩個脈沖的相位相差90度(因此稱為“正交”),這使得你可以根據(jù)它們判斷運(yùn)動的方向,通過積分(累加)運(yùn)算后,還可以用來測算距離。

上圖中,A和B分別連接到兩個傳感器單元上,黑白相間的圓環(huán)稱之為「柵格」。傳感器單元和柵格的實(shí)現(xiàn)方式有很多種,包括「反射式傳感器+反光率不同的柵格」「對射式傳感器+鏤空光柵」「霍爾傳感器+磁極圓環(huán)」「觸點(diǎn)+導(dǎo)軌」等。

本次實(shí)驗(yàn)中,我們使用的是下圖所示的市面上常見的旋轉(zhuǎn)編碼器(數(shù)字電位器):

GD32VF103的正交譯碼器

正交譯碼器功能使用TIMERx_CH0和TIMERx_CH1引腳生成的CI0和CI1正交信號各自相互作用產(chǎn)生計(jì)數(shù)值。通過設(shè)置SMC=0x01、0x02或0x03來選擇是僅由CI0、僅由CI1、或者由CI0和CI1來決定定時器的計(jì)數(shù)方向。在每個方向選擇源的電平改變期間,DIR位是由硬件自動改變的。計(jì)數(shù)器計(jì)數(shù)方向改變的機(jī)制如下方的圖表所示。

正交譯碼器可以當(dāng)作一個帶有方向選擇的外部時鐘,這意味著計(jì)數(shù)器會在0和自動加載值之間連續(xù)地計(jì)數(shù)。因此,用戶必須在計(jì)數(shù)器開始計(jì)數(shù)前配置TIMERx_CAR寄存器

實(shí)驗(yàn)部分

首先需要參照如下的示意圖,對RV-STAR開發(fā)板和旋轉(zhuǎn)編碼器進(jìn)行連線:

然后在集成開發(fā)環(huán)境中創(chuàng)建一個新工程,開始編寫代碼。

首先需要對定時器的編碼器接口進(jìn)行配置,我們使用的是TIMER2的編碼器接口,對應(yīng)的是PA6和PA7引腳,首先要使能它們的外設(shè)時鐘和復(fù)用時鐘,然后配置為浮空輸入模式。

接著需要創(chuàng)建定時器初始化參數(shù)結(jié)構(gòu)體,對定時器的功能進(jìn)行配置,其中需要注意的是要將結(jié)構(gòu)體參數(shù)的預(yù)分頻系數(shù)設(shè)為0,周期設(shè)為10000(即定時器的自動加載值,也可以設(shè)為其他值),然后需要將定時器的模式設(shè)置為TIMER_ENCODER_MODE2(編碼器模式,使用CI0和CI1計(jì)數(shù)),然后將定時器的計(jì)數(shù)值配置為5000(這樣讀取定時器計(jì)數(shù)的初值就是5000),最后使能TIMER2。

相關(guān)代碼實(shí)現(xiàn)如下:


 

void encoder_init()
{
    /* TIMER2_CH0 - PA6, TIMER2_CH1 - PA7 */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);

    rcu_periph_clock_enable(RCU_TIMER2);
    timer_deinit(TIMER2);

    /* initialize TIMER init parameter struct */
    timer_parameter_struct timer_initpara;
    timer_struct_para_init(&timer_initpara);
    /* TIMER2 configuration */
    timer_initpara.prescaler = 0;
    timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection = TIMER_COUNTER_UP;
    timer_initpara.period = 10000; /* set auto-reload value */
    timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
    timer_init(TIMER2, &timer_initpara);

    /* select the encoder mode */
    timer_slave_mode_select(TIMER2, TIMER_ENCODER_MODE2);
    timer_counter_value_config(TIMER2, 5000); /* config the initial value */

    timer_enable(TIMER2);
}

本次實(shí)驗(yàn),我們通過串口的打印輸出來查看編碼器的計(jì)數(shù)值,因此在主程序中需要對串口進(jìn)行初始化,然后在循環(huán)體中,每次讀取依次定時器的計(jì)數(shù)值,再打印輸出到串口。


 

int main()
{
    encoder_init();
    gd_com_init(GD32_COM0);

    int counter = 0;
    while (1) {
        counter = timer_counter_read(TIMER2);
        printf("Counter: %dn", counter);

        delay_1ms(500);
    }
}

代碼編寫完成后,進(jìn)行編譯和上傳,然后打開串口終端(波特率115200),可以查看到在串口終端中輸出定時器的初值為5000:

然后順時針旋轉(zhuǎn)編碼器的旋鈕,觀察到計(jì)數(shù)值增加,并且每轉(zhuǎn)動一個單位計(jì)數(shù)值增加4,符合芯片數(shù)據(jù)手冊中的功能描述:

逆時針旋轉(zhuǎn),計(jì)數(shù)值減少:

“RVMCU課堂”專欄已在社區(qū)開通如需獲取實(shí)驗(yàn)源碼或有實(shí)驗(yàn)相關(guān)問題掃碼進(jìn)入即可

更多實(shí)驗(yàn)例程

盡在RVMCU社區(qū)

www.rvmcu.com

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄