G431RBT6 - Interfacing timer and compare output timer have rather fluctuation timings
I have timer 1 to use with hall sensors as interfacing timer. Timer 8 is then used to output the signals (see picture red and blue).
The simulated hallsignal (3 sensors combined) is very precise and pretty constant (green signal - second box).
"A" shows the interrupt test signal from the input interrupt. "B" is the interrupt from CCR2 of timer 1 that does actually nothing, but shows where the output signals should change.
The first box shows the interval between those 2 high levels of the outputs of timer 8.
The delay from A to B is set to be constant. I have already came across the problem of resetting the counter and prescaler of timer 1, so that is not an issue anymore.
What else would there be, that would cause such a fluctuation? Interrupts should not be critical, as the stuff is happening in the background?
My loop() is empty.
Timer 1:
/**
* Timer for hallsensors (Rotor speed for FOC later)
* Delayed execution of interrupt comes from filter!!!
*/
void initHallTim1AndDriverTim8(){
__disable_irq();
__HAL_RCC_TIM1_CLK_ENABLE();
SET_BIT( TIM1->CR2, TIM_CR2_TI1S); // config all 3 hall signals (PC0-2) via XOR to timer 1
WRITE_REG(TIM1->ARR, 0xFFFF); // Max value (is reset by input signal)
WRITE_REG(TIM1->PSC, TIM1_PRESC - 1); // Mind the 1 that is added in the uC !
SET_BIT( TIM1->CCMR1, TIM_CCMR1_CC1S_0);// |
// TIM_CCMR1_CC2S_0); // channel is configured as input, tim_ic1 is mapped on tim_ti1, etc...
// SET_BIT( TIM1->CCMR2, TIM_CCMR2_CC3S_0); // As above
SET_BIT( TIM1->CCMR1, TIM_CCMR1_OC2M_2 |
TIM_CCMR1_OC2M_1 |
TIM_CCMR1_OC2M_0); // PWM mode 2 - In upcounting, channel 1 is inactive as long as TIMx_CNT<TIMx_CCR1 else active.
SET_BIT( TIM1->CR1, TIM_CR1_CKD_0); // Prescaler (clk/2) for filter and deadtime
SET_BIT( TIM1->CCMR1, TIM_CCMR1_IC1F_1); // filter if needed
SET_BIT( TIM1->CR2, TIM_CR2_MMS_2 |
TIM_CR2_MMS_0); // tim_oc2refc signal is used as trigger output (tim_trgo -> itr0 for timer 8)
SET_BIT( TIM1->DIER, TIM_DIER_CC1IE); // enable interrupt on hall signal (is XOR with 2 and 3
SET_BIT( TIM1->CCER, TIM_CCER_CC1E |
TIM_CCER_CC1NP |
TIM_CCER_CC1P); // capture enable and Rising and falling edge
SET_BIT( TIM1->SMCR, TIM_SMCR_SMS_2); // reset counter and prescaler on trigger input
SET_BIT( TIM1->SMCR, TIM_SMCR_TS_2); // trigger on tim_ti1 -> tim_ti1f_ed
SET_BIT( TIM1->CR1, TIM_CR1_CEN); // enable counter timer 1
NVIC_SetPriority(TIM1_CC_IRQn, 1); // set highest priority
NVIC_EnableIRQ(TIM1_CC_IRQn); // enable interrupt
// OC1M is preploaded
// slave mod reset input bei tim_ti1f_ed
// capture/compare channel 1 is configured in capture mode, capture signal is tim_trc
initTimer8PWM();
startTimer8();
__enable_irq();
//SET_BIT(TIM1->EGR, TIM_EGR_CC1G); //force interrupt
}
Timer 8:
void initTimer8PWM(){
__HAL_RCC_TIM8_CLK_ENABLE(); // Enable clock
CLEAR_REG(TIM8->AF1); // Disable BKIN input
CLEAR_REG(TIM8->AF2);
SET_BIT(TIM8->CR1, TIM_CR1_ARPE | // ARR register is bufferd
TIM_CR1_CMS_1 // center aligned up/down (interrupt on counting up - for ADC trigger only?)
);
//TODO: check entries again for pwm
SET_BIT(TIM8->CR2, TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | // tim_oc4refc or tim_oc6refc rising edges generate pulses on tim_trgo2 for ADC trigger
TIM_CR2_CCPC | // Preload enable
TIM_CR2_CCUS);
//TIMx_ARR -1 ist max counter
WRITE_REG(TIM8->ARR, PWM_WIDTH); // Counter TOP
// Prescaler 12 for 34kHz
TIM8->PSC = 12;
WRITE_REG(TIM8->CCR1, DUTY_TO_TICS(99)); // compare value 1
WRITE_REG(TIM8->CCR2, DUTY_TO_TICS(99)); // compare value 2
WRITE_REG(TIM8->CCR3, DUTY_TO_TICS(99)); // compare value 3
WRITE_REG(TIM8->CCR4, PWM_WIDTH - ADC_TRIG_PRE_COUNT); // compare value 4 (ADC trigger)
SET_BIT(TIM8->CCMR1, TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | // pwm output compare polarity channel 1 and 2 (pwm mode 1)
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 |
TIM_CCMR1_OC1PE | TIM_CCMR1_OC2PE); // preload enable ccr 1 + 2
// Default is OUTPUT !!!
// CC1S = 0 > channel output (CC1 as OUTPUT)
SET_BIT(TIM8->CCMR2, TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | // pwm output compare polarity channel 3 and 4 (pwm mode 1)
TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 |
TIM_CCMR2_OC3PE | TIM_CCMR2_OC4PE); // preload enable ccr 3 + 4
// Timer 1 trigger out comes in on itr0 (Only trgo is possible!)
//TIM8->SMCR itr0 is default 0!
SET_BIT(TIM8->BDTR, TIM_BDTR_OSSR); // inactive state high or low
CLEAR_BIT(TIM8->CCER, TIM_CCER_CC1P);// oc1 polarity active high
CLEAR_BIT(TIM8->CCER, TIM_CCER_CC2P);// oc2 polarity active high
CLEAR_BIT(TIM8->CCER, TIM_CCER_CC3P);// oc3 polarity active high
}
Timer 1 interrupt:
void TIM1_CC_IRQHandler(){
__disable_irq();
GPIOC->BSRR = (uint32_t) GPIO_PIN_3;
lastHallIntervalTics = TIM1->CCR1; // read Capture register (resets interrupt flag) and calculate interval
// preload new CCR2 value (delay for COM -> timer -> It does actually delay +(50-75ns)!
//WRITE_REG(TIM1->CCR2, (uint32_t) (21250));// lastHallIntervalTics * 30 / 100));//US_TO_TIM1_CLOCK(100));//lastHallIntervalTics)); // Delay value for PWM change trigger
WRITE_REG(TIM1->CCR2, (uint32_t) 140);//(lastHallIntervalTics * 33 / 100));//US_TO_TIM1_CLOCK(100));//lastHallIntervalTics)); // Delay value for PWM change trigger
//if(motorRunning)
switchNextSector();
// Interrupt flag is reset by reading CCR1 capture register!
GPIOC->BRR = (uint32_t) GPIO_PIN_3;
__enable_irq();
}
