Problem configuring TC0 Channel 1 timer

Hello,

For some reason I cannot get Channel 1 of TC0 timer to work. Channel 0 works fine though so I don't understand what is happening.

Based upon checking the register it looks like the clock of channel 1 never starts running.

int RPM_update_frequency = 0;
uint32_t RPM_tick_max = 0;
float RPM_period = 0;

void InitializeTC0(void)
{
	//enable power to ID_TC0
	PMC->PMC_PCER0 = PMC_PCER0_PID27; 
	
	// set TC0 channel 0 to handle computing motor RPM
	RPM_update_frequency = 20;
	RPM_tick_max = floor((uint32_t)32000/(float)RPM_update_frequency);
	RPM_period = 1/(float)RPM_update_frequency;

	// select SLCK which operates at 32khz, and enable compare trigger
	TC0->TC_CHANNEL[0].TC_CMR =  TC_CMR_TCCLKS_TIMER_CLOCK5|TC_CMR_CPCTRG;
	// set timer to cause interrupt when timer counter reaches RC value
	TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS;
	// set period number to trigger,
	TC0->TC_CHANNEL[0].TC_RC = RPM_tick_max;
	// Start channel 0
	TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;
	
	// set TC0 channel 1 to handle sending current RPM through serial
	
	int broadcast_frequency = 0;
	uint32_t broadcast_ticks = 0;
	float broadcast_period = 0;
		
	broadcast_frequency = 1;
	broadcast_ticks = floor((uint32_t)32000/broadcast_frequency);
	broadcast_period = 1/broadcast_frequency;
		
	// select SLCK which operates at 32khz, and enable compare trigger
	TC0->TC_CHANNEL[1].TC_CMR =  TC_CMR_TCCLKS_TIMER_CLOCK5|TC_CMR_CPCTRG;
	// set timer to cause interrupt when timer counter reaches RC value
	TC0->TC_CHANNEL[1].TC_IER = TC_IER_CPCS;
	// set period number to trigger, 1 second
	TC0->TC_CHANNEL[1].TC_RC = broadcast_ticks;

	// start channel 1
	TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;

	// set priority and enable interrupt
	NVIC_SetPriority(TC0_IRQn, 4);
	NVIC_EnableIRQ(TC0_IRQn);
	
}


int encoder_1_last_position = 0;
int encoder_2_last_position = 0;

float encoder_1_RPM = 0;
float encoder_2_RPM = 0;

void TC0_Handler(void)
{
	int channel_0_status = 0;
	int channel_1_status = 0;
	int value = 0;
	
	value = TC0->TC_CHANNEL[1].TC_CV;
	
	channel_0_status = TC0->TC_CHANNEL[0].TC_SR;
	if((channel_0_status & TC_SR_CPCS) != 0)
	{
		encoder_1_RPM = 60*(encoder_1_position - encoder_1_last_position)*RPM_update_frequency; // multiplication is faster, speed_update_frequency = 1/period
		encoder_1_last_position = encoder_1_position;
	
		encoder_2_RPM = 60*(encoder_2_position - encoder_2_last_position)*RPM_update_frequency; // multiplication is faster, speed_update_frequency = 1/period
		encoder_2_last_position = encoder_2_position;
	}
	
	channel_1_status = TC0->TC_CHANNEL[1].TC_SR;
	if((channel_1_status & TC_SR_CPCS) != 0)
	{
		char buffer[200];
		int message_length;
		message_length = sprintf(buffer, "Encoder 1 RPM: %f, Encoder 2 RPM: %f \n", encoder_1_RPM, encoder_2_RPM);
		send_message(buffer);
	} 
	
}

So I tried copying the channel 0 code exactly into channel 1 and running it and it does not work. Something is wrong with channel 1 or channel 1 must be configured differently - any ideas?

I have since tried channel 2 as well and it also does not work - it appears the clocks do not get enabled. But again channel 0 works.

Timer 0 is used for millis() counter. You would have to search disable millis() to use Timer 0.

What is it you are trying to do/measure?

Hi, I am not using any arduino function calls. This is really a question about configuring the registers directly.

Not even the ones in init() that run before setup()?

This is very interesting, I set PMC to enable TC1 and TC2 as well and now it appears the channel 1 works, which makes zero sense.

My understanding is the millis() timer is setup by default and running even if you don't use it.

For all my successful timer use I went to the Atmel datasheet and setup the timer registers for my needs.
IMHO for detailed control like this, I don't understand / trust the built in functions of the IDE to get what I want.

I am directly controlling the registers. Interestingly, if I change TC0 to TC1 everything breaks again and the TC1 handler does not get called.

There's obviously something wrong but I don't know what it is.

Ok I think I figured it out.

Basically there is an odd mix of naming conventions. TC0 and TC1 are both within a single timer_counter module but each have their own interupt and power control. I didn't think this was the case because of the channel_number structure associated with TC0 which I do not understand at this point.

But, not starting with a clean slate - they've already been tampered with before setup() runs. I don't know if you are using setup() and loop() because you didn't post your entire sketch. But you can not assume that all the register values are in the reset default state. That means, to be safe, you really have to write them all, or know which ones are modified in init().

I am not using any of the functions provided by arduino framework, atmel IDE provides a minimal main function which initializes system clock and sets flash speed - this is all I use.

Okay.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.