PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AVR startet bei Interrupt neu



Jaecko
25.02.2007, 14:04
Moin.

Hab ein kleines Problem mit dem angehängten Programm.
Der Pin INT0 (PD2) wird mit einem 4,7k-Widerstand auf Masse gezogen; Impuls ist ein 5V-Puls.

Kurze Beschreibung:
Das Programm ist ein Drehzahlmesser, der aus den Impulsen der Zündspule die Drehzahl errechnen und auf einem 4stelligen 7-Seg. Display anzeigen soll.
Nach dem Selbsttest, bei dem nacheinander alle Segmente einzeln durchlaufen, soll die Zeit zwischen 2 Impulsen gemessen werden. Dieser Abstand wird dann in die Drehzahl umgerechnet. Läuft der Timer über (Motor steht, Drehzahl zu langsam), dann soll auf dem Display "----" erscheinen. Ansonsten die 4-stellige Drehzahl mit evtl führenden Nullen.
Ohne Impuls erscheint nach dem Selbsttest auch die "----"

Bei Eingang eines Impulses startet der AVR aber neu.
Stimmt da Softwaretechnisch was nicht?

MfG

Code:


$regfile = "m8def.dat"
$crystal = 8000000
'$prog &HFF , &HE1 , &HD9 , &H00
$framesize = 32
$swstack = 32
$hwstack = 32

'7 Segmente
Config Pinc.5 = Output : Ledsega Alias Portc.5
Config Pinc.4 = Output : Ledsegb Alias Portc.4
Config Pinc.3 = Output : Ledsegc Alias Portc.3
Config Pinc.2 = Output : Ledsegd Alias Portc.2
Config Pinc.1 = Output : Ledsege Alias Portc.1
Config Pinc.0 = Output : Ledsegf Alias Portc.0
Config Pinb.5 = Output : Ledsegg Alias Portb.5

'Segmentauswahl
Config Pind.5 = Output : Z1 Alias Portd.5
Config Pind.6 = Output : Z2 Alias Portd.6
Config Pind.7 = Output : Z3 Alias Portd.7
Config Pinb.0 = Output : Z4 Alias Portb.0

'Timer-Config
Enable Interrupts
Config Timer1 = Timer , Prescale = 8
On Timer1 Isrtimer1
Timer1 = 0
Enable Timer1

'Interrupt
Config Int0 = Rising
Enable Int0
On Int0 Isrint0

'Variablen & Subs
Declare Sub Getsegs
Dim Ledchar As String * 1
Dim Char1 As String * 1
Dim Char2 As String * 1
Dim Char3 As String * 1
Dim Char4 As String * 1
Dim Sega As Bit
Dim Segb As Bit
Dim Segc As Bit
Dim Segd As Bit
Dim Sege As Bit
Dim Segf As Bit
Dim Segg As Bit
Dim Ziffer As Word
Dim Ledstring As String * 4
Dim Messbeginn As Long
Dim Messende As Long
Dim Taktdauer As Long
Dim Drehzahl As Double

'Hier Selbsttest; aus Übersichtlichkeitsgründen rausgenommen


Do

Char1 = Mid(ledstring , 1 , 1)
Char2 = Mid(ledstring , 2 , 1)
Char3 = Mid(ledstring , 3 , 1)
Char4 = Mid(ledstring , 4 , 1)

For Ziffer = 1 To 4
If Ziffer = 1 Then
Z1 = 1 : Z2 = 0 : Z3 = 0 : Z4 = 0
Ledchar = Char1
End If
If Ziffer = 2 Then
Z1 = 0 : Z2 = 1 : Z3 = 0 : Z4 = 0
Ledchar = Char2
End If
If Ziffer = 3 Then
Z1 = 0 : Z2 = 0 : Z3 = 1 : Z4 = 0
Ledchar = Char3
End If
If Ziffer = 4 Then
Z1 = 0 : Z2 = 0 : Z3 = 0 : Z4 = 1
Ledchar = Char4
End If
Getsegs

If Sega = 1 Then
Ledsega = 1 : Waitms 1 : Ledsega = 0 : End If
If Segb = 1 Then
Ledsegb = 1 : Waitms 1 : Ledsegb = 0 : End If
If Segc = 1 Then
Ledsegc = 1 : Waitms 1 : Ledsegc = 0 : End If
If Segd = 1 Then
Ledsegd = 1 : Waitms 1 : Ledsegd = 0 : End If
If Sege = 1 Then
Ledsege = 1 : Waitms 1 : Ledsege = 0 : End If
If Segf = 1 Then
Ledsegf = 1 : Waitms 1 : Ledsegf = 0 : End If
If Segg = 1 Then
Ledsegg = 1 : Waitms 1 : Ledsegg = 0 : End If

