PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt Probleme -> LED blinkt nicht



Olle_Filzlaus
01.12.2005, 07:57
Hallo,

ich habejetzt mal versucht eine LED mittels interrupt blinken zu lassen.

auf die art und weiße will ich später damit mal eine uhr bauen. deswegen der interrupt, sonst könnte ich ja auch wait 1 nehmen.

nur leider blinken die an portd angeschloßenen led nicht. entweder die blinken zu schnell so das ich es nicht sehen kann, oder der interrupt funktioniert nicht (was ich eher denke).

findet ihr ein fehler?

hier mein programm:




'******************************
'* Atmega8 mit 8MHz *
'* Interupt-testprogramm *
'******************************

$regfile "m8def.dat"
$crystal = 8000000

Config Portd = Output
Dim A As Byte , N As Byte
N = 0
A = 0

On Timer1 Ontimer1 'Interrupt-Routine für Timer1-Overflow
Config Timer1 = Timer , Prescale = 256 'Takt: Quarz/256
Enable Timer1 'Timer1-Overflow-Interrupt einschalten
Enable Interrupts 'Interrupts global zulassen
'---------------------------------------------------------
Do 'Hauptschleife
Loop
'---------------------------------------------------------
Ontimer1: 'Interrupt-Routine

N = N + 1

If N = 255 Then
A = A + 1

If A = 255 Then
Toggle Portd.0
A = 0
End If

End If
Return


wie kann man die frequenz berechnen.

weil 8MHz/256 = 31,25KHz / 256 = 122Hz /256 = 0,5Hz.
also müsste meine led aller 2 sekunden an und aus gehen. macht sie aber nicht.

danke für die hilfe

arno

Ratber
01.12.2005, 08:38
Hinter :

If N = 255 Then
A = A + 1



Fehlt noch das "N=0" sonst läuft N gegen unendlich....

hardstyleroxx
01.12.2005, 11:04
Versuche mal das Programm, das sollte so funktionieren! Die Werte sind mit rnAVR berechnet, was du auch hier irgentwo im Forum findest.

$regfile "m8def.dat"
$crystal = 8000000

Config Portd = Output

led alias portd.0

Config Timer1 = Timer, Prescale = 256
Const Timervorgabe = 3036

on timer1 ontimer1
enable timer1
enable interrupts


do

loop


ontimer1:

Timer1 = Timervorgabe

Toggle Led

Return

Rage_Empire
01.12.2005, 11:07
n läuft nicht in unendlich, da es als byte deffiniert wurde und somit bis 255 läuft und danach wieder bei 0 beginnt.

Ratber
01.12.2005, 11:21
Dann kann man dann auch "A=0" in der Schleife weglassen.

Rage_Empire
01.12.2005, 11:53
theoretisch ja, ist aber schlampig so zu programmieren ;-)

Ratber
01.12.2005, 11:58
Ja eben,mein Reden.
Entweder alle oder keinen.

Egal:

Was mir gerade mal so ein- und auffällt:


Der Timer läuft ja fröhlich weiter wärend er in der Int.Schleife steckt.
So übern Daumen kommt der vermutlich nicht mal bis zum Toggle weil er auf den nächsten Timer-Int läuft.

Also am Anfang der Int-Routine Timer abschalten und am Ende wieder einschalten (Disable Timer1/Enable Timer1)

Werner_Just
01.12.2005, 12:14
Hallo,

> wie kann man die frequenz berechnen.
> weil 8MHz/256 = 31,25KHz / 256 = 122Hz /256 = 0,5Hz.
> also müsste meine led aller 2 sekunden an und aus gehen. macht sie
> aber nicht.

Verständlich!

Der Timer1-OVF wird nach 2^16 * 256 Prozessortakten ausgeführt.
Der Timer1-OVF muss 255 * 256 mal ausgefürt werden bis der Portpin getoggelt wird.

Mach bei 8MHz Prozessortakt alle 136.902,08 Sekunden einen Zustandswechsel, bzw eine Blinkfrequenz von 0,00000365 Hz
(3.65 * 10^-6 Hz)!

Gruß Werner

P.S.
> Also am Anfang der Int-Routine Timer abschalten und am Ende wieder
> einschalten (Disable Timer1/Enable Timer1)
2^24 Takte wird die Interrupt Routine nicht benötigen ;)

Ratber
01.12.2005, 12:19
Yep,da bin ich auch gerade drauf gestoßen.

Der Simulator is ja langsam aber sooo langsam nu auch wieder nicht :D

Olle_Filzlaus
01.12.2005, 15:56
Hallo,

danke an eure Hilfe, leider habe ich mein Programm nicht zu laufen bekommen. Aber das programm von hardstyleroxx läuft super.

nur mal noch paar fragen. was ist das:

Const Timervorgabe = 3036

ich denke mal damit wird doch der timer irgendwie eingestellt. aber wie genau.

ich würde das gerne auch mal selber mal berechnen.

weil die nächste mir selber gestellte aufgabe ist eine Uhr.

und da brauche ich ja einen schönen 1 sekundentakt.

thx for help

Arno

hardstyleroxx
01.12.2005, 17:34
Die Konstante wurde wie gesagt von dem Programm rnAVR berechnet, was du hier im Forum auch als Download findest.
Die Konstante ist glaube ich da zu da, damit man die Auflösung feiner einstellen kann.

Torsten_G
01.12.2005, 20:29
Nun, wenn ich das richtig sehe, wird der Timer nach seinem Interrupt mit diesem Wert geladen, somit vergeht weniger Zeit bis zu seinem nächsten Interrupt.

