Pages: [1]   Go Down
Author Topic: ATTiny85 and 84, and the timer(s), porting code from ATMega328.  (Read 3246 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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.
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12777
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Which core are you using?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12777
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 200
Posts: 12777
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
/* 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...
}


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
}
« Last Edit: August 28, 2012, 12:02:27 am by Jance » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
  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.
Logged

Pages: [1]   Go Up
Jump to: