-
        

Ergebnis 1 bis 3 von 3

Thema: AVR startet bei Interrupt neu

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987

    AVR startet bei Interrupt neu

    Anzeige

    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:
    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

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Vitis
    Registriert seit
    06.01.2005
    Ort
    Südpfalz
    Alter
    43
    Beiträge
    2.240
    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.
    Vor den Erfolg haben die Götter den Schweiß gesetzt

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    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...

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •