Timer and Interrupts for ADC- help requested

Go To Last Post
5 posts / 0 new
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

int main (void)
	uint8_t IQsamples[75];
	int j;
	// ADC IP registers address
	volatile avr32_adc_t *adc = &AVR32_ADC;
	// Set functions to peripherals
	// Set PLL0 as Main Clock
	// USART options.
	static const usart_options_t USART_OPTIONS =
		.baudrate     = 115200,
		.charlength   = 8,
		.paritytype   = USART_NO_PARITY,
		.stopbits     = USART_1_STOPBIT,
		.channelmode  = USART_NORMAL_CHMODE
	// Configure ADC	
	AVR32_ADC.mr |= 0x6 << AVR32_ADC_MR_PRESCAL_OFFSET;   //4.6 MHz 
	// Enable the I/Q ADC channels.
	#if defined(I_CHANNEL)
	adc_enable(adc, I_CHANNEL);
	#if defined(Q_CHANNEL)
	adc_enable(adc, Q_CHANNEL);
	//Initialize USART in RS232 mode
	usart_init_rs232(USART, &USART_OPTIONS, FOSC0*2);
	int k;
	while(1){//while 1
				//launch conversion on all channels
				// Acquire the I/Q channels
				Isample = adc_get_value(adc, I_CHANNEL);
				Qsample = adc_get_value(adc, Q_CHANNEL);
				// Creating byte 1
				temp2 =((Isample & 0x00000300) << 5 );
				temp1=(temp1 | temp2);
				temp1= ((temp1 | 0x1000) >> 8  );
				temp2=((Isample & 0x000000F0) >> 4);
				IQsamples[k] = (uint8_t)(temp1 | temp2);
				//IQbuff[74] =  (char)(temp1 | temp2);;
				// Creating byte 2
				temp1 =((Isample & 0x0000000F) << 4 );
				temp1= (temp1 | 0x08);
				temp2= ((Qsample & 0x380) >> 7);
				IQsamples[k+1] = (uint8_t)(temp1 | temp2);
				//IQbuff[k+1] = (char)(temp1 | temp2);
				// Creating byte 3
				temp2= ((Qsample & 0x7F));
				IQsamples[k+2] = (uint8_t)(temp1 | temp2);
			cpu_delay_us(4000, 4*BOARD_OSC0_HZ);
			cpu_delay_us(1000000, 4*BOARD_OSC0_HZ);
			//Write samples in port serial
			usart_write_line(USART, IQsamples);

I have exhausted all options to find a means of doing accurate sampling/data transfer with the above code snippets. Many suggestions from this forum have been to use interrupts and timers which are quite new to me. No much examples/tutorials for the particular chip (AT32UC3), and I am just on the verge of giving up. Please help me.


My need is to introduce timers/interrupts in the code above to achieve a sampling frequency of 250Hz. This looks to me that the original code was doing with cpu_delay_us(4000, 4*BOARD_OSC0_HZ); but this does not seem to do it properly. Please feel free to modify/add/edit this code with lines showing the use of timers/interrupts.


I am willing to learn more, and will like to see sample codes or example tutorials on how to generally use timers/interrupts in data transfer and adc. Please provide me with necessary links and samples.



  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Most of us would just knuckle down and read the datasheet. That’s what we did before the interwebs. Sorry to sound harsh, but that’s the situation. You’ve chosen to use a part that is not very popular.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0



There is a project that uses ADC and USART, but for different mcu, its for ATTINY series 1 & 0. the project you can find it on start.atmel.com, although its not the same but I believe it gives you a good hint on how to proceed.


And here is the documentation. the project uses Timers / RTC, ADC and USART.








  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

obabarin wrote:
cpu_delay_us(4000, 4*BOARD_OSC0_HZ);


if you want to get the precise delay time, the alternative for F_CPU for this chip, there is plenty of info on this forum about this issue.



  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I understand your logic, your do 25 sample-process-store-delay operations which is then followed by a 1 second delay and a transmission of 75 bytes.
The cpu_delay_us(4000, 4*BOARD_OSC0_HZ); limits your sampling rate to a maximum, I repeat, a maximum of 250 Hz because all the sample-process-store operations before that time-delay will consume cpu time.
How much cpu time ?, well that depends on the compile-options that you are using.
You can measure the loop-time (with an oscilloscope or logic-analyzer) by toggling an I/O pin inside the //for2 loop.
You then reduce the cpu_delay_us(4000, 4*BOARD_OSC0_HZ); time-delay to get nearer to your desired 250 Hz sample rate.


A timer can reduce the need for such manual tweaking but your desired rate might not be achievable exactly because of the timer-clock prescaling and your system-clock frequency.

I had to go back through all your previous posts and I think (guess) that FOSC0*2 is 32 MHz.

So, we need to divide the PBA clock by 128000 to get 250 Hz.
The Timer/Counters are 16 bits and the 'best' prescaler is 2 which will increment the TC at a 16 MHz rate,  hence the compare value for the RC register in the timer would be 64000.

The TC should be configured for waveform mode and 'UP mode and automatic trigger on RC compare'.

Now., do you use interrupts or polling ?

- Interrupts require configuring the INTC module and writing an interrupt-handler.

- Polling would check the TC status-register for a compare.



usart_write_line(,) sends the bytes from the buffer that you give it until a null, (zero), byte is found., which means that you have 2 potential problems ;

1) if one of your 75 data-bytes is zero, you will not receive 75 data bytes at the other end.

2) you are assuming that what is in IQsamples[75] (one byte after the actual end of that array) is zero. That is not guaranteed.