mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR ATMega16 Timer Interrupt funktioniert, scheint aber den uC zu reseten


Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, wollte mir vl mal ne uhr oder so bauen,
aber der code soll bisjetzt blos einen ausgang dauerhaft blinkenlassen,
und mit interrupt nach 1s einen anderen ausgang dauerhaft einschalten.

Jetzt hab ich das Problem, das der eine zwar dauerhaft blinkt,
aber der andere der nach einer sekunde dauerhaft an sein soll
erst nach ca 8s. mal kurz blinkt, und dann wieder nach ca.8s ....
#include <inttypes.h>                    
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>

// Initialisierung vom Timer1
void init_timer_1(){
TCCR1A = 0x00; // PWM ausgeschaltet, Es gibt kein signal nach ausen
TCCR1B = (1<<3)|(1<<2)|(0<<1)|(0<<0); //3 = bei erreichen des vergleichwertes auf 0 setzen 2-1-0 = 100= teiler auf 256 010=8
OCR1AH=0x7A; //höherwertiges bit des vergleichwertes //es wird bis 31250 gezählt, (8Mhz/256)=1s
OCR1AL=0x12; //niederwertiges bit der vergleichwertes
TIMSK = 0xff;//(1<<6)|(1<<7);//Interupt bei compare enable
}// init_timer_1


ISR(TIMER1_COMPA_vect) {//Timerinterupt 
    PORTD|=(0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7);
    //sollte ausgang PD6 dauerhaft ein schalten
}//Timerinterupt TIMER1_COMPA_vect


int main (void)
{
DDRD = (0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (0 << 7); //festlegen der ein0/ausgänge1
PORTD = 0; //alle ausgänge des PortD sind auf 0

init_timer_1();//Timer 1 Initialisieren
sei(); //interupts aktivieren

     while(1)
     {
             //einen ausgang immer abwechselnd ein/aus schalten
             if(bit_is_set (PORTD,5)){
                PORTD&=(1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (1 << 6) | (1 << 7); 
           }else{
                 PORTD|=(0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (0 << 7);
          }    
     }           
      return 0;             
}


Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich betreibe den ATMega16 auf dem Pollin Ev.Board
Quarz=8Mhz;
Compiliere mit WinAVR
Übertrage mit Ponyprog
Fusebits: BOTSZ1, BOTSZ0, SUT0, CKSEL3, CKSEL2, CKSEL1 (haben alle 
hacken)

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

1. Deine Fusebits dürften der Auslieferungszustand sein, also läuft der 
Mega16 mit 1MHz intern.

8MHz externer Quarz wäre CKSEL3...0 auf 1, also bei Pony Haken raus.

2. Sind Deine LED zwischen Ausgang und GND oder zwischen Ausgang und + 
angeschlossen?

Die &-Verknüpfung in der While-Schleife macht vermutlich nicht, was Du 
erwartest.

Gruß aus Berlin
Michael

Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, sie waren noch im Auslieferungszustand, hab jetzt die hacken raus,
es sind jetz nur noch die hacken bei
Fusebits: BOTSZ1, BOTSZ0, SUT0
drin.

Meine LED sind zwischen Ausgang und GND => müssten bei ausgang HI 
leuchten

Die & verknüpfung in der whileschleife...
soll rücksetzen wenn ausgang aktiv, und setzen wenn inaktiv,
(das scheint sie auch zu machen, nur halt so schnell das man es nicht 
sieht)


Jetzt ist nur noch das Problem das der Ausgang den der Timerinterupt
setzen soll nur ganz kurz aufblinkt

Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal wie in einem anderen Thema empfohlen einen Kondensator 
zusätzlich nahe am uC angeschlossen (+->GND) hilft aber auch nichts

Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hilfe !!!
Weis denn keiner eine Antwort ?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe deine Fragestellung nicht ganz und müsste mich erst 
durchkämpfen.

EDIT: Hier wurde ein Teil gelöscht. Der falsche Takt wurde bereits 
festgestellt. Anpassung der folgenden Vermutungen dazu spare ich mir ;-)

Die Analyse eines Timer-Codes ist IMHO ja müssig, wenn der µC mit einem 
anderen als dem erwarteten Takt rennt.

OK, soweit bin ich

#include <inttypes.h>                    
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>

// Initialisierung vom Timer1 
// als Clear Timer on Compare Match (CTC) Mode 
// (Mode 4 Tabelle 47 Atmega16 Datenblatt)
void init_timer_1()
{
  // PWM ausgeschaltet, Es gibt kein Signal nach aussen
  TCCR1A = 0x00; 

  // Bit
  // 3     : bei Erreichen des Vergleichwertes auf 0 setzen 
  // 2-1-0 : 100 : Teiler auf 256 
  //         010 :              8
  TCCR1B = (1<<3) | (1<<2); // Teiler 256

  /*  
    To do a 16-bit write, the High byte must be written 
    before the Low byte. 

    For a 16-bit read, the Low byte must be read before 
    the High byte.
  */

  // Höherwertiges Bit des Vergleichwertes 
  // es wird bis 31250 gezählt, (8 Mhz / 256) = 1 s
  OCR1AH = (31250 & 0xFF00) >> 8; 

  // Niederwertiges Bit des Vergleichwertes
  OCR1AL = 31250 & 0x00FF; 

  //Interupt bei Compare enable
  TIMSK = 0xff; //(1<<6)|(1<<7);
}


//Timerinterupt TIMER1_COMPA_vect
ISR(TIMER1_COMPA_vect) 
{
  // Ausgang PD6 dauerhaft einschalten
  PORTD |= (1 << 6); // PD6 HIGH
} 


int main (void)
{
  // Pin 5 und 6 Ausgänge, Rest Eingänge (unbenutzt)
  DDRD = (1 << 5) | (1 << 6); 

  // alle Ausgänge des PortD sind auf 0 (LOW)
  PORTD = 0; 

  init_timer_1(); // Timer 1 initialisieren
  sei();          // Interupts global aktivieren

  while(1)
  {
    // Ausgang an Pin 5 abwechselnd ein/aus schalten
    PORTD ^= (1 << 5); // PD5 toggeln mit XOR
    
    // 1s = 1000 ms warten 
    // 1000 setzt aktuelle avr-libc voraus s. Doku
    _delay_ms(1000);
  }           

  return 0;             
}


Du siehst, ich habe die Bitfummeleien (für mich) lesbarer geschrieben. 
Aus deiner Beschreibung und dem Originalcode ist mir nicht klar, was du 
bei welcher LED bzw. Pin du beobachtest.

Deine while(1) Hauptschleife wechselt quasi ohne Wartezeiten PD5. Noch 
extremer in meinem Umschrieb mit dem Toggeln ohne Abfrage. Ich würde 
erwarten, dass man mit dem Auge kein Blinken beobachten kann.

Deshalb habe ich in der umgeschriebenen Source ein 1s Warten 
hinzugefügt. Eine LED PD5 sollte mit 1s hell/1s dunkel blinken, wenn 
F_CPU + Fuses + Taktquelle stimmen und mit Optimierung übersetzt wurde.

Ein langsameres Blinken wäre ein Zeichen für falschen Takt. Kein Blinken 
ein zeichen für Fehler in der Schaltung und/oder beim Programmieren.

Die ISR(TIMER1_COMPA_vect) sieht OK aus.

Bei der init_timer_1() war ich gerade dran, deine Bitnummern und 
Hexwerte mit dem Datenblatt zu vergleichen und Kommentare zu dem 
einzufügen, was ich meine, was du machen willst.

Für mich lesbarer habe ich das Setzen des Compare-Wertes geschrieben und 
ich habe die Reihenfolge des 16-Bit Register-Schreiben gecheckt.

Bin aber noch nicht fertig. Verdächtig ist mir die Zeile

> TIMSK = 0xff; //(1<<6)|(1<<7);

denn das würde bedeuten

 TICIE1    Timer 1 Input Capture Interrupt Enable
 OCIE1A    Timer 1 Output Compare A Match Interrupt Enable
 OCIE1B    Timer 1 Output Compare B Match Interrupt Enable
 TOIE1     Timer 1 Overflow Interrupt Enable

Und da 3 von 4 Interruptroutinen fehlen... rattert der µC wohl in den 
Reset. Nach dem Reset wird der Anfang von main() wieder durchlaufen, 
d.h. PD5 und PD6 in "Grundstellung".

Wenn die LED an PD6 diese ist:

> der andere der nach einer sekunde dauerhaft an sein soll erst nach
> ca 8s. mal kurz blinkt, und dann wieder nach ca.8s beschrieben wird

würde das zu falschem Takt (1 MHz statt 8 MHz) und Reset durch fehlende 
ISRs passen.

Das Blinken der LED an PD5 verstehe ich nicht, wenn in while(1) nichts 
wirklich wartendes ist.

Aber mich macht das in deiner Source ungenutzte #include <util/delay.h> 
stutzig.
Hast du vielleicht mal mit _delay_ms probiert (was das Blinken erklären 
könnte) und hier nur die falsche Source hochgeladen?

Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das in der While(1) schleife vergessen wir einfach mal
(war nur zum testen, es blinkt so schnell das man das blinken nur daran 
merkt das die led nicht ganz so hell ist)

Da anfangs garkein Interrupt ausgelöst worden ist hab ich halt mal das
ganze register auf 1 gesetzt (TIMSK = 0xff;)
mit
TIMSK =(1<<6);   //OCIE1A (Output Compare Match Interrupt Enable 
Timer/Counter 1)
oder
TIMSK =(1<<7);//TOIE1 (Timer/Counter Overflow Interrupt Enable 
Timer/Counter 1)
oder
TIMSK =(1<<6)|(1<<7);kommt leider gar kein interrupt

also resettet der uC jetzt weil ich interrupts auslöse sie aber nicht 
auswerte ?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1B und TIMSK benutzt du falsch, jedenfalls wenn ich nach dem 
Datenblatt gehe und vermute, was du machen willst. Bei TIMSK haben die 
Bits 6 und 7 nichts mit dem CTC Modus zu tun.

// Initialisierung vom Timer1 
// als Clear Timer on Compare Match (CTC) Mode 
// (Mode 4 Tabelle 47 Atmega16 Datenblatt)
void init_timer_1()
{
  // Non-PWM, Tabelle 44
  TCCR1A = 0x00; 

  // Non-PWM Mode 4 (CTC), Tabelle 47
  // Teiler 256, Tabelle 48
  TCCR1B = (1<<WGM12) | (1<<CS12);

  /*  
    To do a 16-bit write, the High byte must be written 
    before the Low byte. 

    For a 16-bit read, the Low byte must be read before 
    the High byte.
  */

  TCNT1H = 0; 
  TCNT1L = 0; 

  // Vergleichswert setzen. 8 Mhz / 256 => 1 s
  OCR1AH = ((8000000L/256) & 0x0000FF00) >> 8; 
  OCR1AL = (8000000L/256) & 0x000000FF; 

  // Interupt bei Compare Enable A
  // s. 115
  TIMSK = (1<<OCIE1A); 
}


Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, Herzlichen dank!
mein Fehler lag an
TIMSK = 0xff;
bzw.
TIMSK = (1<<6);

mit
TIMSK = (1<<OCIE1A); 
geht es

jetzt frag ich mich was daran der unterschied ist,
laut Tabelle im AVR-GCC Tutorial ist OCIE1A doch bit 6 ???

Bit      7        6    5    4    3      2     1    0
Name   TOIE1   OCIE1A   -   -   TICIE   -   TOIE0   -

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian N. wrote:

> jetzt frag ich mich was daran der unterschied ist,
> laut Tabelle im AVR-GCC Tutorial ist OCIE1A doch bit 6 ???

Im Tutorial steht aber auch:
Die folgenden Ausführungen beziehen sich auf den AT90S2313.
Für andere Modelltypen müsst ihr euch die allenfalls
notwendigen Anpassungen aus den Datenblättern der entsprechenden
Controller herauslesen.

Beim Atmega 16 ist OCIE1A Bit 4.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian N. wrote:

> laut Tabelle im AVR-GCC Tutorial ist OCIE1A doch bit 6 ???
>
> Bit      7        6    5    4    3      2     1    0
> Name   TOIE1   OCIE1A   -   -   TICIE   -   TOIE0   -

Diese Tabelle aus dem AVR-GCC-Tutorial stimmt für den Atmega16 
nicht. Leider steht im Tutorial rel. unauffällig:

> Einige Registerbeschreibungen dieses Tutorials beziehen
> sich auf den inzwischen veralteten AT90S2313.

Möglicherweise ist das hier der Fall.

Lerne:

1/ Man sollte immer das passende Datenblatt lesen und vergleichen.

2/ Symbolische Namen wie OCIE1A sind im Code sinnvoller als absolute 
Zahlen.

Autor: Sebastian N. (exl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...hätte ich dass nur früher gewusst, ...
danke für den hinweis
sollte vieleicht n bischen grösser geschrieben werden für welchen uC das 
Tutorial ist,
der Tip das man die Bits nicht direkt eingibt ist echt gut werd ich mir 
merken

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.