stm32正交編碼器學(xué)習(xí)_第1頁
stm32正交編碼器學(xué)習(xí)_第2頁
stm32正交編碼器學(xué)習(xí)_第3頁
stm32正交編碼器學(xué)習(xí)_第4頁
stm32正交編碼器學(xué)習(xí)_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、最近做一個(gè)項(xiàng)目,主控芯片用STM32RBT6,要用到光柵尺,本來帶一個(gè)控制器的,通過控制器的232可以讀取光柵尺的數(shù)據(jù),但這個(gè)控制器太大,設(shè)備中放不下,于是,考慮自己做一個(gè),網(wǎng)上看到很多有用CPLD的方案,后來無意間發(fā)現(xiàn)stm32的定時(shí)器可以配置成編碼器,甚喜高興之余,突然發(fā)現(xiàn)stm32的定時(shí)器是16位的,我的光柵尺的計(jì)數(shù)會(huì)超過65535,于是在21ic論壇上和幾位高手請教,最終確定的方案工作過程是配置TIM3為正交編碼器模式,并定一個(gè)10ms的中斷,每10ms讀取一次計(jì)數(shù)值,10ms的前提是在10ms內(nèi)計(jì)數(shù)器不溢出(這個(gè)思想要感謝21ic的lxyppc)以下是部分代碼:(這些代碼修改于ST官

2、方的例程,但我的工程用的是V3的固件庫,他們的例程貌似是0.3的,所以有些地方有改動(dòng))下面是初始化TIM3為正交編碼器模式void ENC_Init(void)TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;/* Encoder unit connected to TIM3, 4X mode */ GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;/* TIM3 clock sour

3、ce enable */ 使能端口時(shí)鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/* Enable GPIOA, clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_StructInit(&GPIO_InitStructure);/* Configure PA.06,07 as encoder input */設(shè)置端口為輸入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_In

4、itStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Enable the TIM3 Update Interrupt */使能定時(shí)器3更新中斷NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelSu

5、bPriority = TIMx_SUB_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* Timer configuration in Encoder mode */ 配置編碼器模式TIM_DeInit(ENCODER_TIMER);TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; / No prescaling TIM

6、_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12, TIM_ICPol

7、arity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);/ Clear all pending interruptsTIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENA

8、BLE);/Reset counterTIM2->CNT = COUNTER_RESET;/ ENC_Clear_Speed_Buffer();TIM_Cmd(ENCODER_TIMER, ENABLE); 以下為獲取一次計(jì)數(shù)值,此算法來自lxyppc,可以規(guī)避超過16位的情況,具體細(xì)節(jié)見s16 ENC_Get_Electrical_Angle(void)static u16 lastCount = 0;u16 curCount = ENCODER_TIMER->CNT;s32 dAngle = curCount - lastCount;if(dAngle >= MAX_CO

9、UNT) dAngle -= ENCODER_TIM_PERIOD;else if(dAngle < -MAX_COUNT) dAngle += ENCODER_TIM_PERIOD;lastCount = curCount;return (s16)dAngle; 以下為系統(tǒng)滴答的初始化和中斷函數(shù)void TB_Init(void) /* Setup SysTick Timer for 10 msec interrupts */if (SysTick_Config(SystemFrequency / 100) /* Capture error */ while (1);void SysT

10、ick_Handler(void) /*if (hTimebase_display_500us != 0) hTimebase_display_500us -; */if (hSpeedMeas_Timebase_500us !=0) hSpeedMeas_Timebase_500us-;else hSpeedMeas_Timebase_500us = SPEED_SAMPLING_TIME; CurrentCount += ENC_Get_Electrical_Angle(); /ENC_Calc_Average_Speed must be called ONLY every SPEED_M

11、EAS_TIMEBASE ms /ENC_Calc_Average_Speed(); 以上代碼已通過測試,固件庫版本為:V3.1.2ST官方例程和中文說明文檔:http:/www.stmicroelectronics.co . oder_AN%28CH%29.pdfhttp:/images.stmicroelectronics . 32F10xxx_Encoder_AN(CH).zip最后抱怨一句,st為啥不把定時(shí)器做成32位的呢,能增加1分錢成本嗎原創(chuàng)文章:"【請保留版權(quán),謝謝!】文章出自我愛方案網(wǎng)。這個(gè)是我經(jīng)常用的編碼器讀取方法s16   Enc_GetCou

12、nt(void)  static  u16   lastCount = 0;  u16  curCount = ENCODER_TIM->CNT;  s32 dAngle = curCount - lastCount;  if(dAngle >= MAX_COUNT)    dAngle -= ENCODER_TIM_PERIOD;  else if(dAngle < -MAX_

13、COUNT)    dAngle += ENCODER_TIM_PERIOD;    lastCount = curCount;  return (s16)dAngle;既然你1s都不會(huì)溢出,那你可以做個(gè)每10ms產(chǎn)生一次的中斷在中斷中調(diào)用上面的代碼上述代碼中MAX_COUNT是10ms內(nèi)可能出現(xiàn)的計(jì)數(shù)最大值還要大的值ENCODER_TIM_PERIOD是定時(shí)器的period值,最好比MAX_COUNT大然后定義一個(gè)32位的有符號變量,如currentCount然后每隔10ms執(zhí)行一次currentCou

14、nt += Enc_GetCount();你只需要去讀取currentCount的值就可以得到位移信息了。在這種情況下計(jì)數(shù)器的值變化是這樣的,假設(shè)計(jì)數(shù)器周期值為999:初始值    995正轉(zhuǎn)10   995+10=>1000+5=5反轉(zhuǎn)7     5-7=>-2+1000 = 998最終值    998因此總共轉(zhuǎn)了998-995 = 3個(gè)步長,與實(shí)際情況相同/* Function Name : TIM2_IRQHandler* Description : This function

15、 handles TIM2 global interrupt request.* Input : None* Output : None* Return : None/void TIM2_IRQHandler(void) GPIO_InitTypeDef GPIO_InitStructure; static u16 Seg_Old; if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); if (var = 0) /* OCMP_1 */ var+; /* Segments

16、(lcdcr) to be turned on are loaded with the value 1 otherwise 0 */ Seg_Old = framelcdcr; GPIO_Write(GPIOE,Seg_Old); /* com(lcdcr) is set to low, other coms set to Vdd/2 */ /* Configure all coms as Floating Input */ GPIO_InitStructure.GPIO_Pin = COMPORT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FL

17、OATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /* com(lcdr) is set to low PP */ GPIO_ResetBits(GPIOC,comlcdcr); GPIO_InitStructure.GPIO_Pin = comlcdcr; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); el

18、se /* OCMP_2 */ var = 0; /* Segments(lcdcr) values are inverted */ Seg_Old = (u16)(Seg_Old); GPIO_Write(GPIOE,Seg_Old); /* com(lcdcr) is set to high, other coms set to Vdd/2 */ /* Configure all coms as Floating Input */ GPIO_InitStructure.GPIO_Pin = COMPORT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_

19、IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /* com(lcdr) is set to high PP */ GPIO_SetBits(GPIOC,comlcdcr); GPIO_InitStructure.GPIO_Pin = comlcdcr; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure)

20、; lcdcr+; if (lcdcr>3) lcdcr =0; else if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) TIM_ClearITPendingBit(TIM2, TIM_IT_Update); /* All seg and coms off to decrease VRMS */ GPIO_Write(GPIOE,0); /* Clear segments on portE */ GPIO_ResetBits(GPIOC,COMPORT); /* Clear segments on portC */ /* Confi

21、gure all coms as PP_output */ GPIO_InitStructure.GPIO_Pin = COMPORT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); */stm32編碼器使用方法作者:平凡的陽光 2011-08-23 08:05 星期二 晴 stm32具有16位的編碼器模式,使用它時(shí),16位會(huì)帶來困擾;這里歸結(jié)如下。 既然16

22、位不夠用,就需要擴(kuò)展到32位甚至64位,更多的位數(shù)也可以,不過沒有現(xiàn)成的數(shù)據(jù)類型了;需要探究點(diǎn)別的東西。 如何擴(kuò)展到32位,這讓人困擾;經(jīng)過多次摸索,確認(rèn)使用定時(shí)查詢編碼器計(jì)數(shù)值,用軟件擴(kuò)展到32位的方法最可靠。 例說如下: 這里設(shè)置自動(dòng)裝載值為65535,在使用中不更改這個(gè)ARR值;那么發(fā)生跳變的情況就發(fā)生在0-65535的跳變上,不論它倆由誰變到誰,在我們擴(kuò)展到32位時(shí)都會(huì)引起65535的數(shù)值變化。 由于我們定時(shí)查詢,假定每1ms查詢一次,恰巧在這1ms內(nèi)發(fā)生了跳變;假定跳變前后的值分別為:60000,10000。跳動(dòng)量為60000-10000=50000,這也是跳變前后未修正時(shí)的計(jì)數(shù)差值

23、;反應(yīng)到實(shí)際中為在跳變時(shí)變化量大,為突然性的“暴跌”或“大漲”。那么平時(shí)也有變化“亢進(jìn)”的時(shí)候,這時(shí)候怎么區(qū)分呢。這需要具體問題具體分析。如下。 對于32767的變化量,在1ms查詢周期下;對應(yīng)的變化量為3.2767*10000000,stm32的gpio翻轉(zhuǎn)速度未必有這么高,也就是說現(xiàn)在的“木桶”,最短的不會(huì)是我們的計(jì)數(shù)方式了。 在適用范圍內(nèi),最小的“跳變”量是32768;所以我們能夠接納的最大“亢進(jìn)”量是32767。也就是只要變化量沒過32767,我們可以認(rèn)為他是正常的計(jì)數(shù),沒有發(fā)生跳變。否則就是發(fā)生了跳變,需要參照上次的32位計(jì)數(shù)值修正計(jì)數(shù);就是“+”或“-”掉跳變值65535。 至此,

24、完成了第一個(gè)任務(wù),將16位定時(shí)器擴(kuò)展到32位或64位計(jì)數(shù)。 這里的限定條件是: 1:使用stm32,編碼器計(jì)數(shù)模式 2:編碼器輸入的信號頻率不僅< 32.767M,考慮到IO的高頻響應(yīng)能力,有可能更低。 3:自動(dòng)裝載值為65535,如果<65535,對應(yīng)的可輸入信號頻率也會(huì)跟著減??;更改它相當(dāng)于亂搬石頭,有砸腳風(fēng)險(xiǎn)。 4:報(bào)告一聲,“到目前,還沒必要開溢出中斷”,考慮利用中斷倒并非“杞人憂天”。 void ENC_Init(void)TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitSt

25、ructure;/* Encoder unit connected to TIM3, 4X mode */ GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;/* TIM3 clock source enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/* Enable GPIOA, clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_StructIni

26、t(&GPIO_InitStructure);/* Configure PA.06,07 as encoder input */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Enable the TIM3 Update Interrupt */NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;NVIC_InitStructure

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論