Mam taki mały prosty problem, uruchomiłem encoder mode w stm32f4, działa bez problemu, dodałem poszerzenie zakresu z 16 bit na 32 bity, przy osiągnięciu przez licznik wartości maksymalnej 16 bitowej bez znaku.
Problem leży w tym że przy przejściu wartości z zera na 65535 (0xFFFF), że moja implementacja nie działa - pewnie błąd w logiczny, ale go nie widzę.
- typedef struct {
- uint32_t timerImpulsesPresent, timerImpulsesMul, timerImpulsesOverflowsMul;
- int32_t timerImpulsesDiff, timerImpulsesTemp;
- int32_t timerImpulsesTotal, timerImpulsesOld;
- uint8_t direction;
- uint16_t cntVal;
- float distanceMilimeters;
- float distanceMeters;
- float speedMilimeters;
- float translationMilimeters;
- float rotationMilimeters;
- } encoderTypedef;
- static void encoderTimerInit(TIM_TypeDef *tim)
- {
- __IO uint32_t arrVal = 0xFFFF;
- __IO uint32_t ccmr1Val = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0 |
- TIM_CCMR1_IC1F_3 | TIM_CCMR1_IC1F_0 |
- TIM_CCMR1_IC2F_3 | TIM_CCMR1_IC2F_0;
- __IO uint32_t smcrVal = TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0;
- __IO uint32_t dierVal = TIM_DIER_UIE;
- __IO uint32_t cr1Val = TIM_CR1_CEN;
- //ENC2
- tim->ARR = arrVal;
- tim->CCMR1 = ccmr1Val;
- TIM_ENC_RIGHT->CCER = TIM_CCER_CC1P;
- tim->SMCR = smcrVal;
- tim->DIER = dierVal;
- tim->CR1 |= cr1Val;
- }
- void encoderInterruptHandler(encoderTypedef *enc, TIM_TypeDef *tim)
- {
- if(tim->SR & TIM_SR_UIF)
- {
- if(tim->CNT == 0xFFFF && enc->timerImpulsesOld > tim->CNT)
- {
- enc->timerImpulsesOverflowsMul++;
- enc->timerImpulsesMul = UINT16_MAX*enc->timerImpulsesOverflowsMul;
- }
- else
- {
- enc->timerImpulsesOverflowsMul = 0;
- enc->timerImpulsesMul = 0;
- }
- tim->SR &= ~TIM_SR_UIF;
- }
- }
- void TIM3_IRQHandler(void) //left
- {
- encoderInterruptHandler(&encoderLeft, TIM_ENC_LEFT);
- }
- void TIM4_IRQHandler(void) //right
- {
- encoderInterruptHandler(&encoderRight, TIM_ENC_RIGHT);
- }
- void encoderMilimeterSpeedRead(encoderTypedef *enc, TIM_TypeDef *tim)
- {
- //const float mmPerTick = 360.0F/ENCODER_TICKS;
- const float wheelPerimeter = M_PI*WHEEL_DIAMETER;
- const float constructionParam = wheelPerimeter/ENCODER_TICKS;
- enc->timerImpulsesOld = enc->timerImpulsesPresent;
- enc->timerImpulsesPresent = tim->CNT;
- enc->timerImpulsesDiff = (enc->timerImpulsesPresent - enc->timerImpulsesOld);
- enc->timerImpulsesTemp = abs(enc->timerImpulsesPresent - enc->timerImpulsesTemp);
- if(enc->timerImpulsesDiff < 0 || (enc->timerImpulsesTemp >= INT16_MAX && enc->timerImpulsesMul == 0))
- {
- enc->timerImpulsesTotal = 0xFFFF - enc->timerImpulsesPresent;
- }
- else
- {
- enc->timerImpulsesTotal = enc->timerImpulsesPresent + enc->timerImpulsesMul;
- enc->timerImpulsesTemp = enc->timerImpulsesTotal;
- }
- enc->distanceMilimeters = (constructionParam*enc->timerImpulsesTotal);
- enc->distanceMeters = enc->distanceMilimeters/1000;
- }
- void ProcessEncoders(void)
- {
- encoderMilimeterSpeedRead(&encoderLeft, TIM_ENC_LEFT);
- encoderMilimeterSpeedRead(&encoderRight, TIM_ENC_RIGHT);
- }