Next
Loop

Sub Getsegs
Select Case Ledchar
Case "0"
Sega = 1 : Segb = 1 : Segc = 1 : Segd = 1 : Sege = 1 : Segf = 1 : Segg = 0
Case "1"
Sega = 0 : Segb = 1 : Segc = 1 : Segd = 0 : Sege = 0 : Segf = 0 : Segg = 0
Case "2"
Sega = 1 : Segb = 1 : Segc = 0 : Segd = 1 : Sege = 1 : Segf = 0 : Segg = 1
Case "3"
Sega = 1 : Segb = 1 : Segc = 1 : Segd = 1 : Sege = 0 : Segf = 0 : Segg = 1
Case "4"
Sega = 0 : Segb = 1 : Segc = 1 : Segd = 0 : Sege = 0 : Segf = 1 : Segg = 1
Case "5"
Sega = 1 : Segb = 0 : Segc = 1 : Segd = 1 : Sege = 0 : Segf = 1 : Segg = 1
Case "6"
Sega = 1 : Segb = 0 : Segc = 1 : Segd = 1 : Sege = 1 : Segf = 1 : Segg = 1
Case "7"
Sega = 1 : Segb = 1 : Segc = 1 : Segd = 0 : Sege = 0 : Segf = 0 : Segg = 0
Case "8"
Sega = 1 : Segb = 1 : Segc = 1 : Segd = 1 : Sege = 1 : Segf = 1 : Segg = 1
Case "9"
Sega = 1 : Segb = 1 : Segc = 1 : Segd = 1 : Sege = 0 : Segf = 1 : Segg = 1
Case "-"
Sega = 0 : Segb = 0 : Segc = 0 : Segd = 0 : Sege = 0 : Segf = 0 : Segg = 1
Case "B" ' = Blank
Sega = 0 : Segb = 0 : Segc = 0 : Segd = 0 : Sege = 0 : Segf = 0 : Segg = 0
Case "L"
Sega = 0 : Segb = 0 : Segc = 0 : Segd = 1 : Sege = 1 : Segf = 1 : Segg = 0
Case "o"
Sega = 0 : Segb = 0 : Segc = 1 : Segd = 1 : Sege = 1 : Segf = 0 : Segg = 1
End Select
End Sub

Isrint0:
Messende = Timer1
Taktdauer = Messende - Messbeginn
Drehzahl = 30 / Taktdauer ' 2 Takte pro Umdrehung
Drehzahl = Fix(drehzahl)
Ledstring = Str(drehzahl)
'Länge auf 4 Zeichen anpassen
If Len(ledstring) = 1 Then Ledstring = "000" + Ledstring
If Len(ledstring) = 2 Then Ledstring = "00" + Ledstring
If Len(ledstring) = 3 Then Ledstring = "0" + Ledstring
If Len(ledstring) > 4 Then Ledstring = Right(ledstring , 4)
Timer1 = 0
Messbeginn = Timer1
Return

Isrtimer1:
'Bei Überlauf (= Motor steht) Display auf "----"
Ledstring = "----"
Return

End

Vitis
25.02.2007, 15:08
bei der Isrint0 haste nach dem Return kein end,
bei manchen Bascom versionen soll das Probleme geben können wird berichtet.
Deine ISR int0 ist auch sehr lang, möglich das da in der ISR
ein neuer Interrupt ausgelöst wird, auch das kann zu Problemen
führen. Merke: Die ISR immer so kurz wie möglich halten.
Berechnungen und Stringoperationen möglichst nicht in ISR,
sondern in Mainloop.

Jaecko
25.02.2007, 15:37
Dann werd ich das Programm mal umbauen.
Muss ich sowieso neu anfangen.
Mir ist grad aufgefallen, dass die Berechnung der Drehzahl so irgendwie sowieso nicht stimmen kann. Da ja der Timerwert sich nicht im Sekundentakt ändert; Hab den Prescaler übersehen.

Aber irgendwie steh ich grad aufm Schlauch, den richtigen Timer (8/16 Bit) und den richtigen Prescaler zu finden, damit Drehzahlen von 500 bis 6000 erfasst werden können.
Für 500 RPM muss der Zähler bis 0,12 Sekunden durchzählen können ohne Überlauf.
Aber um bei hohen Drehzahlen auch noch annähernd genau messen zu können, muss die Zeitauflösung relativ hoch sein...

Edit: Nach Rechnung müsste die mindestauflösung bei 1,6 µs liegen...

Und da steh ich grad vor nem Denkproblem:
Timer möglichst genau oder möglichst lang kein Überlauf...