一、STM32F407 定時(shí)器編碼器功能
1.1 STM32定時(shí)器簡(jiǎn)介
STM32的定時(shí)器功能非常強(qiáng)大,根據(jù)官方手冊(cè),定時(shí)器的功能如下
高級(jí)定時(shí)器
TIM1 和 TIM8 主要特性
TIM1 和 TIM8 定時(shí)器具有以下特性:
● 16 位遞增、遞減、遞增/遞減自動(dòng)重載計(jì)數(shù)器。
● 16 位可編程預(yù)分頻器,用于對(duì)計(jì)數(shù)器時(shí)鐘頻率進(jìn)行分頻(即運(yùn)行時(shí)修改),分頻系數(shù)
介于 1 到 65536 之間。
● 多達(dá) 4 個(gè)獨(dú)立通道,可用于:
— 輸入捕獲
— 輸出比較
— PWM 生成(邊沿和中心對(duì)齊模式)
— 單脈沖模式輸出
● 帶可編程死區(qū)的互補(bǔ)輸出。
● 使用外部信號(hào)控制定時(shí)器且可實(shí)現(xiàn)多個(gè)定時(shí)器互連的同步電路。
● 重復(fù)計(jì)數(shù)器,用于僅在給定數(shù)目的計(jì)數(shù)器周期后更新定時(shí)器寄存器。
● 用于將定時(shí)器的輸出信號(hào)置于復(fù)位狀態(tài)或已知狀態(tài)的斷路輸入。
● 發(fā)生如下事件時(shí)生成中斷/DMA 請(qǐng)求:
— 更新:計(jì)數(shù)器上溢/下溢、計(jì)數(shù)器初始化(通過(guò)軟件或內(nèi)部/外部觸發(fā))
— 觸發(fā)事件(計(jì)數(shù)器啟動(dòng)、停止、初始化或通過(guò)內(nèi)部/外部觸發(fā)計(jì)數(shù))
— 輸入捕獲
— 輸出比較
— 斷路輸入
● 支持定位用增量(正交)編碼器和霍爾傳感器電路。
● 外部時(shí)鐘觸發(fā)輸入或逐周期電流管理。
通用定時(shí)器
TIM2 到 TIM5 主要特性
通用 TIMx 定時(shí)器具有以下特性:
● 16 位(TIM3 和 TIM4)或 32 位(TIM2 和 TIM5) 遞增、遞減和遞增/遞減自動(dòng)重載計(jì)
數(shù)器。
● 16 位可編程預(yù)分頻器,用于對(duì)計(jì)數(shù)器時(shí)鐘頻率進(jìn)行分頻 (即運(yùn)行時(shí)修改),分頻系數(shù)介
于 1 到 65536 之間。
● 多達(dá) 4 個(gè)獨(dú)立通道,可用于:
— 輸入捕獲
— 輸出比較
— PWM 生成(邊沿和中心對(duì)齊模式)
— 單脈沖模式輸出
● 使用外部信號(hào)控制定時(shí)器且可實(shí)現(xiàn)多個(gè)定時(shí)器互連的同步電路。
● 發(fā)生如下事件時(shí)生成中斷/DMA 請(qǐng)求:
— 更新:計(jì)數(shù)器上溢/下溢、計(jì)數(shù)器初始化(通過(guò)軟件或內(nèi)部/外部觸發(fā))
— 觸發(fā)事件(計(jì)數(shù)器啟動(dòng)、停止、初始化或通過(guò)內(nèi)部/外部觸發(fā)計(jì)數(shù))
— 輸入捕獲
— 輸出比較
● 支持定位用增量(正交)編碼器和霍爾傳感器電路
● 外部時(shí)鐘觸發(fā)輸入或逐周期電流管理
1.2 STM32定時(shí)器編碼器功能
根據(jù)下面的圖可以看出通用定時(shí)器也是有編碼器輸入功能。
在編碼輸入時(shí)是有上升沿與下降沿的,我們可以利用外部中斷分別捕獲編碼器A、B項(xiàng)邊沿,手寫(xiě)邏輯消除毛刺并解析編碼器數(shù)據(jù),但這是比較復(fù)雜的。其實(shí)這里的脈沖輸入是一種特殊的輸入捕獲情況,因此stm32專(zhuān)門(mén)在定時(shí)器中提供了編碼器模式,可大大簡(jiǎn)化解析過(guò)程。
選擇編碼器接口模式時(shí),如果計(jì)數(shù)器僅在 TI2 邊沿處計(jì)數(shù),在 TIMx_SMCR 寄存器中寫(xiě)入
SMS=001;如果計(jì)數(shù)器僅在 TI1 邊沿處計(jì)數(shù),寫(xiě)入 SMS=010;如果計(jì)數(shù)器在 TI1 和 TI2 邊 沿處均計(jì)數(shù),則寫(xiě)入 SMS=011。
通過(guò)編程 TIMx_CCER 寄存器的 CC1P 和 CC2P 位,選擇 TI1 和 TI2 極性。如果需要,還可對(duì)輸入濾波器進(jìn)行編程TI1 和 TI2 兩個(gè)輸入用于連接增量編碼器。請(qǐng)參見(jiàn)表 75。如果使能計(jì)數(shù)器(在 TIMx_CR1 寄 存器的 CEN 位中寫(xiě)入“1”),則計(jì)數(shù)器的時(shí)鐘由 TI1FP1 或 TI2FP2 上的每次有效信號(hào)轉(zhuǎn) 換提供。TI1FP1 和 TI2FP2 是進(jìn)行輸入濾波器和極性選擇后 TI1 和 TI2 的信號(hào),如果不進(jìn)行 濾波和反相,則 TI1FP1=TI1,TI2FP2=TI2。將根據(jù)兩個(gè)輸入的信號(hào)轉(zhuǎn)換序列,產(chǎn)生計(jì)數(shù)脈 沖和方向信號(hào)。根據(jù)該信號(hào)轉(zhuǎn)換序列,計(jì)數(shù)器相應(yīng)遞增或遞減計(jì)數(shù),同時(shí)硬件對(duì) TIMx_CR1 寄存器的 DIR 位進(jìn)行相應(yīng)修改。任何輸入(TI1 或 TI2)發(fā)生信號(hào)轉(zhuǎn)換時(shí),都會(huì)計(jì)算 DIR 位,無(wú)論計(jì)數(shù)器是僅在 TI1 或 TI2 邊沿處計(jì)數(shù),還是同時(shí)在 TI1 和 TI2 處計(jì)數(shù)。
編碼器接口模式就相當(dāng)于帶有方向選擇的外部時(shí)鐘。這意味著,計(jì)數(shù)器僅在 0 到 TIMx_ARR 寄存器中的自動(dòng)重載值之間進(jìn)行連續(xù)計(jì)數(shù)(根據(jù)具體方向,從 0 遞增計(jì)數(shù)到 ARR,或從 ARR 遞減計(jì)數(shù)到 0)。因此,在啟動(dòng)前必須先配置 TIMx_ARR。同樣,捕獲、比較、預(yù)分頻 器、觸發(fā)輸出功能繼續(xù)正常工作。
在此模式下,計(jì)數(shù)器會(huì)根據(jù)增量編碼器的速度和方向自動(dòng)進(jìn)行修改,因此,其內(nèi)容始終表示編碼器的位置。計(jì)數(shù)方向?qū)?yīng)于所連傳感器的旋轉(zhuǎn)方向。下表匯總了可能的組合(假設(shè) TI1 和 TI2 不同時(shí)切換)。
下圖為雙項(xiàng)模式下計(jì)數(shù)效果,可見(jiàn)在A(yíng)、B中僅一項(xiàng)有**抖動(dòng)(**就是編譯器無(wú)效的脈沖,需要過(guò)濾)時(shí),計(jì)數(shù)值加減后保持不變,實(shí)現(xiàn)了抖動(dòng)補(bǔ)償
從圖上可以看出,定時(shí)器是采集A、B兩相的脈沖,當(dāng)編碼器輸出一個(gè)周期時(shí),定時(shí)器計(jì)數(shù)值為4,這是要必須記住的哈。
二、帶編碼器的直流電機(jī)
我手上剛好有一個(gè)帶編碼器的直流電機(jī),電機(jī)參數(shù)如下,520電機(jī)包含編碼器款該電機(jī)采用全金屬齒輪,具備功率大、抗干擾好、精度高、壽命長(zhǎng)的特點(diǎn)。
在這里需要說(shuō)明一下,如果電機(jī)轉(zhuǎn)一圈,那么黃線(xiàn)輸出的脈沖數(shù)量為:1130 = 330個(gè), 那么綠線(xiàn)輸出的脈沖數(shù)量為:1130 = 330個(gè)。根據(jù)上面分析的定時(shí)器編碼器模式,電機(jī)轉(zhuǎn)一圈,定時(shí)器計(jì)數(shù)脈沖的個(gè)數(shù)為:330*4 = 1320個(gè)。
三、代碼與驗(yàn)證
電機(jī)實(shí)物圖
3.1 初始化代碼
/****************************************
引腳說(shuō)明
A相連接PB6
B相連接PB7
PB6 -- TIM4_CH1
PB7 -- TIM4_CH2
****************************************/
void TIM4_Int_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//開(kāi)啟GPIOC的時(shí)鐘
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_TIM4);//將引腳6映像到TIM8
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_TIM4);//將引腳7映像到TIM8
//定時(shí)器設(shè)置-------------------------------------------------------------
TIM_TimeBaseInitStructure.TIM_Period = 330*4; //重裝載值 這是兩相脈沖總數(shù)量
TIM_TimeBaseInitStructure.TIM_Prescaler=0x0; //預(yù)分頻
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計(jì)數(shù)
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //時(shí)鐘分割
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM3
//編碼器模式設(shè)置--------------------------------------------------------------
TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//計(jì)數(shù)模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10; //濾波器值
TIM_ICInit(TIM4, &TIM_ICInitStructure);
//溢出中斷設(shè)置--------------------------------------------------------------
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允許TIM4溢出中斷
NVIC_InitStructure.NVIC_IRQChannel =TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Reset counter-----------------------------------------------
TIM_SetCounter(TIM4,0); //TIM3->CNT=0
TIM_Cmd(TIM4, ENABLE);
}
主函數(shù)
int Encoder_Timer_Overflow; //編碼器溢出次數(shù)
u16 Previous_Count;
u32 speed=0;
int circle_count = 0; //記錄電機(jī)正反轉(zhuǎn)
//void TIM8_CC_IRQHandler(void)
//{
// if(TIM_GetITStatus(TIM8,TIM_IT_Update)==SET)
// {
// Encoder_Timer_Overflow++;
// }
// TIM_ClearITPendingBit(TIM8,TIM_IT_Update);
//}
//電機(jī)轉(zhuǎn)動(dòng)一圈產(chǎn)生中斷
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)
{
Encoder_Timer_Overflow++;
if((TIM4->CR1>>4 & 0x01)==0) //DIR==0 通過(guò)寄存器TIMx_CR1第四位判斷 0:電機(jī)正轉(zhuǎn)
circle_count++;
else if((TIM4->CR1>>4 & 0x01)==1)//DIR==1 通過(guò)寄存器TIMx_CR1第四位判斷 1:電機(jī)正轉(zhuǎn)
circle_count--;
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
void Read_Encoder(void)
{
u16 Current_Count; //一段時(shí)間的脈沖數(shù)
u16 Enc_Timer_Overflow_one; //當(dāng)前脈沖數(shù)
Enc_Timer_Overflow_one=Encoder_Timer_Overflow; //獲取中斷溢出次數(shù)
Current_Count = TIM_GetCounter(TIM4); //得到脈沖數(shù)
Encoder_Timer_Overflow=0; //清0方便下次計(jì)算
//speed = (u32)(Enc_Timer_Overflow_one*車(chē)輪周長(zhǎng)+Current_Count/(330*4.0)*車(chē)輪周長(zhǎng)); //進(jìn)行平均測(cè)速
}
int main(void)
{
u16 m = 0,n = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
usart1_init(115200);
//TIM8_Int_Init();
TIM4_Int_Init();
while(1)
{
delay_ms(500);
delay_ms(500);
//CNT的值,能夠表示當(dāng)前獲取了多少個(gè)脈沖
printf("獲取定時(shí)器中的CNT值:%d\r\n",TIM4->CNT);
//值為正,表示正轉(zhuǎn)圈數(shù)比反轉(zhuǎn)圈數(shù)多,反之亦然;值遞增,表示正在正轉(zhuǎn),值遞減,表示正在反轉(zhuǎn)。
printf("目前輪子正或反的圈數(shù):%d\r\n",circle_count);
}
return 0;
}
3.2 驗(yàn)證
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-402953.html
總結(jié)一下,通過(guò)對(duì)這些的理解,那么可以計(jì)算速度、角度、加速度等。
最后代碼鏈接:https://download.csdn.net/download/wwwqqq2014/87124313?spm=1001.2014.3001.5503文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-402953.html
到了這里,關(guān)于STM32F407 電機(jī)編碼器測(cè)量的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!