"Const" deklariert die Variable "Timervorgabe" als Konstante, damit ist sie sozusagen schreibgeschützt und man kann nicht einfach im Programm einen neuen Wert drüberbügeln.

Allerdings dürfte der erste Zyklus nach dem Anlauf nicht stimmen, weil der Timer bei 0 startet, sonst ist der erste Timerdurchlauf zu lang.

Etwa so müsste es aber von Anfang an richtig gehen:

$regfile "m8def.dat"
$crystal = 8000000

Config Portd = Output

led alias portd.0

Config Timer1 = Timer, Prescale = 256
Const Timervorgabe = 3036


on timer1 ontimer1
enable timer1
enable interrupts

Timer1=Timervorgabe


do

loop


ontimer1:

Timer1 = Timervorgabe

Toggle Led

Return

Ich hab mal einfach hardstyler´s Programm geklaut... O:)

Viele Grüße

Torsten

Olle_Filzlaus
01.12.2005, 23:08
Hallo,

habe jetzt mal das programm rnavr probiert. ein feines tool. meine uhr läuft schon.

lasse die jetzt mal laufen um rauszubekommen wie genau die läuft. werde ich dann morgen früh mitbekommen.

cu arno

Olle_Filzlaus
05.12.2005, 22:29
habe die uhr jetzt ne weile laufen lassen und rausbekommen das die ca nach 7 stunden ( da ist die nacht vorbei *grins*) 20sekunden falsch geht.

das ist ne ganz schön große Abweichung. woran kann das liegen?

ich würde ja mal vermuten, das der interrupt zwar korekt funktioniert aber ebend ne mini sekunde ungenau geht und dadurch bei hoch rechnen und zählen sich fehler einschleichen. weil die ganzen werte habe ich mit dem tool rnavr berechnet. danke also mal das es stimmt :-)

mir würde am ende adann nur einfallen das ich die stunden anders hochrechne und dort ebend so 2-3 sekunden unter den tisch fallen lasse damit die zeit wieder stimmt, nur wäre das für mich keine richtige lösung.

achja, das programm soll einfach eine zeit zählen, es läuft bis 9999h und so. deswegen sind halt bei 7h 20 sekunden fehler schon ne menge.

hier mein Programm:



'********************************
'* Atmega8 mit 8MHz *
'* Uhrenbeispiel *
'********************************

$regfile "m8def.dat"
$crystal = 8000000

Config Lcdpin = Pin , Db4 = Portd.3 , Db5 = Portd.4 , Db6 = Portd.5 , Db7 = Portd.6 , E = Portd.2 , Rs = Portd.0
Config Lcdbus = 4
Config Lcd = 16 * 2

Dim S As Byte , M As Byte , H As Byte , G As Byte 'Zeit definieren
S = 0
M = 0
H = 0
G = 0

Config Timer1 = Timer , Prescale = 256
Const Timervorgabe = 34286

On Timer1 Ontimer1
Enable Timer1
Enable Interrupts

Cls

Do

Waitms 200
Locate 1 , 1
Lcd "UHR-Zeit"

Locate 2 , 2
Lcd ; G ;
Locate 2 , 4
Lcd ; H ;
Locate 2 , 7
Lcd ; M ;
Locate 2 , 10
Lcd ; S ;

Loop


'************************************************* ******************************
Ontimer1:

Timer1 = Timervorgabe

S = S + 1
If S = 60 Then 'Sekunde
S = 0
M = M + 1

If M = 60 Then 'Minute
M = 0
H = H + 1
If H = 100 Then 'Zehner Stunde
G = G + 1

If G = 99 Then 'hunderter stunden

End If
End If
End If
End If

Return
'************************************************* ******************************


thx für eure hilfe

Torsten_G
05.12.2005, 22:53
Der interne Quarz des Mega 8 ist nicht so genau wie ein Externer.

Schau doch mal ins Datenblatt, da steht die Abweichung drin.

Viele Grüße

Torsten

Ratber
06.12.2005, 06:04
habe die uhr jetzt ne weile laufen lassen und rausbekommen das die ca nach 7 stunden ( da ist die nacht vorbei *grins*) 20sekunden falsch geht.

das ist ne ganz schön große Abweichung. woran kann das liegen?



Erstmal keine Panik.

Grundsätzlich gehts ja richtig.
Nun kommt die Feinabstimmung.

Thorsten hats ja schon gesagt das der Interne Schwinger nicht gerade ein Muster an Genauigkeit ist was übrigens auch im Datenblatt behandelt wird.

Wenn du deine Schaltung bei unterschiedlichen Temperaturen betreibst (Mal ne Nacht auffer Heizung bzw. im Gemüsefach vom Kühlschrank) wirst du feststellen das der interne Schwinger auch recht Temperaturabhängig ist.

Für eine Anwendung die auf ein genaues Timing setzt ist ein genauerer Takt unbedingt nötig.
Also ein Quarz ist da minimum.
der wird dir schon bessere und Temperaturstabilere Werte liefern.
Was dann noch an Ungenauigkeit übrigbleibt kannst du dann ausgleichen indem du ihn "ziehst".
dh. mit einem kleinen Drehkondensator (Oder ausgemesenem Festkondensator) wird die Schwingfrequenz etwas angepasst.


Dabei gilt natürlich auch hier die Regel des Aufwandes.
Je genauer du es brauchst desto mehr must du anstellen.

Die Steigerung für einen quarz ist ein Qarzofen (Ein Kästchen in dem die Temperatur konstant gehalten wird) oder ein speziell Kompensierter Schwinger.
Natürlich schlägt das im Preis nieder also sollte man sich genau überlegen was man braucht.

Ich würde erstmal ,zwecks Erfahrungswerte,mit nem quarz und nem Trimmerkondensator anfangen.