PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : interrupt so oder so



baumagnat
04.08.2009, 09:37
Hallo an alle,
Ich brauche mal eine kurze Hilfe in sachen Interrupt Programmierung.
Kurze Vorgeschichte:
Ich habe mehrere AVRmega32 aneinander gekettet. Davon ist einer der Master und die anderen Slave. Alle Slave haben eine eindeutige Adresse und werden von dem Master über einen eigens geschaffenen Bus nacheinander fortlaufend abgefragt. Das klappt mit einer WHILE {FOR-Schleife} auch prima.
Jetzt das Problem:
Um die Daten auszuwerten brauche ich eine möglichst genaue Zeitangabe.
Dies habe ich versucht durch einen externen CMOS4060 zu schaffen der mir einen 1ms Takt am Master als Eingang bringt. Diesen frage ich zwischendrin immer wieder ab und zähle die Takte mit bis der Master alle Slave abgefragt hat und werte dann die Daten aus (zähler wieder auf NULL). Jetzt habe ich mal mitgestopt und festgestellt das mir ca. 5-8% der Takte verloren gehen. Ich lese immer wieder über Interrupts habe damit aber keinerlei Erfahrung da ich eher ein ab und zu Programmierer bin. Man soll Takte auch intern genau verwalten können habe ich gehört (dann könnte ich den 4060 weglassen). Für diese Probleme (ob intern oder extern) und wie man sie löst bräuchte ich mal eine möglichst exakte Lösung in C wie und wo man Interrupts zählt (inkl. allem was ich einstellen muß (ich setze zurzeit in PonyProg keine Harken)). Der Takt sollte später möglichst schnell sein um die Genauigkeit zu erhöhen. Hauptsache das Ergebnis stimmt. Warum mir Takte fehlen kann ich mir schon vorstellen. Das liegt bestimmt an dem Senden und Empfangen des Masters (Wartezeiten) und der Darstellung auf dem Display.
Danke für eure Hilfe!!! Für euch ist das bestimmt kein Problem.

Hubert.G
04.08.2009, 11:00
Womit programmierst du? AVR-Studio, CodeVision?
Welche Taktfrequenz hat dein Mega32.
Verwendest du schon einen Timer.
Wenn du einen ext. Takt nimmst, dann darfst du nicht pollen.
Mit Interrupts und Timer wirst du dich beschäftigen müssen.
Eine fertige Lösung wird dir kaum jemand bieten können, Hilfe ganz sicher.

baumagnat
04.08.2009, 11:15
also ich abreite mit 11Mhz am AVR einen Timer verwende ich nicht.
Allerdings habe ich mir pause_ms(xxx) über Beschäftigung des AVR geschaffen (FOR-Schleifen mal CPU-Takt).
Pollen???? Ausgang des 4060 auf Eingang des AVR PINA0

Es muß doch sowas geben wie:
zähle per Interrupt eine Variable zähler hoch wenn eine Flanke kommt

021aet04
04.08.2009, 11:28
Das kannst du mit einem internen Timer machen.

baumagnat
04.08.2009, 11:38
ja das wäre mir am liebsten.
Aber dann brauche ich eine Variable die mir sagt wieviele Milli oder noch besser Mikrosekunden seit dem letzten Scanndurchlauf vergangen sind. Also sowas wie eine Zählschleife des Internen Taktes die unabhänig mit läuft. Ich habe bis jetzt nur solche Funktionen gefunden die den AVR schlafen lassen. Bin ich zu blöd google zu benutzen?

Hubert.G
04.08.2009, 11:47
Pollen nennt man die Abfrage eines Pin in einer Schleife. Wenn die Abfrage langsamer ist als der Takt, geht natürlich etwas verloren.
Für dich wäre ein ext. Interrrupt not wendig, INT0 am PD2 z.B.
Besser wäre, wie schon erwähnt, ein Timer, der würde auch das pause_ms ersetzen.

