色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 用STM32對編碼開關(guān)實(shí)現(xiàn)精確計(jì)數(shù)

          用STM32對編碼開關(guān)實(shí)現(xiàn)精確計(jì)數(shù)

          作者: 時(shí)間:2016-11-13 來源:網(wǎng)絡(luò) 收藏
          機(jī)械觸點(diǎn)式編碼開關(guān),依靠 A 相和 B 相信號的相位差來判斷旋轉(zhuǎn)方向,脈沖數(shù)計(jì)數(shù),輸出的理想波形如下圖:
          實(shí)際使用時(shí),其輸出的脈沖邊沿可能會包含很多毛刺,如果簡單的使用上升沿或者下降沿觸發(fā),在邊沿處會可能產(chǎn)生很多誤觸發(fā),使用延時(shí)等手段雖能緩解,但從方法到結(jié)果都有蒙混過關(guān)之嫌,不能令人滿意。下圖是我用示波器隨意抓了一個(gè)編碼開關(guān)的下降沿:

          為了能夠可靠計(jì)數(shù),必須避開上升沿和下降沿附近的毛刺,在編碼開關(guān)輸出脈沖信號的脈沖中段取值,如下圖所示:
          1、A 相和 B 相信號分別送入具有上升/下降沿觸發(fā)能力的IO,開啟上升沿/下降沿觸發(fā)中斷;
          2、在 A 相信號的上升沿/下降沿觸發(fā)中斷中判斷 B 相的狀態(tài),如上圖所示的 T0 時(shí)刻,得到 B 相當(dāng)前的值為 0;
          3、在 B 相信號的上升沿/下降沿觸發(fā)中斷中判斷 A 相的狀態(tài),如上圖所示的 T1 時(shí)刻,得到 A 相當(dāng)前的值為 1;
          4、建立一個(gè)保存 A 相 和 B 相狀態(tài)的數(shù)組,至少可保存 3 組狀態(tài)值,若得到的狀態(tài)值和數(shù)組中保存的上一個(gè)狀態(tài)值相等,說明該次觸發(fā)為毛刺,則不更新狀態(tài)數(shù)組,例如 T1 時(shí)刻由 B 相信號觸發(fā)的中斷程序中,判斷 A 相信號為 1 狀態(tài),與 T0 時(shí)刻中的 A:0; B:0 狀態(tài)不同,則更新數(shù)組;若 T1 時(shí)刻后 B 相的上升沿產(chǎn)生毛刺進(jìn)入中斷程序,則因?yàn)樽x取到的 A 相值仍然為 1,因?yàn)楹蜕弦粋€(gè)狀態(tài)相同,不更新狀態(tài)數(shù)組;
          5、如此利用 A 相的邊沿觸發(fā)中斷讀取 B 相的值,B 相的邊沿觸發(fā)讀取 A 相的值,就可以保證取樣點(diǎn)位于沒相信號的中間時(shí)刻;
          6、在每次狀態(tài)數(shù)組有更新時(shí)判斷編碼開關(guān)的旋轉(zhuǎn)方向,如上圖藍(lán)色框內(nèi)的數(shù)值組合出現(xiàn)時(shí),可以判斷編碼器 +1,反之,如下圖紫色框內(nèi)的數(shù)值組合出現(xiàn)時(shí),可判斷編碼器值 -1;
          7、當(dāng)編碼器出現(xiàn)中途改變方向的情況時(shí),其輸出的脈沖如下圖所示:
          可以看到,T1、T2、T3時(shí)刻編碼器產(chǎn)生 +1 的計(jì)數(shù)脈沖,T5、T6 因?yàn)椴杉降?A 相和 B 相狀態(tài)值與 T3 狀態(tài)沒有變化,故不更新狀態(tài)數(shù)組也不做任何處理,到 T7 時(shí)刻以后開始更新,則 T3、T7、T8 組合產(chǎn)生 -1 的狀態(tài)組合。整個(gè)過程中都不會發(fā)生丟計(jì)數(shù)的情況,另一種編碼器改變旋轉(zhuǎn)方向的情況如下:
          類似上面的分析,也不會發(fā)生丟計(jì)數(shù)的情況。下面給出STM32外部觸發(fā)程序作為參考:
          /* Encoder.c */
          signed char Phase_A, Phase_B; //按bit位來儲存A/B相的狀態(tài),bit7作為緩存,bit6為最新狀態(tài) //值,然后依次是bit5、bit4,需要更新時(shí),使用右移操作,之 //所以使用有符號數(shù),是為了右移時(shí)保留bit7的值
          void EXTI0_IRQHandler(void)
          {
          EXTI->PR &= EXTI_PR_PR0; //Clear interrup pending
          if(COMP->CSR & COMP_CSR_COMP2OUT) //若編碼器直接連入IO,此處改為判斷IO狀態(tài)即可,我使 //用的是比較器輸出的值來驅(qū)動IO產(chǎn)生外部觸發(fā),故為此
          {
          Phase_B |= 0x80; //Phase_B = 1xxx xxxx
          }
          else
          {
          Phase_B &= 0x7F; //Phase_B = 0xxx xxxx
          }
          if(((Phase_B << 1)^Phase_B) & 0x80) //判斷緩存中的bit7位和bit6位是否相等,若不等,更新緩存
          {
          Phase_B >>= 1;
          Phase_A >>= 1;
          if( ((Phase_A & 0x70) == 0x30) && ((Phase_B & 0x70) == 0x60) ) //A:0 1 1, B:1 1 0 序列
          {
          FlashData_Copy.encoder_count += 1;
          }
          if( ((Phase_A & 0x70) == 0x60) && ((Phase_B & 0x70) == 0x30) ) //A:1 1 0, B:0 1 1 序列
          {
          FlashData_Copy.encoder_count -= 1;
          }
          }
          }
          void EXTI2_TSC_IRQHandler(void)
          {
          EXTI->PR &= EXTI_PR_PR2; //Clear interrupt pending
          if(COMP->CSR & COMP_CSR_COMP1OUT)
          {
          Phase_A |= 0x80; //Phase_A = 1xxx xxxx
          }
          else
          {
          Phase_A &= 0x7F; //Phase_A = 0xxx xxxx
          }
          if(((Phase_A << 1)^Phase_A) & 0x80)
          {
          Phase_A >>= 1;
          Phase_B >>= 1;
          if( ((Phase_A & 0x70) == 0x30) && ((Phase_B & 0x70) == 0x60) )
          {
          FlashData_Copy.encoder_count += 1;
          }
          if( ((Phase_A & 0x70) == 0x60) && ((Phase_B & 0x70) == 0x30) )
          {
          FlashData_Copy.encoder_count -= 1;
          }
          }
          }
          /******************************************************************************
          EXTI0 and EXTI2 interrupt setup
          ******************************************************************************/
          void setupEXTI0_2(void)
          {
          /* EXTI0 config */
          SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA;
          EXTI->IMR |= EXTI_IMR_MR0;
          EXTI->RTSR |= EXTI_RTSR_TR0; //Rising trigger
          EXTI->FTSR |= EXTI_FTSR_TR0; //Falling trigger
          /* Enable the Selected IRQ Channels --------------------------------------*/
          NVIC->ISER[EXTI0_IRQn >> 0x05] |=
          (uint32_t)0x01 << (EXTI0_IRQn & (uint8_t)0x1F);
          /* EXTI2 config */
          SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI2_PA;
          EXTI->IMR |= EXTI_IMR_MR2;
          EXTI->RTSR |= EXTI_RTSR_TR2;
          EXTI->FTSR |= EXTI_FTSR_TR2;
          /* Enable the Selected IRQ Channels --------------------------------------*/
          NVIC->ISER[EXTI2_TSC_IRQn >> 0x05] |=
          (uint32_t)0x01 << (EXTI2_TSC_IRQn & (uint8_t)0x1F);
          }
          該方案外圍電路簡單,無需電容濾波,因采樣點(diǎn)為脈沖中部,故工作可靠,在編碼器的特定位置做上記號用手隨意改變方向和速度做測試,最后總能在編碼開關(guān)回到原位置時(shí)歸零,缺點(diǎn)是需要IO具有上升/下降沿的雙向邊沿觸發(fā)能力,以及使用了中斷程序占用了部分資源。


          評論


          技術(shù)專區(qū)

          關(guān)閉