PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interupt 0 und 1 ohne Funktion



TobiasBlome
27.10.2007, 22:22
Hallo,
ich möchte die Zeit zwischen Interrupt0 und Interrupt1 messen. Wenn bei Int0 ein high Signal kommt soll der Timer1 gestartet werden und wenn high bei Interrupt2 kommt soll der Timer gestoppt werden. Aber irgendwie reagiert das Programm nicht auf die Interrupts. Weiß jemand warum?



'7Segmentanzeige mit 5 (oder 4) Anzeigen

$regfile = "ATtiny2313.dat" 'ATTiny2313
$crystal = 18432000 '18,4320MHz Quarz

$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack


'_________________________________________________ ______________________________
Ddrb = &B11111111 'PortB = Ausgang (PB0=A usw.)
Ddrd = &B1110011 'PortD = Ausgang (PD0=Anzeige1, PD4=A2, PD5=A3, PD6=A4) PD2/3 =INT

Config Int0 = Rising 'Falling 'wechsel von High auf Low
Config Int1 = Rising 'Falling 'wechsel von High auf Low
Enable Int0
Enable Int1

'_________________________________________________ ______________________________
Dim Anzeige_akt As Word 'Aktuelle Zeitmessung
Dim Anzeige_str As String * 5 'Zeit als String
Dim Anzeige_str_len As Byte 'String-Länge
Dim Anzeige_ziffer As String * 1 'Aktuelle Ziffer
Dim Anzeige_pos As Byte 'Aktuelle Ziffer im String
Dim I As Byte 'Allgem. Laufzahl
I = 1

Dim Zeit As Single 'gemessene Zeit von Timer1
Dim Kmh As Single 'Geschwindigkeit

'_________________________________________________ ______________________________
'TIMER0 Konfiguration für Ziffernwechsel:
Config Timer0 = Timer , Prescale = 256 ' Timer0 für Anzeige
Const T0_preload = &H70 ' Startwert Timer0 für 500Hz
Tcnt0 = T0_preload

On Timer0 Timer_irq_led ' Timer0-Overflow-Interrupt

Enable Timer0 ' Timer0 starten
Sreg.7 = 1 'Globale Interruptfreigabe

'_________________________________________________ ______________________________
'TIMER1 Konfiguration für Messzeit:
Config Timer1 = Timer , Prescale = 1024
Const Timervorgabe = 0 '29535 -> 0,5 Hz
On Timer1 Timer_irq_kmh 'Unteprogramm aufrufen

'Enable Interrupts

'_________________________________________________ ______________________________

Do ' Dauerschleife als Hauptprogramm
Waitms 250
Anzeige_akt = Timer1 'Zeit 'Wert zum anzeigen



Loop



'_________________________________________________ ______________________________
Timer_irq_led:

Tcnt0 = T0_preload 'Timer wieder laden

Anzeige_str = Str(anzeige_akt) ' Wert in String umwandeln
Anzeige_str_len = Len(anzeige_str) ' Stringlänge messen

Anzeige_pos = Anzeige_str_len - I
Anzeige_pos = Anzeige_pos + 1

Anzeige_ziffer = Mid(anzeige_str , Anzeige_pos , 1)

Portd = 0 'Ghosting vermeiden

Select Case Anzeige_ziffer 'Ziffer auf Port

Case "0" : Portb = 63 'NULL
Case "1" : Portb = 6 'EINS
Case "2" : Portb = 91 'ZWEI
Case "3" : Portb = 79 'DREI
Case "4" : Portb = 102 'VIER
Case "5" : Portb = 109 'FÜNF
Case "6" : Portb = 125 'SECHS
Case "7" : Portb = 7 'SIEBEN
Case "8" : Portb = 127 'ACHT
Case "9" : Portb = 111 'NEUN
Case Else : Portb = 0

End Select

