五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

STM32定時器配置為編碼器模式

2020-06-02 12:47 作者:老-_-白  | 我要投稿

?一、編碼器原理

如果兩個信號相位差為90度,則這兩個信號稱為正交。由于兩個信號相差90度,因此可以根據(jù)兩個信號哪個先哪個后來判斷方向、根據(jù)每個信號脈沖數(shù)量的多少及整個編碼輪的周長就可以算出當前行走的距離、如果再加上定時器的話還可以計算出速度。

二、為什么要用編碼器

從上圖可以看出,由于TI,T2一前一后有個90度的相位差,所以當出現(xiàn)這個相位差時就表示輪子旋轉了一個角度。但有人會問了:既然都是脈沖,為什么不用普通IO中斷?實際上如果是輪子一直正常旋轉當然沒有問題。仔細觀察上圖,如果出現(xiàn)了毛刺呢?這就是需要我們在軟件中編寫算法進行改正。于是,我們就會想到如果有個硬件能夠處理這種情況那不是挺好嗎?

對應的硬件的編碼器就來了~

我們看到STM32的硬件編碼器還是很智能的,當T1,T2脈沖是連續(xù)產(chǎn)生的時候計數(shù)器加一或減一一次,而當某個接口產(chǎn)生了毛刺或抖動,則計數(shù)器計數(shù)不變,也就是說該接口能夠容許抖動。

在STM32中,編碼器使用的是定時器接口,通過數(shù)據(jù)手冊可知,定時器1,2,3,4,5和8有編碼器的功能,而其他沒有。同時只有CH1和CH2是進行編碼器模式的~

三、STM32編碼器配置相關

編碼器輸入信號TI1,TI2經(jīng)過輸入濾波,邊沿檢測產(chǎn)生TI1FP1,TI2FP2接到編碼器模塊,通過配置編碼器的工作模式,即可以對編碼器進行正向/反向計數(shù)。

比如如果用的是定時器2,則對應的引腳是在PA0和PA1上。

通常為了提高精度我們會選擇在上升沿和下降沿都進行計數(shù)!

還有一個非常重要的圖這里也記錄下

其中讓人費解的應該是在第二列的相對信號的電平,這里就來詳細談一下吧。

其實也不難理解哈,我們上面也說了通常為了提高精度會在A、B兩相的上升沿和下降沿都進行計數(shù),那么對應在一個周期就可以計數(shù)四次,計數(shù)次數(shù)的增加也就意味著精度的提高!

編碼器模式下,如果此時處于正轉,那么這四次計數(shù)應該都是加的。同理,如果是反轉,那么這四次計數(shù)都是減的。那么問題來了,如何判斷正反轉呢?

不就是在相對電平的基礎上嘛?。?!

仔細對照圖中,在正轉或者反轉的情況下,A相對B的電平高低以及上表中的計數(shù)方向便可了然于心!?。?/p>

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

SMS=001;如果只在TI1邊沿計數(shù),則置SMS=010;如果計數(shù)器同時在TI1和TI2邊沿計數(shù),則

置SMS=011。

通過設置TIMx_CCER寄存器中的CC1P和CC2P位,可以選擇TI1和TI2極性;如果需要,還可以

對輸入濾波器編程。

兩個輸入TI1和TI2被用來作為增量編碼器的接口。假定計數(shù)器已經(jīng)啟動(TIMx_CR1

寄存器中的CEN=’1’),計數(shù)器由每次在TI1FP1或TI2FP2上的有效跳變驅(qū)動。

配置范例:

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寄存器,計數(shù)器使能)

四、STM32實戰(zhàn)代碼

對了,必須要說明的是編碼器模式下只能對應一個定時器的CH1/CH2通道,也就是剛好接A、B相! Perfect!!!

/*TIM2初始化為編碼器接口*/

void Encoder_Init_TIM2(void)

{

  • TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;??

  • TIM_ICInitTypeDef TIM_ICInitStructure;??

  • GPIO_InitTypeDef GPIO_InitStructure;

  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定時器4的時鐘

  • RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口時鐘

  • ?

  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置

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

  • GPIO_Init(GPIOA, &GPIO_InitStructure); ? ? ? //根據(jù)設定參數(shù)初始化GPIOA

  • TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  • TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預分頻器?

  • TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數(shù)器自動重裝值

  • TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//選擇時鐘分頻:不分頻

  • TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上計數(shù)??

  • TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  • TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用編碼器模式3

  • TIM_ICStructInit(&TIM_ICInitStructure);

  • TIM_ICInitStructure.TIM_ICFilter = 10;

  • TIM_ICInit(TIM2, &TIM_ICInitStructure);

  • TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新標志位

  • TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  • //Reset counter

  • TIM_SetCounter(TIM2,0);

  • TIM_Cmd(TIM2, ENABLE);?

}

/*TIM4初始化為編碼器接口*/

void Encoder_Init_TIM4(void)

{

  • TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;??

  • TIM_ICInitTypeDef TIM_ICInitStructure;??

  • GPIO_InitTypeDef GPIO_InitStructure;

  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定時器4的時鐘

  • RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口時鐘

  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置

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

  • GPIO_Init(GPIOB, &GPIO_InitStructure); ? ? ? //根據(jù)設定參數(shù)初始化GPIOB

  • TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  • TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預分頻器?

  • TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數(shù)器自動重裝值

  • TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//選擇時鐘分頻:不分頻

  • TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上計數(shù)??

  • TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  • TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用編碼器模式3

  • TIM_ICStructInit(&TIM_ICInitStructure);

  • TIM_ICInitStructure.TIM_ICFilter = 10;

  • TIM_ICInit(TIM4, &TIM_ICInitStructure);

  • TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新標志位

  • TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

  • //Reset counter

  • TIM_SetCounter(TIM4,0);

  • TIM_Cmd(TIM4, ENABLE);?

}

/*單位時間編碼器計數(shù) 輸入定時器 輸出速度值*/

int Read_Encoder(u8 TIMX)

{

  • int Encoder_TIM;? ??

  • switch(TIMX)

  • {

  • case 2:? Encoder_TIM= (short)TIM2 -> CNT;? TIM2 -> CNT=0;break;

  • case 3:? Encoder_TIM= (short)TIM3 -> CNT;? TIM3 -> CNT=0;break;

  • case 4:? Encoder_TIM= (short)TIM4 -> CNT;? TIM4 -> CNT=0;break;

  • default:? Encoder_TIM=0;

  • }

  • return Encoder_TIM;

}

void TIM4_IRQHandler(void)

{? ? ?? ?? ? ??

  • if(TIM4->SR&0X0001)//溢出中斷

  • {? ?? ? ? ? ? ? ? ??

  • } ? ?

  • TIM4->SR&=~(1<<0);//清除中斷標志位? ? ??

}

void TIM2_IRQHandler(void)

{? ? ?? ?? ? ??

  • if(TIM2->SR&0X0001)//溢出中斷

{? ?? ? ? ? ? ? ? ??

} ? ?

  • TIM2->SR&=~(1<<0);//清除中斷標志位? ? ??

}


五、一些注意

1.編碼器有個轉速上限,超過這個上限是不能正常工作的,這個是硬件的限制,原則上線數(shù)越多轉速就越低,這點在選型時要注意,編碼器的輸出一般是開漏的,所以單片機的io一定要上拉輸入狀態(tài).

2.定時器初始化好以后,任何時候CNT寄存器的值就是編碼器的位置信息,正轉他會加反轉他會減這部分是不需要軟件干預的,初始化時給的TIM_Period 值應該是碼盤整圈的刻度值,在減溢出會自動修正為這個數(shù).加超過此數(shù)值就回0.

3.如果要擴展成多圈計數(shù)需要溢出中斷像樓主說的,程序上圈計數(shù)加減方向位就行了.

4.每個定時器的輸入腳可以通過軟件設定濾波

5.應用中如果沒有絕對位置信號或者初始化完成后還沒有收到絕對位置信號前的計數(shù)只能是相對計數(shù).收到絕對位置信號后重新修改一次CNT的值就行了.碼盤一般都有零位置信號,結合到定時器捕獲輸入就行.上電以后要往返運動一下找到這個位置.

6.即便有濾波計數(shù)值偶爾也會有出錯誤的情況,一圈多計一個或少計一個數(shù)都是很正常的特別是轉速比較高的時候尤其明顯,有個絕對位置信號做修正是很有必要的.絕對位置信號不需要一定在零位置點,收到這個信號就將CNT修正為一個固定的數(shù)值即可.

7.開啟定時器的輸入中斷可以達到每個步計數(shù)都作處理的效果,但是高速運轉的時候你可能處理不過來.


STM32定時器配置為編碼器模式的評論 (共 條)

分享到微博請遵守國家法律
蓬溪县| 宁陕县| 贺州市| 永州市| 西盟| 北安市| 雅江县| 平湖市| 常州市| 烟台市| 苏尼特右旗| 宁河县| 鄂州市| 乌审旗| 琼结县| 海盐县| 隆化县| 尉氏县| 盐池县| 安达市| 陇西县| 皮山县| 山西省| 扬中市| 瑞昌市| 施甸县| 永昌县| 彭水| 秀山| 荔浦县| 上思县| 荣昌县| 皮山县| 南丹县| 普兰店市| 文成县| 兖州市| 南陵县| 河间市| 高阳县| 金寨县|