Forum: Compiler & IDEs Vorteiler / Prescaler funktioniert nicht Mega8


von Friedrich (Gast)


Lesenswert?

Hallo Hallo

Ich habe mir das AVR Bord von Pollin besorgt und schreibe gerade meine
ersten Programme in C. Besser gesagt mein erstes Programm in C.
Als Mikrocontroller benutze ich den Maga8. Software AVR Studio 4 zum
Brennen bnutze ich PonyProg2000

Und hier das überarbeitete Programm
Das Alte ist unter LED zu finden.

#include <avr/io.h>
#include <avr/iom8.h>
#include <avr/interrupt.h>

#ifndef F_CPU
#warning "F_CPU nicht definiert!!!"
#define F_CPU 12000000UL
#endif
int i,a,b,erg;

ISR (TIMER0_OVF_vect)
{
   PORTD^= (1<< PD5)|(1<< PD6);

}

void zeit (void)
{
        DDRD|= (1<<DDD5) | (1<<DDD6);
        TCCR0|= (1<<CS00)|(1<<CS02);
        sei();
        TIMSK|= (1<<TOIE0);
}

int main(void)

{
   while (1)
    {
           zeit();
           b++;
           a=b+1;

        if (a>=2000)
            {
                PORTD|=(1<<PD6);
                PORTD&=~(1<<PD5);
                    i++;
                    i=i+1;
             }

                if (i==2000)
                       {
                       PORTD|=(1<<PD5);
                       PORTD&=~(1<<PD6);
                            a=0;
                            b=0;
                            i=0;
                       }



  }
 }

Sorry, das ich da etwas unstrukturiert bin.
Ich werden auch einen neuen Beitrag anfangen. Aber zu vor möchte ich
gerne deine Fragen (von Karl siehe LED) die du mir gestellt hast 
beantworten.

>
>
>         TIMSK|= (1<<TOIE0);
>         TIMSK&= ~(1<<TOIE0);
>
>
> den Overflow Interrupt freizugeben und danach gleich wieder zu sperren?
>

Ich bin davon ausgegangen, dass der Overflow dann gelöscht wird,
beziehungsweise rückgesetzt wird.


> Woran machst du fest, dass dein Prescaler nicht funktioniert?
> Auf wieviel hast du ihn den eingestellt? Wie oft wird daher die ISR
> aufgerufen?

Den Prescaler habe ich auch schon auskommentiert und da hat sich nix
geändert beim Blinken. Einstellung hatte ich auf 1024 eingestellt.
Siehe Datenblatt
http://www.atmel.com/dyn/resources/prod_documents/...
Die ISR wird einmal aufgerufen, wenn ich das richtig verstanden habe,
oder???
Gibt es da zu auch gute Bücher, um einen den Einstieg zu erleichtern???


Vielen Dank!

Friedrich

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Friedrich schrieb:

> #ifndef F_CPU
> #warning "F_CPU nicht definiert!!!"
> #define F_CPU 12000000UL
> #endif

F_CPU wird nur von den Headerdateien <util/delay.h> und
<util/setbaud.h> benutzt, die du beide nicht einbindest.  Damit ist
dieses #define nutzlos.

>            zeit();
>            b++;
>            a=b+1;

All dein Herumopern auf den Variablen wird der Compiler bei
eingeschalteter Optimierung herauswerfen (bzw. die Ausdrücke drastisch
vereinfachen), da er feststellen kann, dass die Variablenwerte
anschließend sowieso nicht benutzt werden.

Wenn du eine definierte Verzögerung haben willst, dann nimm die
Funktionen aus <util/delay.h> (aber bitte die Optimierung
einschalten!).

Wenn du die Übung durch hast, nimmst du dann gleich einen Timer. ;-)

>>         TIMSK|= (1<<TOIE0);
>>         TIMSK&= ~(1<<TOIE0);

> Ich bin davon ausgegangen, dass der Overflow dann gelöscht wird,
> beziehungsweise rückgesetzt wird.

Datenblatt lesen: deine Annahme ist falsch.  Ein gesetztes IRQ-Flag
wird nicht einfach dadurch gelöscht, dass man den IRQ verbietet und
wieder freigibt.  Im Datenblatt steht auch drin, wie man es wirklich
löscht:
1
TIFR = (1 << TOV0);

von Friedrich (Gast)


Lesenswert?

Hallo Jörg!

Ja, ich bin da etwas unstrukturiert. Ich möchte halt nur den Timer erst 
mal verstehen, wie man ihn einstellt. Klar kann ich auch die 
Headerdateien <util/delay.h> nehmen dann kann ich direkt die Zeit 
einstellen.
Aber ich möchte mir schon gerne eine eigne Funktion schreiben.
Vieles findet man ja auch im AVR-GCC-Tutorial.

Vielen Dank!

Ich werde erst mal deine Vorschläge umsetzen und dann ausprobieren.


Wie bekomme ich denn, eine farbliche Hinterlegung des Quelltextes hier 
hin??

Bis dann

Friedrich

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Friedrich schrieb:
> Wie bekomme ich denn, eine farbliche Hinterlegung des Quelltextes hier
> hin?

Indem du beim Schreiben deines Beitrags mal ein paar Zeilen nach
oben scrollst und dir die Bemerkungen unter "Formatierung" ansiehst.

von Friedrich (Gast)


Lesenswert?

Hallo Jörg!

Ein großes Dankeschön an Dich!

Jetzt blinken die LEDs! Aber ich weiß immer noch nicht ob der Vorteiler 
(Prescaler) funktioniert. Hier noch mal mein Programm.
1
#include <avr/io.h>
2
#include <avr/iom8.h>
3
#include <avr/interrupt.h>
4
5
int i,a; 
6
7
void zeit (void)
8
{
9
        DDRD|= (1<<DDD5) | (1<<DDD6);
10
        sei();
11
        TIMSK|= (1<<TOIE0);
12
        TIFR=(1<<TOV0);
13
}
14
15
int main(void)
16
17
18
{
19
     TCCR0|= (1<<CS00)|(1<<CS02);
20
   while (1)
21
    {
22
           zeit();
23
           a++;
24
           
25
        if (a==2000)
26
        
27
            
28
              PORTD ^=(1<<PD6);
29
        else
30
                  i++;
31
        
32
             if (i==2000)    
33
             {      
34
                       PORTD ^=(1<<PD5);
35
                           a=0;
36
                           i=0;
37
                    
38
              }      
39
 
40
                      
41
  }                    
42
 }

Hoffe das es jtzt o.k. ist


Vielen Dank!

Friedrich

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was die Funktion zeit() genau machen soll, ist mir nicht klar.
Eine bestimmte Zeit warten wird sie jedenfalls nicht.

Das Schlimmste aber ist: du schaltest einen Interrupt frei (den
Overflow-Interrupt von Timer 0), hast aber keine ISR dafür.  Das
führt zum Ausführen der default-ISR, und die springt auf Adresse
0, d. h. sie bewirkt einen Neustart des Programms.

Vielleicht beschreibst du ja erst einmal, was du mit dem Timer
genau bezweckst.

Deine Einrückung passt übrigens nicht zu dem, wie die hintereinander
stehenden if-Anweisungen ausgeführt werden.

von Friedrich (Gast)


Lesenswert?

Hallo Jörg!

Im Prinzip möchte ich den Timer und Vorteiler bzw. Interrupt verstehen, 
wie diese Komponenten zusammenspielen.
Im ersten Schritt wollte ich einfach zwei LEDs blinken lassen in einer 
bestimmten Zeit. (<util/delay.h> möchte ich aber nicht verwenden)
Dann wollte ich über eine Tastenabfrage die LEDs unterschiedlich schnell 
blinken lassen, aber dazu muss ich ja erst den Timer verstehen.

Ich sehe es schon ich bin ein hoffnungsloser Fall.

Ich möchte dir aber für deine Geduld und Hilfe nochmals Danken!

Friedrich

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Friedrich schrieb:
> Ich sehe es schon ich bin ein hoffnungsloser Fall.

Keineswegs, aber du solltest zumindest eine Idee im Kopf haben,
wie du den Timer dafür benutzen willst.

Im Moment wirfst du ihn nur an.  Dann rennt er los, das macht er
natürlich völlig parallel zur CPU.  Nur, danach kümmerst du dich
nie wieder um den Timer.  Irgendwie musst du ja dessen Ergebnis
mal auswerten.

von Krapao (Gast)


Lesenswert?

1
/*
2
  Im ersten Schritt wollte ich einfach zwei LEDs blinken lassen in einer
3
  bestimmten Zeit. (<util/delay.h> möchte ich aber nicht verwenden)
4
5
  Hardware: Atmega8
6
*/
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
10
int main(void)
11
{
12
  // Ausgänge einrichten
13
  DDRD|= (1<<DDD6)|(1<<DDD5);
14
15
  /* 
16
     Timer0 einrichten
17
18
     Angenommene Taktfrequenz des Atmega8 1000000 Hz (Werkseinstellung)
19
20
     Bei Prescaler 1024 kommen pro Sekunde 976,5625 Takte, d.h ein Takt
21
     kommt alle 1/976,5625s = 1,024 ms
22
23
     Der Zähler von Timer0 ist 8-Bit breit, d.h. nach 2^8 = 256
24
     Zählschritten läuft der Zähler über. Beim Überlaufen kann ein
25
     OVERFLOW Interrupt ausgelöst werden. 1,024 ms * 256 = 250 ms
26
27
     Wir lassen die LED an PD5 bei jedem Overflow an oder aus gehen.
28
     Wir lassen die LED an PD6 alle 5 Sekunden an oder aus gehen....
29
  */
30
  TCCR0 |= (1<<CS02)|(1<<CS00); // Prescaler 1024
31
  TIFR = (1<<TOV0); // Timer0 Overflow Interrupt Flag löschen
32
  TIMSK|= (1<<TOIE0); // Timer0 Overflow Interrupt zulassen
33
34
  // Interrupts global einschalten
35
  sei();
36
37
  while(1)
38
  {
39
    // Der Timer0 läuft hier parallel zum (leeren) 
40
    // Anweisungsblock in dieser while-Schleife!
41
  }                    
42
}
43
44
ISR(TIMER0_OVF_vect)
45
{
46
  static uint8_t zaehler_bis_5s = 0;
47
48
  // LED an PD5 bei jedem Interrupt toggeln
49
  PORTD ^= (1<<PD5);
50
51
  // LED an PD6 alle 5s toggeln
52
  // 5000 ms = X * 250 ms => X = 20
53
  zaehler_bis_5s += 1;
54
  if ( zaehler_bis_5s == 5000/250 )
55
  {
56
    PORTD ^= (1<<PD6);
57
    zaehler_bis_5s = 0;
58
  }
59
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.