cancel
Showing results for 
Search instead for 
Did you mean: 

G431RBT6 - Interfacing timer and compare output timer have rather fluctuation timings

Tobe
Senior III

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();
}

 

 

 

 

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tobe
Senior III

Found the culprit:

The internal oscillator has these fluctuations. Enabling the external shows way less fluctuations.

View solution in original post

4 REPLIES 4

I don't see how is TIM8 bound to TIM1.

Instead of code, it might be more useful to show registers content.

Using prescaler in TIM8 may be one source of jitter. The many sources of latency of interrupts and code executed there, is another (try avoiding interrupts/softwer for sub-microsecond measurements).

JW

In the timer 1 interrupt, preload registers for timer 8 are set with "switchNextSector();".

Timer 1 CCR2 does set of a trigger event that goes to itr0 of timer 8. Timer 1 is set  to have its counter and prescaler reset when an trigger occours on the interrupt lines, so from there should be not jitter.

Timer 8 has itr0 as default: (TIM8->SMCR itr0 is default 0!)

A COM event is generated at tim_trgi as stated in the manual at page 1134:

COM can be generated by software by setting the COM bit in the TIMx_EGR register or by hardware (on
tim_trgi rising edge).

Currently i cant not give register details, since i got a measurement running.

Tobe
Senior III

I got the registers now from it:

Edit:
I have now activated the external oscillator, and deactivated the internal. Watching at it with persistant mode and the cursors does not show any improvement.

Maybe the PLL circuit is introducing some fluctuations?

Tobe
Senior III

Found the culprit:

The internal oscillator has these fluctuations. Enabling the external shows way less fluctuations.