加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 01模塊來(lái)源
    • 02 規(guī)格參數(shù)
    • 03移植過(guò)程
    • 04移植驗(yàn)證
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】EC11旋轉(zhuǎn)編碼器

08/29 08:26
764
閱讀需 23 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

旋轉(zhuǎn)編碼器是一種將旋轉(zhuǎn)位移轉(zhuǎn)換為一連串?dāng)?shù)字脈沖信號(hào)的旋轉(zhuǎn)式傳感器。這些脈沖用來(lái)控制角位移。讀數(shù)系統(tǒng)通常采用差分方式,即將兩個(gè)波形一樣但相位差為180°的不同信號(hào)進(jìn)行比較,以便提高輸出信號(hào)的質(zhì)量和穩(wěn)定性。讀數(shù)是在兩個(gè)信號(hào)的差別基礎(chǔ)上形成的,從而消除了干擾。

01模塊來(lái)源

資料下載鏈接:https://pan.baidu.com/s/18pp1KaT2V_llizWvdIXtKA?pwd=8889

資料提取碼:8889

02 規(guī)格參數(shù)

模塊的廠家資料下載請(qǐng)查看百度網(wǎng)盤鏈接

工作電壓:5V

工作電流:1MA

模塊尺寸:18 x 25 mm

旋轉(zhuǎn)角度: 360度

通信協(xié)議:相位差

管腳數(shù)量:5 Pin(2.54mm間距排針

03移植過(guò)程

我們的目標(biāo)是在立創(chuàng)·CW32F030C8T6開(kāi)發(fā)板上能夠判斷旋轉(zhuǎn)方向、旋轉(zhuǎn)次數(shù)和是否按下的功能。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn),再移植至我們的工程。

3.1查看資料

旋轉(zhuǎn)編碼器是通過(guò)兩個(gè)引腳的相位差,實(shí)現(xiàn)的旋轉(zhuǎn)方向判斷(以后的CLK引腳統(tǒng)一稱呼為A相,DT引腳為B相)

當(dāng)是順時(shí)針旋轉(zhuǎn)時(shí),A相超前B相90度,即A相為下降沿時(shí),B相為低電平;A相為上升沿時(shí),B相為高電平。

當(dāng)是逆時(shí)針旋轉(zhuǎn)時(shí),B相超前A相90度,即A相為下降沿時(shí),B相為高電平;A相為上升沿時(shí),B相為低電平。

而EC11按旋轉(zhuǎn)的輸出動(dòng)作可以分為兩種。

一種是轉(zhuǎn)兩格,A、B端輸出一個(gè)完整脈沖(轉(zhuǎn)一格就只是由低電平->高電平或由高電平->低電平);

一種就是轉(zhuǎn)一格,A、B對(duì)C端輸出一個(gè)完整脈沖。


轉(zhuǎn)一格半個(gè)脈沖


轉(zhuǎn)一格完整脈沖

因此我們只需檢測(cè)A相或者B相有發(fā)生高低電平跳變時(shí),就判斷另一相狀態(tài),來(lái)決定旋轉(zhuǎn)方向。根據(jù)以下真值表,可以發(fā)現(xiàn):

當(dāng)兩相同時(shí)為上升沿或者同時(shí)為下降沿時(shí),則為順時(shí)針;

當(dāng)兩相不同時(shí)為上升沿或者不同時(shí)為下降沿時(shí),則為逆時(shí)針;

下B相 右A相 上升沿 下降沿
上升沿 順時(shí)針 逆時(shí)針
下降沿 逆時(shí)針 順時(shí)針

旋轉(zhuǎn)編碼器是機(jī)械結(jié)構(gòu)的,是機(jī)械結(jié)構(gòu)就避免不了在旋轉(zhuǎn)或者按下時(shí)有抖動(dòng),這里采用定時(shí)器每隔10ms掃描一次編碼器是否有動(dòng)作,實(shí)現(xiàn)10ms內(nèi)的消抖。

在中斷服務(wù)函數(shù)中,根據(jù)真值表確定旋轉(zhuǎn)的方向。

3.2引腳選擇

該模塊有5個(gè)引腳,具體引腳連接見(jiàn) 表 各引腳連接。

3.3移植至工程

打開(kāi)自己的工程。(這里工程參考見(jiàn)入門手冊(cè)工程模板)

移植步驟中的導(dǎo)入.c和.h文件與第二章的第1小節(jié)【DHT11溫濕度傳感器】相同,只是將.c和.h文件更改為ec11.c與ec11.h。這里不再過(guò)多講述,移植完成后面修改相關(guān)代碼。

在文件ec11.c中,編寫如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-19     LCKFB-LP    first version */
#include "ec11.h"#include "stdio.h"

/****************************************************************** * 函 數(shù) 名 稱:Encoder_GPIO_Init * 函 數(shù) 說(shuō) 明:旋轉(zhuǎn)編碼器引腳初始化 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:使用定時(shí)器每10Ms掃描一次是否有旋轉(zhuǎn),即通過(guò)定時(shí)器進(jìn)行消抖******************************************************************/void Encoder_GPIO_Init(void){    GPIO_InitTypeDef GPIO_InitStruct;                     // GPIO初始化結(jié)構(gòu)體    BTIM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct;     // 定時(shí)器初始化結(jié)構(gòu)體
    RCC_GPIO_ENABLE();        // 使能GPIO時(shí)鐘    BTIM_RCC_ENABLE();        // 使能BTIM時(shí)鐘
    // 禁止中斷,以安全地配置NVIC    __disable_irq();
    // 開(kāi)啟BTIM1中斷,并關(guān)聯(lián)到NVIC    NVIC_EnableIRQ(BSP_TIMER_IRQ);
    // 允許中斷,恢復(fù)中斷狀態(tài)    __enable_irq();
    GPIO_InitStruct.Pins =  GPIO_ENCODER_SW|          // GPIO引腳                            GPIO_ENCODER_LCK|                            GPIO_ENCODER_DT;    GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP;    // 上拉輸入    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;          // 輸出速度高    GPIO_Init(PORT_GPIO, &GPIO_InitStruct);           // 初始化

    // 配置定時(shí)器模式、周期和預(yù)分頻器    BTIM_TimeBaseInitStruct.BTIM_Mode = BTIM_Mode_TIMER;       // 設(shè)置為定時(shí)器模式    BTIM_TimeBaseInitStruct.BTIM_Period = 625 - 1;             // 設(shè)置周期,使得定時(shí)器每10ms產(chǎn)生一次溢出中斷    BTIM_TimeBaseInitStruct.BTIM_Prescaler = BTIM_PRS_DIV1024; // 預(yù)分頻器設(shè)置為1024,以降低時(shí)鐘頻
    // 使用上述配置初始化定時(shí)器BTIM1    BTIM_TimeBaseInit(BSP_TIMER, &BTIM_TimeBaseInitStruct);
    // 使能BTIM1的溢出中斷    BTIM_ITConfig(BSP_TIMER, BTIM_IT_OV, ENABLE);
    // 啟動(dòng)定時(shí)器BTIM1    BTIM_Cmd(BSP_TIMER, ENABLE);}

/****************************************************************** * 函 數(shù) 名 稱:Encoder_Scanf * 函 數(shù) 說(shuō) 明:判斷旋轉(zhuǎn)編碼器是否有往哪一個(gè)方向旋轉(zhuǎn) * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:1=正轉(zhuǎn) 2=反轉(zhuǎn) * 作       者:LC * 備       注:哪一邊正轉(zhuǎn)哪一邊反轉(zhuǎn)不需要太在意,你說(shuō)的算******************************************************************/char Encoder_Scanf(void){    static GPIO_PinState EC11_CLK_Last= GPIO_Pin_RESET; //EC11的LCK引腳上一次的狀態(tài)(A相)    static GPIO_PinState EC11_DT_Last = GPIO_Pin_RESET; //EC11的DT引腳上一次的狀態(tài)(B相)    char ScanResult = 0;    //當(dāng)A發(fā)生跳變時(shí)采集B當(dāng)前的狀態(tài),并將B與上一次的狀態(tài)進(jìn)行對(duì)比。    if(GET_CLK_STATE !=EC11_CLK_Last)    {           //若A 0->1 時(shí),B 1->0 正轉(zhuǎn);若A 1->0 時(shí),B 0->1 正轉(zhuǎn);                //若A 0->1 時(shí),B 0->1 反轉(zhuǎn);若A 1->0 時(shí),B 1->0 反轉(zhuǎn)        if(GET_CLK_STATE == 1)     //EC11_A和上一次狀態(tài)相比,為上升沿        {            //EC11_B和上一次狀態(tài)相比,為下降沿            if((EC11_DT_Last == 1)&&(GET_DT_STATE == 0))                ScanResult = 1;  //正轉(zhuǎn)             //EC11_B和上一次狀態(tài)相比,為上升沿            if((EC11_DT_Last == 0)&&(GET_DT_STATE == 1))                ScanResult = 2; //反轉(zhuǎn)
            //>>>>>>>>>>>>>>>>下面為正轉(zhuǎn)一次再反轉(zhuǎn)或反轉(zhuǎn)一次再正轉(zhuǎn)處理<<<<<<<<<<<<<<<<//            //A上升沿時(shí),采集的B不變且為0            if((EC11_DT_Last == GET_DT_STATE)&&(GET_DT_STATE == 0))                ScanResult = 1;                                 //正轉(zhuǎn)             //A上升沿時(shí),采集的B不變且為1            if((EC11_DT_Last == GET_DT_STATE)&&(GET_DT_STATE == 1))                ScanResult = 2;                                //反轉(zhuǎn)        }        else  //EC11_A和上一次狀態(tài)相比,為下降沿        {            //EC11_B和上一次狀態(tài)相比,為下降沿            if((EC11_DT_Last == 1)&&(GET_DT_STATE == 0))                ScanResult = 2;                        //反轉(zhuǎn)             //EC11_B和上一次狀態(tài)相比,為上升沿            if((EC11_DT_Last == 0)&&(GET_DT_STATE == 1))                ScanResult = 1;                         //正轉(zhuǎn)
            //>>>>>>>>>>>>>>>>下面為正轉(zhuǎn)一次再反轉(zhuǎn)或反轉(zhuǎn)一次再正轉(zhuǎn)處理<<<<<<<<<<<<<<<<//            //A上升沿時(shí),采集的B不變且為0            if((EC11_DT_Last == GET_DT_STATE)&&(GET_DT_STATE == 0))                ScanResult = 2;                                //反轉(zhuǎn)            //A上升沿時(shí),采集的B不變且為1            if((EC11_DT_Last == GET_DT_STATE)&&(GET_DT_STATE == 1))                ScanResult = 1;                                 //正轉(zhuǎn)        }        EC11_CLK_Last = GET_CLK_STATE;   //更新編碼器上一個(gè)狀態(tài)暫存變量        EC11_DT_Last = GET_DT_STATE;     //更新編碼器上一個(gè)狀態(tài)暫存變量        return ScanResult;               //返回值的取值:   0:無(wú)動(dòng)作; 1:正轉(zhuǎn);  2:反轉(zhuǎn);    }    return 0;}


/****************************************************************** * 函 數(shù) 名 稱:Encoder_Sw_Down * 函 數(shù) 說(shuō) 明:判斷編碼器是否被按下 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:0=沒(méi)有被按下  1=被按下 * 作       者:LC * 備       注:請(qǐng)注意消抖******************************************************************/unsigned char Encoder_Sw_Down(void){    //沒(méi)有按下    if( GET_SW_STATE == GPIO_Pin_SET )    {        delay_ms(100);//消抖        return 0;    }    else//按下    {        delay_ms(100);//消抖//        printf("downrn");        return 1;    }}
/****************************************************************** * 函 數(shù) 名 稱:Encoder_Rotation_left * 函 數(shù) 說(shuō) 明:左旋轉(zhuǎn)服務(wù)函數(shù)。當(dāng)編碼器左轉(zhuǎn)時(shí),需要執(zhí)行的操作 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:向左旋轉(zhuǎn)次數(shù) * 作       者:LC * 備       注:無(wú)******************************************************************/int Encoder_Rotation_left(void){    static int left_num = 0;//左轉(zhuǎn)次數(shù)    left_num++;    /*  你的代碼寫在此處  */    printf("left num = %drn",left_num);
    /*  你的代碼寫在此處  */    return left_num;}
/****************************************************************** * 函 數(shù) 名 稱:Encoder_Rotation_left * 函 數(shù) 說(shuō) 明:右旋轉(zhuǎn)服務(wù)函數(shù)。當(dāng)編碼器右轉(zhuǎn)時(shí),需要執(zhí)行的操作 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:向右旋轉(zhuǎn)次數(shù) * 作       者:LC * 備       注:無(wú)******************************************************************/int Encoder_Rotation_right(void){    static int right_num = 0;//右轉(zhuǎn)次數(shù)    right_num++;    /*  你的代碼寫在此處  */
    printf("right num = %drn",right_num);    /*  你的代碼寫在此處  */
    return right_num;}

/************************************************函數(shù)名稱 : BSP_TIMER_IRQHandler功    能 : 基本定時(shí)器中斷服務(wù)函數(shù)參    數(shù) : 無(wú)返 回 值 : 無(wú)作    者 : LC*************************************************/void BSP_TIMER_IRQHANDLER(void){        static char dat = 0;        if(BTIM_GetITStatus(BSP_TIMER, BTIM_IT_OV) == SET)        {                dat = Encoder_Scanf();//掃描編碼器是否扭動(dòng)                if( dat != 0 )//如果有轉(zhuǎn)動(dòng)                {                        if( dat == 2 )                        {                                Encoder_Rotation_left();                        }                        else                        {                                Encoder_Rotation_right();                        }
                }        }        BTIM_ClearITPendingBit(BSP_TIMER, BTIM_IT_OV);}

 

在文件ec11.h中,編寫如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-19     LCKFB-LP    first version */#ifndef _BSP_ENCODER_H_#define _BSP_ENCODER_H_
#include "board.h"
#define RCC_GPIO_ENABLE()   __RCC_GPIOA_CLK_ENABLE()
#define PORT_GPIO           CW_GPIOA
//SW引腳#define GPIO_ENCODER_SW     GPIO_PIN_7
//CLK引腳#define GPIO_ENCODER_LCK    GPIO_PIN_6
//DT引腳#define GPIO_ENCODER_DT     GPIO_PIN_4
//獲取CLK引腳的狀態(tài)#define GET_CLK_STATE   GPIO_ReadPin(PORT_GPIO, GPIO_ENCODER_LCK)//獲取DT引腳的狀態(tài)#define GET_DT_STATE    GPIO_ReadPin(PORT_GPIO, GPIO_ENCODER_DT)//獲取SW引腳的狀態(tài)#define GET_SW_STATE    GPIO_ReadPin(PORT_GPIO, GPIO_ENCODER_SW)
//定時(shí)器掃描#define BTIM_RCC_ENABLE()            __RCC_BTIM_CLK_ENABLE() // 使能定時(shí)器時(shí)鐘#define BSP_TIMER                    CW_BTIM1                // 定時(shí)器#define BSP_TIMER_IRQ                BTIM1_IRQn              // 定時(shí)器中斷#define BSP_TIMER_IRQHANDLER         BTIM1_IRQHandler        // 定時(shí)器中斷服務(wù)函數(shù)

void Encoder_GPIO_Init(void);//旋轉(zhuǎn)編碼器初始化unsigned char Encoder_Sw_Down(void);//編碼器是否按下int Encoder_Rotation_left(void);//左轉(zhuǎn)服務(wù)函數(shù)int Encoder_Rotation_right(void);//右轉(zhuǎn)服務(wù)函數(shù)

#endif

04移植驗(yàn)證

在自己工程中的main主函數(shù)中,編寫如下。

/* * Change Logs: * Date           Author       Notes * 2024-06-19     LCKFB-LP    first version */#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "ec11.h"
int32_t main(void){    board_init();        // 開(kāi)發(fā)板初始化
    uart1_init(115200);  // 串口1波特率115200
    Encoder_GPIO_Init();    printf("encoder demo startrn");    while(1)    {        if( Encoder_Sw_Down() == 1 )//旋轉(zhuǎn)編碼器被按下        {            printf("Encoder downrn");        }    }}

移植現(xiàn)象:向右旋轉(zhuǎn)10次,向左旋轉(zhuǎn)10次,按下一次。

模塊移植成功案例代碼:

鏈接:https://pan.baidu.com/s/18_4-IfR_pzyy1QvyQE7XkQ?pwd=LCKF

提取碼:LCKF

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
12110192 1 Delphi Automotive LLP Combination Line Connector
暫無(wú)數(shù)據(jù) 查看
770854-1 1 TE Connectivity CONTACT, AMPSEAL SN/LP

ECAD模型

下載ECAD模型
$0.17 查看
LQW18AN33NG00D 1 Murata Manufacturing Co Ltd General Purpose Inductor, 0.033uH, 2%, 1 Element, Air-Core, SMD, 0603, CHIP, 0603

ECAD模型

下載ECAD模型
$0.15 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

以開(kāi)放、共享、互助為理念,致力于構(gòu)建武漢芯源半導(dǎo)體CW32系列MCU生態(tài)社區(qū)。無(wú)論是嵌入式MCU小自還是想要攻破技術(shù)難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營(yíng)養(yǎng)、共同成長(zhǎng)。

B站