PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CTC Timer mit mega168



phyro
30.07.2009, 14:12
Hallo,

nachdem ich von Bascom auf C umgestiegen bin stehe ich wieder vor wahrscheinlich normalen anfänglichen Problemen.

Für eine digital Uhr benötige ich einen Timer, der (genau) jede Sekunde die ISR ausführt.

Ich habe schon die Wiki durchgeschaut, die dort angegebenen Beispiel laufen bei mir nicht.

Jetzt habe ich ein anderes Beispiel gefunden:


//----------------------------------------------------
// Set up timer 1 to generate an interrupt every 1 ms
//----------------------------------------------------
TCCR1A = 0x00;
TCCR1B = (_BV(WGM12) | _BV(CS12));
OCR1A = 71;
TIMSK1 = _BV(OCIE1A);

ISR(TIMER1_COMPA_vect)
{
second++;
}

Es werden beim Compilieren zwar keine Fehler gefunden, aber meine Sekunden werden trotzdem nicht erhöht. Hoffe ihr wisst Rat.

zusätzliche Infos:

µController: AT mega168
Compiler: AVR Studio (mit Win AVR für C)

radbruch
30.07.2009, 14:20
volatile uint8_t second;

Wenn eine ISR auf eine Variable zugreift sollte diese volatile sein.

phyro
30.07.2009, 14:31
Danke für den Hinweis, aber der Codeausschnitt ist wirklich nur ein Ausschnitt. weiter oben im Programm steht bereits volatile int second

oberallgeier
30.07.2009, 17:51
... der Codeausschnitt ist wirklich nur ein Ausschnitt ...
Hübsches Ratespiel der Art: ich verstecke den größten Teil meines geheimen Codes, bitte sucht den Fehler.
... Timer, der (genau) jede Sekunde die ISR ausführt ... Beispiel laufen bei mir nicht ... anderes Beispiel gefunden ...Eine alte indische Programmiererweisheit lautet: selbst ist der Programmierer. Ne andere ist eher kryptisch: RTFM.

... Timer, der (genau) jede Sekunde die ISR ausführt ... zusätzliche Infos: ... AT mega168 ...Die Basis für einen genauen Timer ist der Quarztakt. Ohne dessen Wert zu kennen müsste ich zusammen mit der Bedeutung des "_BV" auch hier etwas raten. "TCCR1A = 0x00;" halte ich für ein eher unsinniges Codestück, da beim CTC mit OCR1A zumindest WGM01 gesetzt sein muss. Soweit ich mich an die Dokumentation erinnere.

phyro
30.07.2009, 22:55
Hübsches Ratespiel der Art: ich verstecke den größten Teil meines geheimen Codes, bitte sucht den Fehler.

Sorry, ich habe gedacht es währe übersichtlicher, wenn ich nur das poste, was auch mit dem Timer zu tun hat. Den übrigen Teil habe ich zuvor schon getestet und der tut was er soll.

Übrigens, der Ton macht die Musik!

Und wie gesagt, den Timer habe ich in Bascom schon einmal erfolgreich umgesetzt, ich will zunächst mal, dass der Timer überhaupt erstmal läuft, die passende Geschwindigkeit kann ich dann hinterher immer noch einstellen. Darum geht es mir hier nicht.

Und hier noch mal der gesamte Code:


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

void anzeige(int A1, int A2, int A3, int P);

volatile int second = 0;
volatile int minute = 0;
volatile int hour = 0;

int P = 0;


int main (void) {

//----------------------------------------------------
// Set up timer 1 to generate an interrupt every 1 ms
//----------------------------------------------------
TCCR1A = 0x00;
TCCR1B = (_BV(WGM12) | _BV(CS12));
OCR1A = 71;
TIMSK1 = _BV(OCIE1A);


DDRB = 0xff; // PortB als Ausgang
DDRC = 0b001111; // PortC.0 bis C.3 als Ausgang

while(1)
{

anzeige(hour,minute,second,0);


}
return 0;
}

/* Die Funkton Anzeige kümmert sich darum, die in A1, A2 und A3 abgelegten Zahlen auf
den Sechs 7-Segment Anzeigen dar zu stellen, P ist für die Sekunden Punkte zuständig */

void anzeige(int A1, int A2, int A3, int P)
{

PORTB = 0b000001;
PORTC = A1/10 ;

_delay_ms(3);

PORTB = 0b000010;
PORTC = A1%10 ;

_delay_ms(3);

PORTB = 0b000100;
PORTC = A2/10 ;

_delay_ms(3);

PORTB = 0b001000;
PORTC = A2%10 ;

_delay_ms(3);

PORTB = 0b010000;
PORTC = A3/10 ;

_delay_ms(3);

PORTB = 0b100000;
PORTC = A3%10 ;

_delay_ms(3);

}

ISR(TIMER1_COMPA_vect)
{
second++;

if (second>59) {
second=0;
minute++;
}

if (minute>59) {
minute=0;
hour++;
}


if (hour>23) {
hour =0;
}
}


Und der Controller wird über einen Quarz mit 16 Mhz versorgt

sternst
30.07.2009, 23:05
Und wie stellst du jetzt fest, dass second nicht richtig hochgezählt wird?

phyro
30.07.2009, 23:12
oh sry, hatte noch ne Dreher im Programm, weil ich nachher noch was dran gemacht hatte, zum testen war im Hauptprogramm nur die fkt Anzeige aufgerufen worden. Hab es im vorherigen Post geändert.

oberallgeier
30.07.2009, 23:36
... Den übrigen Teil habe ich zuvor schon getestet und der tut was er soll ...
oh sry, hatte noch ne Dreher im Programm, weil ich nachher noch was dran gemacht hatte ...
... Übrigens, der Ton macht die Musik! ...

phyro
30.07.2009, 23:43
Achso, jetzt wird mir alles klar!!! :D

Wo liegt denn das Problem, dass ich, nachdem ich hier das erste mal nachgefragt habe, noch selbst am Programm rumgewerkelt habe?
Du musst mir ja nicht helfen wenn du nicht willst? Aber was genau stört dich daran? Das ich hier frage wenn ich mal nicht weiter weiß?

Besserwessi
30.07.2009, 23:46
Wenn das alles an Code ist, fehlt wohl das sei().

phyro
31.07.2009, 00:01
Wow, danke, jetzt Zählt er schön brav.

Also mit sei() starte ich den Timer oder wie? Hab die Befehle, die für den Timer sind noch nicht verstanden, wenn es keine umstände macht, würd ich mich über Kommentare über die Zeilen

TCCR1A = 0x00;
TCCR1B = (_BV(WGM12) | _BV(CS12));
OCR1A = 71;
TIMSK1 = _BV(OCIE1A);
sei();

freuen!

021aet04
31.07.2009, 00:23
sei(); // Interrupts einschalten
Das weiß ich noch vom Mega8. Du könntest auch das DB lesen http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf. Da steht alles drin, was man wissen muss.

phyro
08.08.2009, 19:58
Die Uhr ist nun fertig.

Danke nochmal für die Hilfe.

Hier könnt ihr das Ergebnis sehen! (https://www.roboternetz.de/phpBB2/viewtopic.php?p=454832#454832)