'Segment wählen
If I = 1 Then Portd.0 = 1 'EINER
'If I = 2 Then Portd.1 = 1 'ZEHNER
If I = 2 Then
Portd.4 = 1 'HUNDERTER
'Portb.7 = 1 'Kommastelle
End If
If I = 3 Then Portd.5 = 1 'TAUSENDER
If I = 4 Then Portd.6 = 1 'ZEHNTAUSENDER

I = I + 1 'Nächste Ziffer
If I >= 6 Then I = 1 'max Anzeigen angeben! damit Anzeige möglichst hell ist(bei 5Anzeigen muss bei der 6. wieder bei 1 Angefangen werden)


Return

Irq0: 'Aufruf bei Lichtschranke 1 per Interrupt
Timer1 = 0 'Timer auf 0 setzen
Start Timer1 'Timer starten
Portb.7 = 1
Return

Irq1: 'Aufruf bei Lichtschranke 2 per Interrupt
Stop Timer1 'Timer stoppen
'Zeit = Timer1
Portb.7 = 0
Return


Timer_irq_kmh: 'Aufruf jede oder jede halbe Sekunde
Timer1 = Timervorgabe 'AUF TIMER EINSTELLUNG ACHTEN!!!!!!!

Return

linux_80
27.10.2007, 23:36
Hi,

also in diesem Beispiel ist die Zeile mit dem Enable Interrupts auskommentiert, dann kann das nicht gehen !

Michael
27.10.2007, 23:48
Hallo TobiasBlome,

du hast vergessen, anzugeben was passieren soll:
On Int0 Irq0
On Int1 Irq1
Enable Interrupts muß vermutlich auch ausgeklammert werden

Gruß, Michael

TobiasBlome
28.10.2007, 08:35
Hallo und vielen Dank!
Enable Interrupts hab ich jetzt benutzt und On Int0 Irq0
On Int1 Irq1 steht auch drinn! Ergebnis es funktioniert!
aber was meins tdu mit:
Enable Interrupts muß vermutlich auch ausgeklammert werden. Wie ausklammern?

Tobias

TobiasBlome
28.10.2007, 18:03
Tja dank euch funktioniert Teil 1 von meinem Programm - aber mal von vorne:

Also ich möchte eine Geschwindigkeit mit zwei Lichtschranken messen. Abstand 30cm und jede löst einen Interrupt aus(INT0 und INT1). Wenn INT0 kommt wird Timer1 gestartet. Nun möchte ich zählen wie oft Timer1 überläuft bis INT1 den Timer stoppt.
Irgendwie klappt das zählen vom Timerüberlauf nicht.
Kann mir jemand sagen warum und ob meine Vorgehensweise im Prinzip richtig ist?

Tobias





'7Segmentanzeige mit 5 (oder 4) Anzeigen

$regfile = "ATtiny2313.dat" 'ATTiny2313
$crystal = 18432000 '18,4320MHz Quarz

$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
'$baud = 9600

'_________________________________________________ ______________________________
Ddrb = &B11111111 'PortB = Ausgang (PB0=A usw.)
Ddrd = &B1110011 'PortD = Ausgang (PD0=Anzeige1, PD4=A2, PD5=A3, PD6=A4) PD2/3 =INT

Config Int0 = Rising 'Falling 'wechsel von High auf Low
Config Int1 = Rising 'Falling 'wechsel von High auf Low
Enable Int0
Enable Int1
On Int0 Irq0
On Int1 Irq1


'_________________________________________________ ______________________________
Dim Anzeige_akt As Word 'Aktuelle Zeitmessung
Dim Anzeige_str As String * 5 'Zeit als String
Dim Anzeige_str_len As Byte 'String-Länge
Dim Anzeige_ziffer As String * 1 'Aktuelle Ziffer
Dim Anzeige_pos As Byte 'Aktuelle Ziffer im String
Dim I As Byte 'Allgem. Laufzahl
I = 1


Dim T1ueberlauf As Single 'gemessene Zeit von Timer1
Dim Kmh As Single 'Geschwindigkeit

'_________________________________________________ ______________________________
'TIMER0 Konfiguration für Ziffernwechsel:
Config Timer0 = Timer , Prescale = 256 ' Timer0 für Anzeige
Const T0_preload = &H70 ' Startwert Timer0 für 500Hz
Tcnt0 = T0_preload

On Timer0 Timer_irq_led ' Timer0-Overflow-Interrupt

Enable Timer0 ' Timer0 starten
Sreg.7 = 1 'Globale Interruptfreigabe

'_________________________________________________ ______________________________
'TIMER1 Konfiguration für Messzeit Lichtschranke:
Config Timer1 = Timer , Prescale = 1024
Const Timervorgabe = 0 '29535 -> 0,5 Hz
On Timer1 Timer_irq_kmh 'Unteprogramm aufrufen
Stop Timer1
Enable Interrupts

'_________________________________________________ ______________________________

T1ueberlauf = 0 'Timer1Zähler auf 0 setzen
Do ' Dauerschleife als Hauptprogramm
'Waitms 250
Anzeige_akt = T1ueberlauf 'Wert zum anzeigen



Loop



'_________________________________________________ ______________________________
Timer_irq_led:

Tcnt0 = T0_preload 'Timer wieder laden

Anzeige_str = Str(anzeige_akt) ' Wert in String umwandeln
Anzeige_str_len = Len(anzeige_str) ' Stringlänge messen

Anzeige_pos = Anzeige_str_len - I
Anzeige_pos = Anzeige_pos + 1

Anzeige_ziffer = Mid(anzeige_str , Anzeige_pos , 1)

Portd = 0 'Ghosting vermeiden

Select Case Anzeige_ziffer 'Ziffer auf Port

Case "0" : Portb = 63 'NULL
Case "1" : Portb = 6 'EINS
Case "2" : Portb = 91 'ZWEI
Case "3" : Portb = 79 'DREI
Case "4" : Portb = 102 'VIER
Case "5" : Portb = 109 'FÜNF
Case "6" : Portb = 125 'SECHS
Case "7" : Portb = 7 'SIEBEN
Case "8" : Portb = 127 'ACHT
Case "9" : Portb = 111 'NEUN
Case Else : Portb = 0

End Select

'Segment wählen
If I = 1 Then Portd.0 = 1 'EINER
'If I = 2 Then Portd.1 = 1 'ZEHNER
If I = 2 Then
Portd.4 = 1 'HUNDERTER
Portb.7 = 1 'Kommastelle
End If
If I = 3 Then Portd.5 = 1 'TAUSENDER
If I = 4 Then Portd.6 = 1 'ZEHNTAUSENDER

I = I + 1 'Nächste Ziffer
If I >= 6 Then I = 1 'max Anzeigen angeben! damit Anzeige möglichst hell ist(bei 5Anzeigen muss bei der 6. wieder bei 1 Angefangen werden)


Return

Irq0: 'Aufruf bei Lichtschranke 1 per Interrupt
Timer1 = 0 'Timer auf 0 setzen
T1ueberlauf = 0 'Timer1Zähler auf 0 setzen
Start Timer1 'Timer starten
Return

Irq1: 'Aufruf bei Lichtschranke 2 per Interrupt
Stop Timer1 'Timer stoppen
Return


Timer_irq_kmh: 'Aufruf jede oder jede halbe Sekunde
Timer1 = Timervorgabe 'AUF TIMER EINSTELLUNG ACHTEN!!!!!!!
T1ueberlauf = T1ueberlauf + 1 'Timer1Zähler hoch zählen
Return

Michael
28.10.2007, 20:47
Hallo TobiasBlome,

