天天看點

stm32碼盤傳感器_stm32的編碼器模式

選擇編碼器接口模式的方法是:如果計數器隻在TI2的邊沿計數,則置TIMx_SMCR寄存器中的

SMS=001;如果隻在TI1邊沿計數,則置SMS=010;如果計數器同時在TI1和TI2邊沿計數,則

置SMS=011

TI1FP1和TI2FP2

是TI1和TI2在通過輸入濾波器和極性控制後的信号;如果沒有濾波和變相,則TI1FP1=TI1,

TI2FP2=TI2。根據兩個輸入信号的跳變順序,産生了計數脈沖和方向信号。依據兩個輸入信号

的跳變順序,計數器向上或向下計數,同時硬體對TIMx_CR1寄存器的DIR位進行相應的設定。

不管計數器是依靠TI1計數、依靠TI2計數或者同時依靠TI1和TI2計數,在任一輸入端(TI1或者

TI2)的跳變都會重新計算DIR位。

編碼器接口模式基本上相當于使用了一個帶有方向選擇的外部時鐘。這意味着計數器隻在0到

TIMx_ARR寄存器的自動裝載值之間連續計數(根據方向,或是0到ARR計數,或是ARR到0計

數)。是以在開始計數之前必須配置TIMx_ARR;同樣,捕獲器、比較器、預分頻器、重複計數

器、觸發輸出特性等仍工作如常。編碼器模式和外部時鐘模式2不相容,是以不能同時操作。

在這個模式下,計數器依照增量編碼器的速度和方向被自動的修改,是以計數器的内容始終指

示着編碼器的位置。計數方向與相連的傳感器旋轉的方向對應。下表列出了所有可能的組合,

假設TI1和TI2不同時變換

表73 計數方向與編碼器信号的關系

226/754相對信号的電平

(TI1FP1對應TI2,

TI2FP2對應TI1)TI1FP1信号TI2FP2信号有效邊沿

上升下降上升下降

高向下計數向上計數不計數不計數僅在TI1計數

低向上計數向下計數不計數不計數

高不計數不計數向上計數向下計數僅在TI2計數

低不計數不計數向下計數向上計數

高向下計數向上計數向上計數向下計數在TI1和TI2上計數

低向上計數向下計數向下計數向上計數

一個外部的增量編碼器可以直接與MCU連接配接而不需要外部接口邏輯。但是,一般會使用比較器

将編碼器的差動輸出轉換到數字信号,這大大增加了抗噪聲幹擾能力。編碼器輸出的第三個信

号表示機械零點,可以把它連接配接到一個外部中斷輸入并觸發一個計數器複位。

下圖是一個計數器操作的執行個體,顯示了計數信号的産生和方向控制。它還顯示了當選擇了雙邊

沿時,輸入抖動是如何被抑制的;抖動可能會在傳感器的位置靠近一個轉換點時産生。在這個

例子中,我們假定配置如下:

● CC1S=’01’ (TIMx_CCMR1寄存器, IC1FP1映射到TI1)

● CC2S=’01’ (TIMx_CCMR2寄存器, IC2FP2映射到TI2)

● CC1P=’0’ (TIMx_CCER寄存器, IC1FP1不反相, IC1FP1=TI1)

● CC2P=’0’ (TIMx_CCER寄存器, IC2FP2不反相, IC2FP2=TI2)

● SMS=’011’ (TIMx_SMCR寄存器,所有的輸入均在上升沿和下降沿有效).

● CEN=’1’ (TIMx_CR1寄存器,計數器使能)

圖91 編碼器模式下的計數器操作執行個體

stm32碼盤傳感器_stm32的編碼器模式

下圖為當IC1FP1極性反相時計數器的操作執行個體(CC1P=’1’,其他配置與上例相同)

圖92 IC1FP1反相的編碼器接口模式執行個體

stm32碼盤傳感器_stm32的編碼器模式

當定時器配置成編碼器接口模式時,提供傳感器目前位置的資訊。使用第二個配置在捕獲模式

的定時器,可以測量兩個編碼器事件的間隔,獲得動态的資訊(速度,加速度,減速度)。訓示機

械零點的編碼器輸出可被用做此目的。根據兩個事件間的間隔,可以按照固定的時間讀出計數

器。如果可能的話,你可以把計數器的值鎖存到第三個輸入捕獲寄存器(捕獲信号必須是周期的

并且可以由另一個定時器産生);也可以通過一個由實時時鐘産生的DMA請求來讀取它的值。

eg:

編碼器A相接PB6,B相接PB7

#define ENCODENU 65536

void time4IOInit()

{

GPIO_InitTypeDef        GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //①使能 GPIOB 時鐘

GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6 | GPIO_Pin_7; //PB6 7 設定

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入

GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void time4CountInit()

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   //使能 TIM4 時鐘

TIM4->ARR = ENCODENU-1;                                                                    //設定計數器重裝值(因為沒有使用更新中斷是以将計數器設最大值,保證1s延時不會溢出)

TIM4->PSC  = 0;                                                                                          //預分頻器

TIM4->CR1 &=~(3<<8);                                                                              // 選擇時鐘分頻:不分頻

TIM4->CR1 &=~(3<<5);                                                                              //邊沿對齊(根據dir位向上或者向下計數)

//定時器4配置成編碼器模式,雙邊沿觸發

TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);

TIM_SetCounter(TIM4, 0);                                                                       //計數器清零

}

void encoderConfig()

{

time4IOInit();

time4CountInit();

TIM_Cmd(TIM4, ENABLE);  //計數器使能,開始工作

}

void main ()

{

int dir=0;

u16 nu=0;

encoderConfig();

for (;;)

{

dir=(TIM4->CR1 & 0x0010)>4;                                                     //取方向标志位

if(dir > 0){                                                                                         //向下計數

nu = (ENCODENU-TIM_GetCounter(TIM4))/4;                  //除以4是因為一對脈沖計數器計數4次

FG_Print("down ; TIM_GetCounter=%d  \r\n",nu*60/1000);//(*60是因為延時1s轉換成一分鐘,/1000是因為編碼器轉一圈是1000個脈沖)

}else{                                                                                              //向上計數

nu = TIM_GetCounter(TIM4)/4;

FG_Print("up ; TIM_GetCounter=%d  \r\n",nu*60/1000);

}

TIM_SetCounter(TIM4, 0);

osDelay(1000);

}

}