ATTINY406 Timer and delay weirdness

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

Hello

 

I recently decided to try a project with one of the newer ATtiny microcontrollers, in particular with the ATtiny 406. Basically just measuring a voltage and displaying it onto a few 7-segment-displays

But I am facing a weird issue with it, and despite reading for hours into the datasheet, I couldn't find what I did wrong.

 

The TCA0 Timer (16bit) is creating a interrupt far faster than it should be able to. I don't modify the counter and just want it to count it's whole range up to the TOP, which should take ~3ms for it.

But instead, I get a TCA0_OVF every ~15uS. The quite opposite problem seems to happen with _delay_ms, where it takes significant longer than it should.

 

I am using the latest version of Atmel Studio 7 on Windows 8.1, the DevicePackManager got updated ~3weeks ago.

 

#define F_CPU  20000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

/* Timer runs way to fast, changing prescaler has no effects 
 * Calculations how it should be: 1/20000000UL -> 50ns
 * 50ns * 2^16 (65536) -> LED Toggle every ~3.2768ms
 * Reality: Toggle every 15 us - but why???					*/
ISR(TCA0_OVF_vect)
{
	TCA0.SINGLE.INTFLAGS	= 0;
	TCA0.SINGLE.CNT 		= 0;
	PORTB.OUTTGL = (1<<2);	// PB2
}

void init();
int main(void)
{
	init();	
	sei();
    while(1) 
    {
		/* Expected LED Toggle 4 times a second
		   Reality: Takes a half minute until the LED gets toggled */
		_delay_ms(250);
		PORTB.OUTTGL = (1<<1);	// PB1
    }
}

void init()
{
	PORTB.DIR = 0x06;		// Set PB1 & PB2 to be an Output
	
	CCP = 0xD8;				// Configuration Change Protection
	CLKCTRL.MCLKCTRLB = 0;	// Change of the Oscillator Prescaler
							// Prescaler off -> f = 20MHz
	
	TCA0.SINGLE.PER 	= 0xFFFF;	// Setting upper limit
	TCA0.SINGLE.CTRLA	=	0x01;	// Turn timer on, 1024 Prescaler
	TCA0.SINGLE.INTCTRL	=	0x01;	// Turn Overflow-Interrupt on
	TCA0.SINGLE.CNT		= 0x0000;	// Set counter to 0
	
}

I really can't see where I've failed.

This topic has a solution.
Last Edited: Fri. Jan 11, 2019 - 12:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like the CCP / prescale change may not be happening. Is there some reason you aren't using _PROTECTED_WRITE() ?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The INTFLAGS bit is cleared to 0 by writing 1.
Otherwise interrupt handling will be repeated many times.

 

_delay_ms is built on the premise that interrupt processing does not occur.
If interrupt processing is done here, that time will extend.

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

Couldn't find _PROTECTED_WRITE() on AS7, so it seems to be not supported (yet?) there for the new tinys. The clock is set correctly, which I checked by a free-running LED in the while-loop and an Oscilloscope.

 

The problem really was with the INTFLAGS. I am used from the "classic" AVRs that the flags are cleared by the hardware and not by myself.

 

Thank you both for you help, my problem is solved and I learned more about AVR.

Last Edited: Fri. Jan 11, 2019 - 12:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

_PROTECTED_WRITE is included in xmega.h, but you can use it without including it intentionally.
Of course, it works also in the tiny0 series.