Go Down

Topic: ATTiny85 and 84, and the timer(s), porting code from ATMega328. (Read 3811 times) previous topic - next topic

random_hacker

Hello,

I have the following timer code, and I'd like to have it work on my shiny new ATTiny processors (I have both the ATTiny85, and ATTiny84).

I don't fully understand how timers are set up, so I ended up copy/pasting some code which worked perfectly well on the ATMega328, but isn't compiling for the ATTiny85.
The code I currently have is:
Code: [Select]

#include <avr/interrupt.h>
#include "LedMatrix.h"
// LedMatrix.h defines Display.nextScanLine() and SCAN_LINE_FREQUENCY

  void startTimer() {
    cli();           // disable all interrupts

    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;

    OCR1A = 62500/(SCAN_LINE_FREQUENCY);     // compare match register.
    TCCR1B |= (1 << WGM12);   // CTC mode
    TCCR1B |= (1 << CS12);    // 256 prescaler
    TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt

    sei();             // enable all interrupts
  }



  ISR(TIMER1_COMPA_vect) {
    Display.nextScanLine();
  }

The error messages I'm getting are:

LedMatrix.cpp:57: error: 'TCCR1A' was not declared in this scope
LedMatrix.cpp:58: error: 'TCCR1B' was not declared in this scope
LedMatrix.cpp:62: error: 'WGM12' was not declared in this scope
LedMatrix.cpp:64: error: 'TIMSK1' was not declared in this scope

So, it appears to me that setting up a timer isn't the same in both systems.  I don't mind using  #ifdef blocks to differentiate the codebase, but I'm not sure what to put into the ATTiny's block.

Any help is appreciated, including pointers to relevant documentation or tutorials.


random_hacker

I was using a tutorial on how to program a attiny using the Arduino 1.0.1:  http://hlt.media.mit.edu/?p=1695

The core files they said to use came from https://github.com/damellis/attiny/zipball/Arduino1

I'm selecting the "ATTiny85 (8MHz internal)" board from the menu.

If there is a better way, I'm all for it.

random_hacker

Also, it appears this compiles fine with the ATTiny84, only the with 85 select it doesn't compile.

I'm also thinking that I may need to use the 84 anyway, as my project needs a minimum of 6 output pins, and I don't want to have to mess with disabling reset right now.

Coding Badly

If there is a better way, I'm all for it.


I think this one is better...
http://code.google.com/p/arduino-tiny/
http://arduino.cc/forum/index.php?topic=8878.0
http://arduino.cc/forum/index.php?topic=51984.0

If you do decide to use the Tiny Core bear in mind that, by default, timer 1 is used for the time functions (millis, micros, etcetera) with the ATtiny85 processor.  There is a compile time switch to use timer 0 instead.

Coding Badly

Also, it appears this compiles fine with the ATTiny84, only the with 85 select it doesn't compile.


I remember timer 1 being identical on the ATmega328 and ATtiny84 processors.  That is definitely the shortest path solution.  Timer 1 on the ATtiny85 is very different than any of the other AVR timers you will encounter.

Quote
I'm also thinking that I may need to use the 84 anyway, as my project needs a minimum of 6 output pins, and I don't want to have to mess with disabling reset right now.


Does that mean you no longer need help?

random_hacker


I think this one is better...
http://code.google.com/p/arduino-tiny/
http://arduino.cc/forum/index.php?topic=8878.0
http://arduino.cc/forum/index.php?topic=51984.0

Okay, I'll check it out, thanks.


If you do decide to use the Tiny Core bear in mind that, by default, timer 1 is used for the time functions (millis, micros, etcetera) with the ATtiny85 processor.  There is a compile time switch to use timer 0 instead.

Okay, thanks for the heads up.  Do you remember where you saw that, so I can look up the details?



Also, it appears this compiles fine with the ATTiny84, only the with 85 select it doesn't compile.


I remember timer 1 being identical on the ATmega328 and ATtiny84 processors.  That is definitely the shortest path solution.  Timer 1 on the ATtiny85 is very different than any of the other AVR timers you will encounter.


Okay, can you point me to more information on that? Like I said, I originally just copy-and-pasted some code that worked, I'd like to understand it a bit more, and then I'd like to understand how to utilize the timer on ATTiny85.  I have a lot of experience with reading and understanding technical docs, as long as I know what docs to look at :-)

Quote
I'm also thinking that I may need to use the 84 anyway, as my project needs a minimum of 6 output pins, and I don't want to have to mess with disabling reset right now.


Does that mean you no longer need help?

I always need help :-)  As a matter of fact, the ATTiny84 doesn't seem to be running my interrupt, so the timer set up code as-is doesn't work (it compiles just fine, but that doesn't mean much).

Thanks for all the suggestions guys, I appreciate it.

Jance

#7
Aug 28, 2012, 06:31 am Last Edit: Aug 28, 2012, 07:02 am by Jance Reason: 1
Were you ever able to get interrupts to work with the ATTiny84? I'm running into the exact same problem- I can't get a simple CTC interrupt to trigger (for a clock-like application). The blink sketch works on the ATTiny84, but switching to interrupts with a similar sketch to yours compiles, but the ISR routine never fires.  :smiley-sad-blue:

I'm unsure if this is a problem with the Arudino IDE, or the damellis-attiny-6bff522 hardware files, but the datasheet seems to suggest the same registers as the AtMega328p, except with different register addresses.

I feel bad that I'll have to use a practically under used AT328p for this project when the AtTiny84 has the right amount of resources I need.

Thanks.

----= UPDATE =----
I got it to work by reading this related thread: http://arduino.cc/forum/index.php/topic,97048.0.html
Note the ISR vector- it's different. TIM1_COMPA_vect  vs TIMER1_COMPA_vect

NON-WORKING CODE: (from http://letsmakerobots.com/node/28278, which works on Arduino, but not the ATTiny84 as mentioned above)
[font=Verdana]/* Arduino 101: timer and interrupts
  1: Timer1 compare match interrupt example
  more infos: http://www.letmakerobots.com/node/28278
  created by RobotFreak
*/

#define ledPin 0

void setup()
{
 pinMode(ledPin, OUTPUT);
 
 // initialize timer1
 noInterrupts();           // disable all interrupts
 TCCR1A = 0;
 TCCR1B = 0;
 TCNT1  = 0;

 OCR1A = 31250;            // compare match register 16MHz/256/2Hz
 TCCR1B |= (1 << WGM12);   // CTC mode
 TCCR1B |= (1 << CS12);    // 256 prescaler
 TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
 interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
 digitalWrite(ledPin, digitalRead(ledPin) ^ 1);   // toggle LED pin
}

void loop()
{
 // your program here...
}
[/font]

WORKING CODE:
#define ledPin 0

void setup()
{
 DDRA  = 0xDF;
 PORTA = 0x20;
 DDRB  = 0xFF;
 PORTB = 0xFF;

 noInterrupts();        
 TCCR1A = 0;
 TCCR1B = 0;
 TCNT1  = 0;
 OCR1A = 11250;            
 TCCR1B |= (1 << WGM12);  
 TCCR1B |= (1 << CS12);  
 TIMSK1 |= (1 << OCIE1A);  
 interrupts();
}

ISR(TIM1_COMPA_vect) // timer interrupt
{
 digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}

void loop()
{
 // main code
}

random_hacker

Yes, I got my code to work, after trying a few things.  I think the biggest difference is I set "TCCR1C = 0;" in my init.  Also, (as your code has it), the interrupt vector name is TIM1_COMPA_vect, not TIMER1_COMPA_vect.  Confusing, inconsistant, and unfortunate.

Code: [Select]

  void startTimer() {
    cli();           // disable all interrupts

    TCCR1A = 0;
    TCCR1B = 0;
    TCCR1C = 0; // ***THIS LINE ADDED***
    TCNT1  = 0;

    OCR1A = (F_CPU/PRESCALER)/(SCAN_LINE_FREQUENCY);     // compare match register.
    TCCR1B = (1 << WGM12) | (4 << CS10);    // CTC mode and 256 prescaler
    TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt

    sei();             // enable all interrupts
  }


  ISR(TIM1_COMPA_vect) { // *** THIS LINE CHANGED ***
    Display.nextScanLine();
  }


My actual project has #if's for the 84 specific stuff, so my source works for both ATTiny84 and ATMega328.  The one thing I didn't realize is my code is running at  8MHz now, and my ISR takes up a large portion of the processing time now.  I ordered some 20MHz crystals and some caps, so hopeful my code will run even faster than the Arduino version.

Go Up