Go Down

Topic: 8/16bit timer Konfiguration ? (Read 661 times) previous topic - next topic

hoboPowa

Nov 20, 2012, 09:00 pm Last Edit: Nov 21, 2012, 04:49 pm by hoboPowa Reason: 1
hy,
hab die Tage wieder einmal den arduino (mit ATmega328P) in die Hand genommen und wollte ein paar Timer durch Bit-Manipulation konfigurieren, so dass diese 1s abzählen. Ausgabe durch umschalten (an <=> aus) von angeschlossenen LED's. Ich hatte jedoch nicht sehr viel Erfolg; allgemeines C-Beispiel zB 8bit timer (1s Zählzeit)  
=> mein Arduino schaltet erst nach ca 2sek. anstatt nach einer...
Arduino spezifisch hab ich bisher nicht wirklich etwas hilfreiches gefunden  :~
Von daher schaut bitte über meine Programme und erklärt was falsch ist. Wahrscheinlich hab ich irgendwelche grundlegenden, arduino-spezifischen Einstellungen/Regeln/Größen nicht beachtet.
die 3 Timer:
Code: [Select]

//---------------- 8bit-Timer, abzählen einer Sekunde ---------------- //
int counter = 0;

void setup(){
  DDRD = 0xFF;
  PORTD = 0x00;
  DDRB = 0x3F;
  PORTB = 0x00;
  // Ausgänge, alle auf 0
  TCCR2A  = (1 << WGM21);
  // CTC- Mode; Clear Timer on Compare Match
  TCCR2B |= ((1 << CS22) | (1 << CS21) | (1 << CS20));
  // prescaler: in diesem Fall clockspeed von 16MHz / 1024 = 15625Hz für den timer
  OCR2A = 125;
  // 15625 / 125 = 125 => nach 125 durchläufen ist eine Sekunde vorbei
  TIMSK2 = (1 << OCIE2A);
  //Compare A Match Interrupt Enable für timer2/counter2
  // Vergleichswert = 125, Interrupt wird ausgelöst wenn TCNT2 = OCR2A
  SREG = (1 << 7);             
  // interrupts enabled
}

void loop(){
  while(1){
    delay(1000); // überprüfen des Timers
    PORTB = ~PORTB;  //leds werden an bzw aus geschaltet (an <=> aus)
  }
}

ISR(TIMER2_COMPA_vect){
  if(counter <= 125){
    counter++;
  }
  else{
    counter = 0;
    PORTD = ~PORTD;
  }
}
   
// Ergebniss: ca 1s , aber nach 10s schon abweichung von +0,5s => da bei jedem durchlauf ISR zusätzlich Takte "hinzufügt" ?


//-----------------------------------------------------------//
//-----------8bit-Timer, abzählen einer Sekunde -------------//

int counter = 0;
void setup(){
  DDRD = 0xFF;
  PORTD = 0x00;
  DDRB = 0x3F;
  PORTB = 0x00;
  // Ausgänge, alle auf 0
  TCCR2B |= ((1 << CS22) | (1 << CS21) | (1 << CS20));
  // prescaler: in diesem Fall clockspeed von 16MHz / 1024 = 15625Hz für den timer
  TIMSK2 = (1 << TOIE2);
  //overflow Interrupt Enable für timer2/counter2
  SREG = (1 << 7);             
  // interrupts enabled
}

void loop(){
  while(1){
    delay(1000);     
    PORTB = ~PORTB; 
    // überprüfung, ob Timer stimmt
  }
}

// Takt = 15625Hz geteilt durch 256 = 61,04 => nach rund 61 durchläufen ist eine Sekunde vorbei ?!
ISR(TIMER2_OVF_vect){ 
  if(counter <= 61){
    counter++;
  }
  else{
    counter = 0;
    PORTD = ~PORTD;
  }
}
   
// Ergebniss : ungefähr 2s sind die LED's and, 2s aus usw Warum?


//-----------------------------------------------------------//
//-------------- 16bit Timer, abzählen einer Sekunde --------//
int counter = 0;

void setup(){
  DDRD = 0xFF;
  PORTD = 0x00;
  DDRB = 0x3F;
  PORTB = 0x00;
  // Ausgänge, alle auf 0
  SREG = (1 << 7);             
  // global interrupts enabled
  TCCR1B  |= ((1 << CS12) | (1 << WGM12));
  //prescaler: in diesem Fall 16MHz /256 = 62500Hz für den timer // CTC- Mode => zählen bis vergleichswert, automatisch zurückgesetzt
  TCNT1 = 0;
  OCR1A = 0b1111010000100100;
  // Vergleichswert = 62500 , Interrupt wird ausgelöst wenn TCNT1 = OCR1A
  //62500 Takte werden gezählt mit Frequenz von 62500Hz => eine sekunde vorbei(?), durch interrupt werden leds an (für 1s) bzw ausgeschaltet (für 1s) => theoretisch
  TIMSK1 = (1 << OCIE1A);  //Output Compare A Match Interrupt Enable setzten
  // spielt die Reihenfolge der Bit-Manipulation eine Rolle ?
}

void loop(){
  while(1){
    delay(1000);
    PORTB = ~PORTB;
    //zum vergleich, ob der timer 1s abzählt
  }
}

ISR(TIMER1_COMPA_vect){ 
  PORTD = ~PORTD;  // schaltet LEDS ein und aus
}

/* => ERGEBNIS : LED's bleiben dauerhaft aus
                 Fehler ?
      mit prescaler /64 sind die leds dauerhaft an (zu schnelles schalten für menschliches Auge ?!)
*/ 

habe versucht alle Schritte gut zu erklären.
Daten-Blatt: atmega328P

Vielen Dank für eure Hilfe

pylon

Soll die Arduino-Umgebung weiterhin funktionieren? Dann darfst Du Timer0 nicht verwenden, der ist für millis() und delay() verantwortlich.

Dein C-Beispiel ist für einen mit 4 MHz getakteten ATmega geschrieben, läuft auf dem Timer0 und verändert den Prescaler. Willst Du das wirklich?

pylon

Wenn's Timer1 sein kann, dann könnte Dich der folgende Code glücklich machen:

Code: [Select]

void setup() {
  TCCR1B = 0x0D; // CTC1 | Prescaler 1024
  OCR1AH = 15625 >> 8;
  OCR1AL = 15625 & 0xFF;
  TIMSK1 |= OCIE1A;
}

void loop() {
}

ISR(TIMER1_COMPA_vect) {
  // executes every second
  // attention: interrupt context
}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy