- 看前說明:這里重點介紹的時STM32的定時器編碼器模式,是根據(jù)STMF10x參考手冊,如果有使用過編碼器或編碼器不一樣的可以直接跳過前面的編碼器介紹,直接看理論分析與程序部分。
1、編碼器介紹
- 這里需要注意的參數(shù)
- 輸出脈沖線數(shù):1024線:編碼器每旋轉(zhuǎn)一周輸出的脈沖的個數(shù),這個數(shù)據(jù)就是你在編寫的定時器的重裝載值。
-
兩種編碼器的區(qū)別
- 從圖中看就會來的更加直接:
- 帶方向的編碼器只有一路的脈沖輸出,另外一路就是編碼器的正反轉(zhuǎn)的信號,零位信號就是編碼器的機(jī)械零位。
- 帶方向的編碼器只有一路的脈沖輸出,另外一路就是編碼器的正反轉(zhuǎn)的信號,零位信號就是編碼器的機(jī)械零位。
- 從圖中看就會來的更加直接:
- 正交編碼器兩路的脈沖輸出,在判斷電機(jī)的正反轉(zhuǎn)時,是更加A、B兩相的波形來的,其實就是看哪路波形超前,這里用32的定時器編碼器功能就只需要去查計數(shù)器的方向位來判斷電機(jī)的正反轉(zhuǎn)。
- 引腳說明
2、脈沖計數(shù)對應(yīng)電機(jī)速度的數(shù)據(jù)兩種處理方式
(1) 定時器中斷法,計算電機(jī)的圈數(shù)(過程小題大做,不推薦)
- 前面提到了編碼器的線數(shù)為1024線(編碼器每轉(zhuǎn)一周就會輸出1024個脈沖),那么你的重裝載值為(1024-1),當(dāng)計數(shù)值達(dá)到1024就會發(fā)生溢出中斷,也就是說識別到了脈沖數(shù)為1024個(編碼器轉(zhuǎn)了一圈)。每發(fā)生一次中斷,就說明電機(jī)轉(zhuǎn)了一圈
(1)脈沖計數(shù)法,直接根據(jù)單位時間內(nèi)所采集到的脈沖數(shù)作為電機(jī)的轉(zhuǎn)速(更加精準(zhǔn),推薦)
- 編碼器在實際的測數(shù)使用時確實是根據(jù),電機(jī)轉(zhuǎn)一圈:編碼器轉(zhuǎn)多少圈的方式來實際測量電機(jī)的轉(zhuǎn)速的,但是在其本質(zhì)就還是編碼器的輸出的脈沖數(shù),所以直接計算編碼器的單位時間的脈沖數(shù)推算電機(jī)的速度是一樣的,數(shù)據(jù)來的更加直接、精準(zhǔn)。
3、STM32定時器編碼器模式理論分析
(1)定時器編碼器模式選擇
文章來源:http://www.zghlxwxcb.cn/news/detail-423857.html
- 首先是定時器編碼器模式的選擇,其實就是選擇在那一個通道計數(shù),還是兩個通道都要計數(shù)也就是這三種模式。
- 對于帶方向的就只有一路脈沖,所以選擇其中一路通道就ok了。
- 對于正交編碼器而言有兩路脈沖,所以就選擇第三中方式,兩路通道都計數(shù)。
(2)定時器編碼器輸入極性的選擇
-
看懂這張圖才是,確定輸入極性的關(guān)鍵所在:所謂極性就是選擇在輸入脈沖信號的上升沿計數(shù)還是下降沿計數(shù)。
(3)定時器編碼器輸入極性的寄存器配置
文章來源地址http://www.zghlxwxcb.cn/news/detail-423857.html
CC1S=’01’ (TIMx_CCMR1寄存器,IC1FP1映射到TI1)
CC2S=’01’ (TIMx_CCMR1寄存器,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ù)器使能)
- 這里解釋一下
- TIx 就相當(dāng)于輸入信號的 TIM4->CH1 TIM4->CH2;
- TIxF 濾波后信號;
-
TIxFPx經(jīng)過帶極性選擇的邊緣檢測器過后的產(chǎn)生的信號;
4、結(jié)合手冊函數(shù)刨析庫函數(shù)
(1)STM32定時器編碼器模式的庫函數(shù)配置代碼
/*TIM2初始化為編碼器接口*/
void Encoder_Init_TIM2(void)
{
//結(jié)構(gòu)體變量的創(chuàng)建
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//RCC時鐘使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定時器4的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口時鐘
//編碼器引腳的配置,對于定時器的通道管腳在用戶手冊上的==8.3.7定時器復(fù)用功能重映射==
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è)定參數(shù)初始化GPIOA
//定時器的基本配置,這里主要介紹定時器的編碼器模式,不做過多解釋
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預(yù)分頻器
TIM_TimeBaseStructure.TIM_Period = 0xffff; //設(shè)定計數(shù)器自動重裝值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//選擇時鐘分頻:不分頻
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數(shù)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//編碼器模式選擇與配置
//參數(shù)一TIMx:定時器的選擇
//參數(shù)二TIM_EncoderMode:編碼器模式的選擇
//參數(shù)三TIM_IC1Polarity:通道一的極性選擇
//參數(shù)四TIM_IC2Polarity:通道二的極性選擇
//具體配置->正交編碼器:配置如下
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
//帶方向的編碼器配置如下->區(qū)別只在于帶方向的編碼器只有一個脈沖輸入,而正交編碼器有兩個脈沖輸入
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新標(biāo)志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//Reset counter
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);
}
(2)刨析
- 轉(zhuǎn)到
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
函數(shù)下可以看到如下代碼:
/* Get the TIMx SMCR register value */
tmpsmcr = TIMx->SMCR;
/* Get the TIMx CCMR1 register value */
tmpccmr1 = TIMx->CCMR1;
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
-
再看下面來自用戶手冊中的截圖,就不用我再繼續(xù)挖下去了。
5、編碼器速度的讀取
- 前面已經(jīng)說過了編碼器的脈沖計數(shù)對應(yīng)電機(jī)速度的數(shù)據(jù)處理方法,這里就繼續(xù)說明了。
- 速度是單位時間為前提的,我這里采用的是直接計算單位時間對應(yīng)的脈沖數(shù)來推算電機(jī)的速度的。這里的單位時間也就是采樣率的意思,就是我們間隔多少時間去采集然后清零脈沖計數(shù)值一次。這里的采樣率不能太高,也不能太低。對電機(jī)的控制,一般采樣率=5毫秒越小就越接近瞬時速度,為什么不能過小想必不用說大家也知道。所以這里就需要一個定時器來計算采樣周期
//配置定時器1每5毫秒中斷一次,在中斷函數(shù)中讀取編碼器數(shù)值
void Time1_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStrure;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//定時器的基本配置
TIM_TimeBaseStrure.TIM_Period = 1000-1;//計數(shù)的次數(shù)
TIM_TimeBaseStrure.TIM_Prescaler = 7200-1;//控制頻率72000000/7200=10000;頻率=10000HZ
TIM_TimeBaseStrure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStrure.TIM_ClockDivision = 0;
TIM_TimeBaseStrure.TIM_RepetitionCounter = 0;//重復(fù)計數(shù)次數(shù)
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStrure);
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清空中斷標(biāo)志位
TIM_ITConfig(TIM1,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//開啟中斷更新和觸發(fā)中斷源
NVIC_InitStruct.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM1,ENABLE);
}
int Read_Encoder(void)
{
int value_1;
value_1=(int)TIM_GetCounter(TIM2);
TIM_SetCounter(TIM2,0);
return value_1;
}
void TIM1_UP_IRQHandler()
{
int circle_count ;
if(TIM_GetITStatus(TIM1,TIM_IT_Update) != RESET)
{
circle_count = Read_Encoder();
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清空中斷標(biāo)志位
}
}
到了這里,關(guān)于STM32編碼器模式(帶方向/正交編碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!