baumagnat
04.08.2009, 11:57
genau das wäre auch mein Ansatz.
Gibt es eine kleine Headerdatei die mir die Anzahl der Mikrosekunden zurückliefert. Sowas wie.

.
.
.
takte = timerus();
timerus(0);
.
.
.

Hubert.G
04.08.2009, 13:45
Das geht mit dem Timer0 ganz einfach.


#include <avr/interrupt.h>
volatile unsigned char zaehler;

// Im main einrichten
TCCR0=(1<<WGM1)|(1<<CS02); // CTC, prescaler /256
OCR0=42; // sollte mit dem Prescaler 1msec ergeben
TIMSK=(1<<OCIE0); // Output Comparematch Interrupt aktivieren
sei(); // Interrupt generell freigeben

//Interruptroutine
ISR(TIMER0_COMP_vect ){
zaehler++;
}
Die Variable zaehler wird jede 1msec um 1 erhöht

baumagnat
04.08.2009, 14:33
leider ohne Erfolg!!!

Ich habe also folgendes versuchsweise geschrieben:

#include <avr/io.h> //Zugriff auf IO's des Controllers
#include <avr/interrupt.h>

volatile unsigned char zaehler;

int main()
{

// Im main einrichten
TCCR0=(1<<WGM1)|(1<<CS02); // CTC, prescaler /256
OCR0=42; // sollte mit dem Prescaler 1msec ergeben
TIMSK=(1<<OCIE0); // Output Comparematch Interrupt aktivieren
sei(); // Interrupt generell freigeben

DDRB = 0xff; //PB0...PB7 als Ausgänge definieren

while(1)
{
PORTB = zaehler;
}
}

//Interruptroutine
ISR(TIMER0_COMP_vect )
{
zaehler++;
}

daraufhin mekert mein AVR Studio mit folgenden Meldungen:

../ZAEHLER/zaehlerinterrupt.c:10: error: `WGM1' undeclared (first use in this function)
../ZAEHLER/zaehlerinterrupt.c:10: error: (Each undeclared identifier is reported only once
../ZAEHLER/zaehlerinterrupt.c:10: error: for each function it appears in.)
../ZAEHLER/zaehlerinterrupt.c: At top level:
../ZAEHLER/zaehlerinterrupt.c:24: warning: return type defaults to `int'
make: *** [zaehlerinterrupt.o] Error 1
Build failed with 3 errors and 1 warnings...

hab ich da was falsch verstanden???

Besserwessi
04.08.2009, 15:05
Der Fehler beim WGM1 kommt daher, das das wohl WGM01 heißen soll.


Die Warnung mit dem Return type ist etwas schwer zuzuordnen. Könnte davon kommen, das main als Int definiert wurde. Beim AVR (ohne Betreibssystem) ist eher void main() üblich.

baumagnat
04.08.2009, 15:30
OK, die Fehlermeldung wäre weg ---> es lag tatsächlich an WGM01

Aber zählen tut da mal nichts.

Kann das sein das ich FUSE-BITS setzen muß und wenn ja welche???

Besserwessi
04.08.2009, 17:02
Mit den Fuse bits hat das erst mal nichts zu tun. Die braucht man höchstens damit der quarz auch genutzt wird. Ohne ändern der Fuse bits wird der 1 MHz interne RC-takt genutzt.

Es sieht so aus, als wäre in der ISR definition ganz am Ende noch ein Space. Das könnte Ärger machen, war jedenfalls bei GCC3.x der Fall.

Hubert.G
04.08.2009, 17:56
Also, abgesehen von dem Fehler mit WGM01, läuft das bei mir in der Simulation einwandfrei.

baumagnat
05.08.2009, 19:09
Vielen Dank für eure Hilfe. Ich glaube ich bin auf einen guten Weg. Habe mir die Artikel unter Timer nochmal reingezogen und etwas abgeändert. Es läuft zwar noch nicht alles perfekt aber das wird schon. Wenn ich nochmal Hilfe brauche melde ich mich.