旋转编码器
旋轉編碼器
增量編碼器是一種將旋轉位移轉換為一連串數字脈沖信號的旋轉式傳感器。這些脈沖用來控制角位移。在Eltra編碼器中角位移的轉換采用了光電掃描原理。讀數系統以由交替的透光窗口和不透光窗口構成的徑向分度盤(碼盤)的旋轉為依據,同時被一個紅外光源垂直照射,光把碼盤的圖像投射到接收器表面上。接收器覆蓋著一層衍射光柵,它具有和碼盤相同的窗口寬度。接收器的工作是感受光盤轉動所產生的變化,然后將光變化轉換成相應的電變化。再使低電平信號上升到較高電平,并產生沒有任何干擾的方形脈沖,這就必須用電子電路來處理。讀數系統通常采用差分方式,即將兩個波形一樣但相位差為180°的不同信號進行比較,以便提高輸出信號的質量和穩定性。讀數是再兩個信號的差別基礎上形成的,從而消除了干擾。
增量編碼器給出兩相方波,它們的相位差90°,通常稱為A通道和B通道。其中一個通道給出與轉速相關的信息,與此同時,通過兩個通道信號進行順序對比,得到旋轉方向的信息。還有一個特殊信號稱為Z或零通道,該通道給出編碼器的絕對零位,此信號是一個方波與A通道方波的中心線重合。現在實現檢測這個增量編碼器正轉還是反轉 。
編碼器時序
實物圖如圖
程序實現(STM32F103):
實現思路:使用IO口檢測K2何時變為電平,后立即檢測K3電平,K3若為低電平則為方向1,若為高電平,則為方向二。
連接關系
- VCC~3.3V
- GND~GND
- SW~PA7
- DT~PA6
- C LK~PB2
encoder.h
#ifndef __ENCODER_H #define __ENCODER_H #include "sys.h" #include "delay.h"#define ENCODER_PORT_A GPIOA //定義IO接口組 #define ENCODER_L GPIO_Pin_6 //定義IO接口,DT,旋鈕左轉 #define ENCODER_D GPIO_Pin_7 //定義IO接口,SW;旋鈕按下#define ENCODER_PORT_B GPIOB //定義IO接口組 #define ENCODER_R GPIO_Pin_2 //定義IO接口,CLK,旋鈕右轉void ENCODER_Init(void);//初始化 u8 ENCODER_READ(void);#endifencoder.c
#include "encoder.h"u8 KUP;//旋鈕鎖死標志(1為鎖死) u16 cou;void ENCODER_Init(void){ //接口初始化GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO的初始化枚舉結構 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = ENCODER_L | ENCODER_D; //選擇端口號 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇IO接口工作方式 //上拉電阻 GPIO_Init(ENCODER_PORT_A,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ENCODER_R; //選擇端口號 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇IO接口工作方式 //上拉電阻 GPIO_Init(ENCODER_PORT_B,&GPIO_InitStructure); }u8 ENCODER_READ(void){ //接口初始化u8 a;//存放按鍵的值u8 kt;a=0;if(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L))KUP=0; //判斷旋鈕是否解除鎖死if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&KUP==0){ //判斷是否旋轉旋鈕,同時判斷是否有旋鈕鎖死delay_us(100);kt=GPIO_ReadInputDataBit(ENCODER_PORT_B,ENCODER_R); //把旋鈕另一端電平狀態記錄delay_ms(3); //延時if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)){ //去抖if(kt==0){ //用另一端判斷左或右旋轉a=1;//右轉}else{a=2;//左轉}cou=0; //初始鎖死判斷計數器while(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&cou<60000){ //等待放開旋鈕,同時累加判斷鎖死cou++;KUP=1;delay_us(20); //}}}if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)&&KUP==0){ //判斷旋鈕是否按下 delay_ms(20);if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)){ //去抖動a=3;//在按鍵按下時加上按鍵的狀態值//while(ENCODER_D==0); 等等旋鈕放開}}return a; }初始化,僅是對IO管腳初始化,值得關注的是全局變量KUP——旋鈕鎖死標志,該變量的設置是由于旋轉編碼器為機械結構,有可能旋鈕K2由于某種卡死在低電平。造成程序崩潰,為解決這種問題,故有以下語句
while(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&cou<60000){ //等待放開旋鈕,同時累加判斷鎖死cou++;KUP=1;delay_us(20); //}檢測是否松開旋鈕一段時間,若長時間不松開旋鈕,則鎖死旋鈕。使旋鈕的值不發生變化,放當松開旋鈕時,對該變量解鎖。
if(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L))KUP=0; //判斷旋鈕是否解除鎖死針對其他語句結構,仔細一看就好了,很容易理解的,這樣就完成了對編碼器旋轉方向以及旋轉角度的檢測,接下來就可以在主程序中調用他吧。
#include "stm32f10x.h" //STM32頭文件 #include "sys.h" #include "delay.h" #include "i2c.h" #include "oled0561.h" #include "encoder.h"int main (void){//主程序u8 a=0,b=0,c=0x01;RCC_Configuration(); //系統時鐘初始化 RTC_Config(); //RTC初始化ENCODER_Init(); //旋轉編碼器初始化I2C_Configuration(); // IIC 初始化OLED0561_Init(); // oled 初始化OLED_DISPLAY_LIT(100);//亮度設置OLED_DISPLAY_8x16(6,8*8,a/10+0x30);//顯示OLED_DISPLAY_8x16(6,9*8,a%10+0x30);//顯示while(1){b=ENCODER_READ(); //讀出旋轉編碼器值 if(b==1){a++;if(a>99)a=0;} //分析按鍵值,并加減計數器值。if(b==2){if(a==0)a=100;a--;}if(b==3)a=0;if(b!=0){ //如果有旋轉器的操作OLED_DISPLAY_8x16(6,8*8,a/10+0x30);//顯示OLED_DISPLAY_8x16(6,9*8,a%10+0x30);//顯示}} }總結
- 上一篇: 树莓派4B之声音传感器模块(python
- 下一篇: 移位寄存器-Verilog