Im Int0 wird Timer1 gelöscht und von 0 gestartet.
Ungefähr jede Millisekunde beim Überlauf von Timer1 wird eine Variable hochgezählt, die erst bei Unterbrechung der 1. Lichtschranke wieder auf 0 gesetzt wird.
Im Int1 wird Timer1 gestoppt.

Wozu startest und löschst du Timer1 überhaupt? Du willst doch letztendlich die Takte zwischen beiden Ereignissen zählen?

Welche zu messende Geschwindigkeit erwartest du denn ungefähr?

Gruß, Michael

TobiasBlome
28.10.2007, 20:58
Hallo
also ich möchte ca. 10ms bis 1 sec messen und deswegen zähle ich wie oft der Timer überläuft. Deshalb wird der Timer auch einmalig mit der 1. Lichtschanke INT0 auf 0 gesetzt

Tobias

Michael
28.10.2007, 21:21
Hallo TobiasBlome,


Ungefähr jede Millisekunde beim Überlauf von Timer1
ups, ich habe mich geirrt.
Timer1 wird ja mit 18432000/1024 = 18000 Hz getaktet
Ein Überlauf kommt dann alle 3,6 Sekunden.
Dein Timerinterrupt kommt also nicht in der erwarteten Zeit, deine Variable T1ueberlauf bleibt leer.



Wozu startest und löschst du Timer1 überhaupt? Du willst doch letztendlich die Takte zwischen beiden Ereignissen zählen?

Gruß, Michael

TobiasBlome
28.10.2007, 21:28
ups
ich dachte der kommt 18000 mal pro sek....
das passt ja garnicht....

Eigendlich wollte ich den Timer mit INT0 Starten mit INT1 stoppen und dan die Zeit vom Timer ablesen. Weil ich dachte das dem 18000/sek durchläuft habe ich nur noch die Interrupts gezählt.
Wie würdest du das machen?

Tobias

TobiasBlome
28.10.2007, 21:30
aber... ist 18000Hz nicht = 18000 mal pro Sekunde

Michael
28.10.2007, 21:59
Hallo TobiasBlome,


aber... ist 18000Hz nicht = 18000 mal pro Sekunde
ja, 18000 mal pro Sekunde wird Timer1 um 1 erhöht. Wenn Timer1 2^16 erreicht hat, ist er wieder 0 (Überlauf).

Ich würde 1 Word Variable deklarieren, "Bla"
Bei Int0 schreibst du Timer1 = 0.
Bei Int1 schreibst du Bla = Timer1.

Das Ergebnis steht nun in Bla.
Kein Timer1 starten oder stoppen.

Bei Überlauf sind 3,6 Sekunden um, das ist mehr als die angepeilte Zeit.
dazu können wir später kommen.

In der Hauptschleife (dazu ist sie da) berechnest du den Geschwindigkeitswert mit Hilfe von Bla.
Deine Strecke hat 30cm. Dein Ereignis dauert (angenommen) 0,3 Sekunden. (Geschwindigkeit 1m/s) Dein Bla hat dann den Wert 5400. (18000/s*0,3s) Wenn du jetzt durch 54 teilst, erhältst du das Ergebnis in cm/s.

Klar?

Gruß, Michael

TobiasBlome
28.10.2007, 22:19
aha
also
5400/54=100cm/s (->x3600) =360000cm/h (-> / 10000) = 36km/h

ist das so richtig?

TobiasBlome
28.10.2007, 22:24
mmhh

weiß nicht so das so richtig ist - ich bekomm nur noch 1 bis max 6 km/h wenn ich meine Hand an den 2 Drähten zum testen dran vorbei ziehe.

do
Zeit1 = Zeit / 54
Zeit2 = Zeit1 * 3600
Zeit3 = Zeit2 / 10000
Loop

TobiasBlome
28.10.2007, 22:33
kann man es irgendwie hinbekommen, dass der INT nur einen Impuls bekommt? Weil: wenn INT1 auf high ist wird schon der Wert angezeigt und wenn INT1 auf LOW geht ändert sich der Wert. Problem also wenn etwas beide Lichtschranken gleichzeitig belegt... kann man INT als Impuls benutzen, der erst nach einem "Flanknwechsel" wieder arbeitet?

Tobias

Michael
29.10.2007, 00:20
Hallo TobiasBlome,

Zeit1 = Zeit / 54 (angenommen 1m/s, dann hat Zeit = 5400)
>Zeit1 hat jetzt 100 (cm/s)

Zeit2 = Zeit1 * 3600
>Zeit2 hat jetzt 360000**

Zeit3 = Zeit2 / 10000
>Zeit3 hat jetzt den Wert 36 (3,6 wäre richtig)

** Eine Word Variable hat einen Wertebereich bis 2^16 = max 65535, hast du das bedacht?
Wenn ich eine Word Variable durch 10000 teile können also nur noch Werte von 0 bis 6 rauskommen (die Nachkommastellen werden abgeschnitten).

Gruß, Michael

TobiasBlome
29.10.2007, 16:08
Hallo,nein daran habe ich nicht gedacht - so einfach:-) man muss es nur sehen...

TobiasBlome
29.10.2007, 16:16
warum eigendlich durch 54 teilen?

for_ro
29.10.2007, 16:16
Warum willst du überhaupt teilen? Lass doch den Wert und setze bei Ausgabe nur das Komma entsprechend.
Außerdem müsstest du durch 100.000 teilen, wenn du von cm auf km umrechnen willst.

Gruß

Rolf

TobiasBlome
29.10.2007, 16:22
moment etwas langsamer...
also ich habe eine Messstrecke von 30cm und eine Zeit die ich in Km/h umrechnen muss oder?

TobiasBlome
29.10.2007, 16:59
also die Rechnung ist falsch weil:
30cm 0,3sec -> 5529,6 (18432/s*0,3s) -> 5529,6 / 54 = 102,4cm/s
30cm 0,1sec -> 1843,2 (18432/s*0,1s) -> 1843,2 / 54 = 34,1cm/s

also wenn es 0,3s dauer ist es länger als bei 0,1s also langsamer trozdem schafft er bei 0,3s 100cm/s und bei den schnelleren 0,1s nur 34cm/s

Michael
29.10.2007, 18:50
Hallo TobiasBlome,


also die Rechnung ist falsch weil:
nein, das hatte ich dir aber am 28.10.07 22:59 (Forumzeit) geschrieben


30cm 0,3sec -> 5529,6 (18432/s*0,3s) -> 5529,6 / 54 = 102,4cm/s

30cm in 0,3s macht 100cm in 1s, oder nicht? mit welcher Geschwindigkeit wird dein Timer getaktet? Taktfrequenz durch Prescaler oder Taktfrequenz durch 1000?
Du mußt die Posts schon lesen, die ich dir schreibe...

Gruß, Michael

TobiasBlome
29.10.2007, 19:36
$crystal = 18432000
Prescale = 1024

dann muss da etwas anderes falsch sein, weil je langsamer ich an den Lichtschranken vorbei gehe desto mehr steht auf der Anzeige...

Zeit1 = Zeit / 54
Zeit2 = Zeit1 * 3600
Zeit3 = Zeit2 / 1000

ich muss nochmal überlegen

Michael
29.10.2007, 21:49
Hallo TobiasBlome,


weil je langsamer ich an den Lichtschranken vorbei gehe desto mehr steht auf der Anzeige...
ja, stimmt, ein Zahlendreher, es muß heißen:
5400/Timerwert
dann hast du das Ergebnis in m/s
oder 540000/Timerwert
in cm/s

Da hättest du aber selber drauf kommen können?

Gruß, Michael

TobiasBlome
29.10.2007, 22:12
also ich hab nu Y=mx+b genommen und da kommt dann:
km/h = -0,0058579*messwert+109,05442
raus.
klappt bestens.