選擇編碼器接口模式的方法是:如果計數器隻在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 編碼器模式下的計數器操作執行個體
下圖為當IC1FP1極性反相時計數器的操作執行個體(CC1P=’1’,其他配置與上例相同)
圖92 IC1FP1反相的編碼器接口模式執行個體
當定時器配置成編碼器接口模式時,提供傳感器目前位置的資訊。使用第二個配置在捕獲模式
的定時器,可以測量兩個編碼器事件的間隔,獲得動态的資訊(速度,加速度,減速度)。訓示機
械零點的編碼器輸出可被用做此目的。根據兩個事件間的間隔,可以按照固定的時間讀出計數
器。如果可能的話,你可以把計數器的值鎖存到第三個輸入捕獲寄存器(捕獲信号必須是周期的
并且可以由另一個定時器産生);也可以通過一個由實時時鐘産生的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);
}
}