cancel
Showing results for 
Search instead for 
Did you mean: 

Delay of interfacing timer is rather inconsistent

Tobe
Senior III

I have implemented a hallinterface (tim 1), to update my pwm timer (tim 8). But the delay i set is rather fluctuating.

Disabling interrupt inside of the tim 1 interrupt did not help. And i think, outside of the interrupt it should not matter, since this is only hardware that is not influenced by software really? At least i would not think that it should fluctuate in a scale of about 2us.

 

Init of interfacing 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->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
}

 

 

Init of timer 8 for pwm:

 

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

	// TODO: Prescaler TIMx_PSC

	WRITE_REG(TIM8->CCR1, DUTY_TO_PWM(99));	// compare value 1
	WRITE_REG(TIM8->CCR2, DUTY_TO_PWM(99));	// compare value 2
	WRITE_REG(TIM8->CCR3, DUTY_TO_PWM(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;
	TIM1->CNT = 0;
	//GPIOC->BSRR = (uint32_t) GPIO_PIN_3;
	// read Capture register (resets interrupt flag)
	unsigned long captValue = TIM1->CCR1;
//	captValue = TIM1->CCR2;
//	captValue = TIM1->CCR3;
	lastHallIntervalTics = captValue - lastHallSignalTics;	// calc interval
	lastHallSignalTics = captValue;





	// set (preload) new pwm
	// set new CCR2 value (delay for COM -> timer 8)
	// It does actually delay +(50-75ns)!
	WRITE_REG(TIM1->CCR2, 	US_TO_TIM1_CLOCK(10));//lastHallIntervalTics));	// Delay value for PWM change trigger


	//if(motorRunning)
		switchNextState();

	//SET_BIT(TIM8->EGR, TIM_EGR_COMG); // update
	//printBin(0x48);


	//print("TIM1_CC_IRQHandler");
	//while(1);
	// Tim8?? CLEAR_BIT(TIM8->SR, TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF); 	// Clear any int flags
	// Interrupt flag is reset by reading CCR1 capture register!
	GPIOC->BRR = (uint32_t) GPIO_PIN_3;
	__enable_irq();
}

 

 

Timer 1 prescaler (APB2 85Mhz):

 

#define TIM1_PRESC 200	// - 1 is subtracted later!

#define NS_TO_TIM1_CLOCK(ns) (85*ns/TIM1_PRESC/1000)
#define US_TO_TIM1_CLOCK(us) (85*us/TIM1_PRESC)

 

 

Interrrupt timer 8 (should not matter in this case i tihnk):

 

void TIM8_TRG_COM_IRQHandler(){
	GPIOC->BSRR = (uint32_t) GPIO_PIN_3;
	if(! (TIM8->SR & TIM_SR_COMIF)){	// Return if no flag is set (prevents false triggers because of latency in the bus)
		__ASM volatile ("NOP");
		__ASM volatile ("NOP");
		GPIOC->BRR = (uint32_t) GPIO_PIN_3;
		return;
	}


	TIM8->SR = ~TIM_SR_COMIF;	// DONT send "&=" ReadModifyWrite is bad!
	__ASM volatile ("NOP");
	__ASM volatile ("NOP");
	GPIOC->BRR = (uint32_t) GPIO_PIN_3;
}

 

 

Please find attached the curves:

Yellow curve: First pulse is of timer 1 interrupt. Second + third is Interrupt of timer 8.

Red and blue curve: Outputs of timer 8

Green line: input of timer 1 input cpature

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tobe
Senior III

While writing this topic, i found the issue myself: The prescaler counter had to be reset too:

TIM1->EGR = TIM_EGR_UG;	// reset prescaler counter (through update event)

View solution in original post

1 REPLY 1
Tobe
Senior III

While writing this topic, i found the issue myself: The prescaler counter had to be reset too:

TIM1->EGR = TIM_EGR_UG;	// reset prescaler counter (through update event)