- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 7 von 7

Thema: UART beeinflusst Variablen???

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2009
    Beiträge
    6

    UART beeinflusst Variablen???

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich beschäftige mich erst seit ein paar Wochen mit Microcontrollern und habe daher noch nicht allzu viel Erfahrung. Ich habe folgendes Programm für einen Datenlogger geschrieben:

    Code:
    $regfile = "m8def.dat"
    $crystal = 1000000
    $hwstack = 65
    $swstack = 40
    $framesize = 100
    $baud = 4800
    
    
    Config Sda = Portc.4
    Config Scl = Portc.5
    
    
    
    Declare Sub Serial0charmatch
    Declare Sub Wertlesen(kanal As Word)
    Declare Sub Speichern(daten As Word)
    Declare Sub Lesen
    Declare Sub Intervall(intervall_neu As String)
    Declare Sub Datenausgabe(bereich As String)
    Declare Sub Online
    
    
    Dim Schreiben As Word At $250
    Dim Schreiben1 As Byte At $250 Overlay
    Dim Schreiben2 As Byte At $251 Overlay
    Dim Addresse As Word At $260
    Dim Addresse1 As Byte At $260 Overlay
    Dim Addresse2 As Byte At $261 Overlay
    Dim Lesen As Word At $270
    Dim Lesen1 As Byte At $270 Overlay
    Dim Lesen2 As Byte At $271 Overlay
    Dim Befehl As String * 12
    Dim Befehlarray(2) As String * 7
    Dim Intervall As Word
    Dim Zeit As Word
    Dim A As Byte
    Dim N As Word
    Dim Ende As Word
    Dim Zaehler As Word
    Dim Temp As Word
    Dim Druck As Word
    
    
    Config Adc = Single , Prescaler = Auto
    Start Adc
    Config Timer1 = Timer , Prescale = 64
    Timer1 = 49910
    On Timer1 Isr_timer1
    Config Serialin = Buffered , Size = 15 , Bytematch = 13
    Config Pinb.2 = Input
    Config Portb.1 = Output
    'Config Portb.3 = Output
    Portb.2 = 1
    Zeit = 0
    Zaehler = 1
    
    
    Readeeprom Lesen1 , 10                                      'Intervallzeit lesen
    Readeeprom Lesen2 , 11
    If Lesen >= 1 Then
     Intervall = Lesen
    Else
     Intervall = 1
    End If
    
    Enable Interrupts                                           'Programm Anfang
    Enable Timer1
    Do
        Addresse = Zaehler * 2
        Decr Addresse                                           'Hauptschleife
      If Zeit >= Intervall Then
        N = 0
        Call Wertlesen(n)
    
        Call Speichern(temp)
        Addresse = 5000
        Call Speichern(zaehler)
        Incr Zaehler
      End If
    
    Loop
    End
    
    
    Isr_timer1:                                                 'Timer zählt im Sekundentakt
    Timer1 = 49910
    If Pinb.2 = 0 Then
    Incr Zeit
    End If
    Return
    
    
    Sub Serial0charmatch()                                      'Daten über UART empfangen
      Input Befehl Noecho
      If Befehl <> "" Then
        A = Split(befehl , Befehlarray(1) , "  ")
        Select Case Befehlarray(1)
          Case "interv" : Call Intervall(befehlarray(2))
          Case "lesen" : Call Datenausgabe(befehlarray(2))
          Case "online" : Call Online
        End Select
      End If
    End Sub
    
    Sub Wertlesen(kanal As Word)
      Toggle Portb.1                                            'AD-Wandler auslesen
      Temp = Getadc(kanal)
      Zeit = 0
    
    End Sub
    
    Sub Speichern(daten As Word)
      Disable Interrupts
      Schreiben = Daten
      I2cstart                                                  'Start
      I2cwbyte &HA0                                             'Sende Slavadresse
      I2cwbyte Addresse2                                        'Sende Speicheradresse High
      I2cwbyte Addresse1                                        'Sende Speicheradresse  LOW
      I2cwbyte Schreiben2                                       'Sende Wert
      I2cstop                                                   'stop
      Waitms 5                                                  'warte 10ms
      Incr Addresse
      I2cstart                                                  'Start
      I2cwbyte &HA0                                             'Sende Slavadresse
      I2cwbyte Addresse2                                        'Sende Speicheradresse High
      I2cwbyte Addresse1                                        'Sende Speicheradresse  LOW
      I2cwbyte Schreiben1                                       'Sende Wert
      I2cstop                                                   'stop
      Waitms 5                                                  'warte 10ms
      Enable Interrupts
    End Sub
    
    Sub Lesen
       Disable Interrupts
       I2cstart                                                 'Start
       I2cwbyte &HA0                                            'Sende Slavadresse +1 für Schreiben
       I2cwbyte Addresse2                                       'Sende Speicheradresse High
       I2cwbyte Addresse1                                       'Sende Speicheradresse Low
       I2cstart                                                 'Start
       I2cwbyte &HA1                                            'Sende Slavadresse +1 für Lesen
       I2crbyte Lesen2 , Nack                                   'Lese Adresse vom EEprom
       I2cstop
       Waitms 5                                                 'Stop
       Incr Addresse
    
       I2cstart                                                 'Start
       I2cwbyte &HA0                                            'Sende Slavadresse +1 für Schreiben
       I2cwbyte Addresse2                                       'Sende Speicheradresse High
       I2cwbyte Addresse1                                       'Sende Speicheradresse Low
       I2cstart                                                 'Start
       I2cwbyte &HA1                                            'Sende Slavadresse +1 für Lesen
       I2crbyte Lesen1 , Nack                                   'Lese Adresse vom EEprom
       I2cstop                                                  'Stop
       Waitms 5
       Enable Interrupts
    End Sub
    
    
    Sub Intervall(intervall_neu As String)
     Disable Interrupts
     Schreiben = Val(intervall_neu)
     Writeeeprom Schreiben1 , 10
     Writeeeprom Schreiben2 , 11
     Intervall = Val(intervall_neu)
     Enable Interrupts
     Print "Neuer Intervall: " ; Intervall_neu                  '   Intervallzeit ändern
    End Sub
    
    Sub Datenausgabe(bereich As String)
    Select Case Bereich
     Case "z"
      Addresse = 5000
      Call Lesen
      Print Str(lesen)
     Case "iv"
      Print Str(intervall)
     Case Else
      Addresse = Val(bereich)
      Ende = Val(bereich) + 19
      Do
       Call Lesen
       Print Str(lesen)
       Incr Addresse
      Loop Until Addresse > Ende
     End Select
    End Sub
    
    
    Sub Online
     N = 0
     Call Wertlesen(n)
     Print Str(temp)
    End Sub
    Der Timer zählt im Sekundentakt die Variable Zeit hoch. Wenn Variable Zeit = Variable Intervall ist, wird der aktuelle Wert vom AD-Wandler gelesen, der Wert und der neue Zählerstand in einem externen EEPROM gespeichert und die Variable Zeit zurückgesetzt. Anschließend können die Daten über UART wieder ausgelesen werden.

    Das funktioniert auch soweit, jedoch veränder sich der Zählerstand manchmal beim auslesen. Habe ich vielleicht bei der Variablendeklaration etwas falsch gemacht?
    Vielen Dank im Voraus für eure Antworten

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Ich schätze das liegt daran, dass du High und Low Byte vertauschst. Musst du mal überprüfen. Wenn du sowas deklarierst

    Dim Schreiben As Word At $250
    Dim Schreiben1 As Byte At $250 Overlay
    Dim Schreiben2 As Byte At $251 Overlay
    Dim Addresse As Word At $260
    Dim Addresse1 As Byte At $260 Overlay
    Dim Addresse2 As Byte At $261 Overlay
    Dim Lesen As Word At $270
    Dim Lesen1 As Byte At $270 Overlay
    Dim Lesen2 As Byte At $271 Overlay

    dann liegt bei 250 das Low-Byte und bei 251 das High-byte der Variable Schreiben. Mit festen Adressen würde ich das Normalerweise sowieso nicht machen. Lieber so:

    Dim Schreiben As Word
    Dim Schreiben_low As Byte At Schreiben Overlay
    Dim Schreiben_high As Byte At $Schreiben+1 Overlay
    Dim Addresse As Word
    Dim Addresse_low As Byte At Addresse Overlay
    Dim Addresse_high As Byte At $Addresse+1 Overlay
    Dim Lesen As Word
    Dim Lesen_low As Byte At Lesen Overlay
    Dim Lesen_high As Byte At Lesen+1 Overlay

    So ist dein Code auch auf einen anderen µC portierbar, ohne dass du die Adressen ändern musst.

    Außerdem würde ich eine Sub nicht genauso nennen wie eine Variable (Intervall). Bascom kommt zwar damit zurecht, es liest sich aber schwerer.

    Gruß

    Rolf

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2009
    Beiträge
    6
    Hallo Rolf,
    danke für deine Tipps. Leider war das aber nicht der Fehler. Die Messwerte die ich auslese sind ok. Nur wenn ich mehrmals hintereinander den Zähler auslese (also lesen z sende), erhöht sich der Zähler um 1 und es wird ein neuer Messwert aufgenommen (obwohl PB2 1 ist). Als würde die Variable Zeit beeinflusst...

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Das war wohl eh Quatsch, was ich da bzgl. Low und High losgelassen habe. Bei dir im Programm ist es richtig rum. Sorry.
    Ich kann deinen Code wegen der I2C Befehle nicht wirklich ausprobieren.
    Wenn du vermutest, dass die Zeit erhöht wird, dann mach doch mal ein Print Zeit in die ISR, damit du sofort siehst, wann da was passiert.

    Gruß

    Rolf

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2009
    Beiträge
    6
    Die Variablen ändern sich wohl doch nicht. Aber obwohl Zeit = 0 und Intervall = 5 ist, wird die Bedingung if Zeit >= Intervall manchmal ausgeführt. Sehr komisch....

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Läuft da vielleicht eine der Variable über?
    Versuch mal durch Prints oder Anzeigen auf dem Display einzugrenzen, unter welchen Bedingungen der Fehler auftritt.
    Schau auch mal, ob die String Variablen, die vor Intervall deklariert sind, evtl. längere Strings bekommen können. Bascom überprüft und verhindert dies nicht. Ein Zeichen zu lang und schon hast du im Low-Byte von Intervall das Stringende-Zeichen stehen, eine 0.

    Gruß

    Rolf

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    29.01.2009
    Beiträge
    6
    Ich denke nicht. Habe die String-Variablen und den UART-Puffer mal deutlich vergrößert, aber der fehler bleibt trotzdem. Und eigentlich werden nie mehr als 8 Byte empfangen.

    Der Fehler tritt immer nur auf wenn ich den zähler (mit "lesen z") oder den aktuellen Wert ( mit "online") mehrmals hintereinander auslese. Beim auslesen der Datensätze ( z.B. "lesen 1") ist der Fehler noch nicht aufgetreten.

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad