-         

Ergebnis 1 bis 9 von 9

Thema: Timingproblem mit 2 Seriellen Schnittstellen

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    29.07.2011
    Beiträge
    345

    Timingproblem mit 2 Seriellen Schnittstellen

    Anzeige

    Hi zusammen

    ich habe vor Daten per Interrupt von 2 UARTS einzulesen. Die Daten können zu absolut unterschiedlichen Zeitpunkten eintreffen. Im Moment mache Ich es so, das ich für beide einen Eingangspuffer verwende und Zyklisch abfrage ob Daten im Puffer sind. Wenn ja, dann werden diese verarbeitet und die Antwort zurück gesendet. Das dauert aber unter Umständen "sehr lange". Nun habe ich versucht die Daten per Interrupt einzulesen. Was aber irgendwie nicht richtig funktioniet.

    Meine Vermutung ist, dass das Interrupt der einen UART noch aktiv ist, während Daten auf der anderen eintreffen. Somit unterbrechen sie sich dauernd gegenseitig bis gar nichts mehr geht. Es müssen unmittelbar nach dem Eintreffen der Daten auch wieder welche zurück gesendet werden. Deshalb wollte ich es per Interrupt machen.

    Wie könnte ich das Problem lösen?

    Danke für euere Hilfe

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    46
    Beiträge
    765
    Hast du 2 Hardware UART? Wenn ja, dann mit
    Code:
    If Ischarwaiting(x) = 1 Then
    arbeiten.
    Hast Du nur einen, dann einmal mit ischarwaiting und 1mal mit Interrupt den SoftUART einlesen.

    Mit ischarwaiting ist mir noch nichts verloren gegangen.

    Codeausschnitt aus einem meiner Projekte (X300T Frontend):

    Code:
    Config Serialin = Buffered , Size = 88                      'wohl überdimensioniert     
    Enable Interrupts
    
    Do
       Gosub Infrarot
    
       If Anders1 = 1 Then 'Laufschrift Timer hat ausgelöst oder Text hat sich geändert
          Anders1 = 0
          Gosub Lauftext
          Gosub Discanimation 'Drehendes Discsymbol animieren
       End If
    
       If Anders3 = 1 Then   'Zahlen empfangen, diese auf dem Display anzeigen
          Anders3 = 0
          Gosub Zahlen
       End If
    
       Gosub Buttons
    
       If Ischarwaiting() = 1 Then
            Gosub Empfangen
       End If
    Loop
    End
    
    Empfangen:
    
       B = Inkey()
       If B >= 13 Then 'Alles kleiner 13 wird abgeschnitten 
             If B = 13 Then
                Gosub Auswerten
             Else
                If Len(seingang) < 53 Then
                   Seingang = Seingang + Chr(b)
                Else
                   Seingang = ""
                   Print "ERROR: COM Overflow..."
                End If
             End If
       End If
    
    Return
    
    Auswerten:
    'hier wird der Eingang abgearbeitet.
    return
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Zitat Zitat von demmy Beitrag anzeigen
    Im Moment mache Ich es so, das ich für beide einen Eingangspuffer verwende und Zyklisch abfrage ob Daten im Puffer sind. Wenn ja, dann werden diese verarbeitet und die Antwort zurück gesendet. Das dauert aber unter Umständen "sehr lange".
    Ich habe mir das fast ganz abgewöhnt, mit Config SerialIn= Buffered zu arbeiten, weil es häufig zu Timing Problemen kommt. Dabei wird nämlich auch der URXC Interrupt verwendet und zusätzlich noch die eigene SerialCharMatch Routine.
    Um dies zu umgehen verwende ich jetzt immer den URXC Interrupt direkt. Und ich versuche, die eingehenden Zeichen schon einmal "vorzuverarbeiten", soweit dies geht. Dann musst du nicht so viel Zeit in die Verarbeitung stecken, wenn der Datensatz komplett ist.
    Wenn du dann noch das letzte rauskitzeln willst, rufst du die ISR mit Nosave auf, da häufig nur wenige Register zu sichern sind. Da musst du aber ein bisschen vorsichtig sein.

    Zitat Zitat von demmy Beitrag anzeigen
    Nun habe ich versucht die Daten per Interrupt einzulesen. Was aber irgendwie nicht richtig funktioniet.
    Dann zeige doch mal, wie du an die Verarbeitung rangegangen bist.

    Zitat Zitat von demmy Beitrag anzeigen
    Meine Vermutung ist, dass das Interrupt der einen UART noch aktiv ist, während Daten auf der anderen eintreffen. Somit unterbrechen sie sich dauernd gegenseitig bis gar nichts mehr geht.
    Die ISRs unterbrechen sich nicht gegenseitig, wenn du das nicht explizit zugelassen hast - wovon du eh lieber die Finger lassen solltest. Ein Aufruf wird immer erst zu Ende gebracht, bevor die nächste ISR aufgerufen wird. Allerdings kommt dein Hauptprogramm dabei evtl. etwas zu kurz.

    Zitat Zitat von demmy Beitrag anzeigen
    Es müssen unmittelbar nach dem Eintreffen der Daten auch wieder welche zurück gesendet werden. Deshalb wollte ich es per Interrupt machen.
    Das Zurückschicken kannst du natürlich auch gepuffert machen, sodass dir hoffentlich nichts verloren geht.

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    29.07.2011
    Beiträge
    345
    Also ich verwende 2 Hardware Uarts. Es ist so das der µC als Buskoppler fungieren soll. d.h. er ist Master und Slave zugleich. UART1 ist die Schnittstelle zum Hauptbus und die UART0 ist die Schnittstelle zum "Kartenbus". Dort sollen bis zu 6 weitere µC angeschlossen werden die dann Zyklisch abgefragt werden. deren Daten sollen dann auf Anfrage vom Hauptbus abgeholt werden können. Ich hoffe ihr versteht was ich meine.

    So wie das Program im Moment ist funktioniert es auch. Aber zu langsam. Ich Suche einen Weg wie man es schneller machen kann. Schaut es euch mal an, vielleicht habt ihr eine Idee. Aktuelle Version ist ohne Interrupts mit Zyklischer Bufferabfrage, da es mit Interrupts ja nicht funktioniert hat. Ich hoffe ihr könnt mir helfen.

    Code:
    '--------------------------------------------------------------
    '    S-Bus-Koppler
    '
    '--------------------------------------------------------------
    $regfile = "m162def.dat"                                    ' specify the used micro
    $crystal = 8000000                                          ' used crystal frequency
    ' use baud rate (Rackbus)
    $baud = 38400
    ' baud rate for second serial port (Hauptbus)
    $baud1 = 38400
    
    $hwstack = 42                                               ' default use 32 for the hardware stack
    $swstack = 40                                               ' default use 10 for the SW stack
    $framesize = 40                                             ' default use 40 for the frame space
    ' Lib für die automatische Sende- Empfangsumschaltung
    $lib "modbus.lbx"
    
    ' Com1 (Rackbus) Schnitstelle auf 9 Bit Modus konfigurieren
    Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 9 , Clockpol = 0
    ' Com2 (Hauptbus) Schnitstelle auf 9 Bit Modus konfigurieren
    Config Com2 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 9 , Clockpol = 0
    
    
    ' use OPEN/CLOSE for using the second UART
    Open "COM2:" For Binary As #1
    
    
    Echo Off
    
    
    Enable Interrupts
    
    ' MPCM (MULTI PROCESSOR COMMUNICATION MODE) auf Hauptbus einschalten
    Ucsr1a.mpcm = 1
    
    
    ' PORTS DEKLARIEREN
    
    Rs485dir Alias Portd.2
    Config Rs485dir = Output
    Rs485dir = 0                                                'Auf Empfangsmodus schalten
    ' Pin für die Sende-Empfangsumschaltung UART
    Config Print = Portd.2 , Mode = Set
    
    
    Rs485dir1 Alias Portb.1
    Config Rs485dir1 = Output
    Rs485dir1 = 0                                               'Auf Empfangsmodus schalten
    ' Pin für die Sende-Empfangsumschaltung UART1
    Config Print1 = Portb.1 , Mode = Set
    
    
    Declare Function Checksumme_berechnen(byref Datenbereich As Byte) As Byte
    
    
    ' Empfangspuffer UART
    Config Serialin = Buffered , Size = 150
    ' Sendepuffer UART
    Config Serialout = Buffered , Size = 150
    ' Empfangspuffer UART1
    Config Serialin1 = Buffered , Size = 150
    ' Sendepuffer UART1
    Config Serialout1 = Buffered , Size = 150
    
    
    ' TIMER
    
    
    ' Watchdog Timer / LED
    Config Timer1 = Timer , Prescale = 256                      ' Timer konfigurieren
    On Timer1 Timerroutine1                                     ' Timerinterrupt Subroutine zuweisen
    Enable Timer1                                               ' Timer aktivieren
    Stop Timer1                                                 ' Timer stoppen
    Timer1 = 34286                                              ' Timer auf neuen Startwert einstellen (1s)
    
    
    ' Timeout Timer
    Config Timer3 = Timer , Prescale = 256                      ' Timer konfigurieren
    On Timer3 Timerroutine3                                     ' Timerinterrupt Subroutine zuweisen
    Enable Timer3                                               ' Timer aktivieren
    Stop Timer3
    
    
    
    ' VARIABLENDEKLARATION
    
     Dim Koppleradresse As Byte
    
     Dim Empfangeneadresse As Byte
    
     Dim Kopplerstatusbyte As Byte
    
     Dim Kopplersteuerbyte As Byte
    
     Dim Kartenadresse As Byte
     Kartenadresse = 255                                        ' Startwert
    
     Dim Anzahl_karten As Byte
    
     Dim Aktuelle_karte As Byte
     Aktuelle_karte = 1
    
     Dim Folge_karte As Byte
    
    
     ' Teilnehmer Speicherbereiche
     Dim An_k1 As Word
     Dim Von_k1 As Word
    
     Dim An_k2 As Word
     Dim Von_k2 As Word
    
     Dim An_k3 As Word
     Dim Von_k3 As Word
    
     Dim An_k4 As Word
     Dim Von_k4 As Word
    
     Dim An_k5 As Word
     Dim Von_k5 As Word
    
     Dim An_k6 As Word
     Dim Von_k6 As Word
    
     Dim An_k7 As Word
     Dim Von_k7 As Word
    
     Dim Sendeword As Word
     Dim Empfangsword As Word
     Dim Empfangene_kartenadresse As Byte
    
     Dim Schritt1 As Bit
     Schritt1 = 1
     Dim Schritt1a As Bit
     Dim Schritt2 As Bit
     Dim Schritt2a As Bit
     Dim Schritt3 As Bit
    
     Dim Sendeschritt1 As Bit
     Dim Sendeschritt2 As Bit
    
     Dim Err_falscher_teilnehmer As Bit
     Dim Err_fehlende_antwort As Bit
     Dim Err_falsche_protokolllaenge As Bit
    
     Dim Rack_bus_error As Bit
     Dim Karten_error As Bit
    
     Dim Watch_dog As Bit
     Dim Watchdogtimer As Bit
    
    
     ' Variablen zur Datenabwicklung UART / R-Bus
    
     Dim Rs485_count1 As Word
    
    
     ' Variablen zur Datenabwicklung UART1 / S-Hauptbus
     Dim Rs485_1_count1 As Word
     Dim S_bus_empfangsarray(15) As Byte
     Dim S_bus_sendearray(15) As Byte
     Dim S_bus_empfangschecksum As Byte
     Dim S_bus_sendechecksum As Byte
     Dim Datenmodus As Bit
    
    
    ' KOPPLERADRESSE ERRECHNEN
    
    If Code1 = 0 Then
    Koppleradresse = Koppleradresse + 1
    End If
    
    If Code2 = 0 Then
    Koppleradresse = Koppleradresse + 2
    End If
    
    If Code3 = 0 Then
    Koppleradresse = Koppleradresse + 4
    End If
    
    If Code4 = 0 Then
    Koppleradresse = Koppleradresse + 8
    End If
    
    If Code5 = 0 Then
    Koppleradresse = Koppleradresse + 16
    End If
    
    If Code6 = 0 Then
    Koppleradresse = Koppleradresse + 32
    End If
    
    If Code7 = 0 Then
    Koppleradresse = Koppleradresse + 64
    End If
    
    If Code8 = 0 Then
    Koppleradresse = Koppleradresse + 128
    End If
    
    
    ' Kopleradresse auf 255 begrenzen
    If Koppleradresse >= 255 Then
    Koppleradresse = 255
    End If
    
    
    ' Koppleradresse für das Sendearray festlegen
    S_bus_sendearray(1) = Koppleradresse
    
    
    ' ANZAHL DER ANGESCHLOSSENEN KARTEN ERMITTELN
    
     Ermittlung:
    
             ' Restdaten im Eingangspuffer löschen
             Clear Serialin
    
             ' Gesendete Daten als Adresse deklarieren (TXB8 High = Adresse ; TXB8 Low = Daten)
             Ucsr0b.txb8 = 1
    
             ' Anfrage an Kartenr. X senden
             Printbin Kartenadresse ;
    
             ' Die Karte hat 10ms Zeit zu antworten
             Waitms 10
    
             ' Überprüfen ob ein Zeichen im Empfangspuffer wartet.
             ' Wenn ja, das Zeichen abrufen und...
             If _rs_bufcountr0 > 0 Then
    
                   If _rs_bufcountr0 = 1 Then
                      ' Teilnehmer hat seine Adresse korrekt zurück gesendet
    
                       Inputbin Empfangene_kartenadresse
    
                       ' Nur Karten die Ihre Adresse korrekt übermitteln werden Registriert
                       If Empfangene_kartenadresse = Kartenadresse Then
    
                            ' ...Eine Karte hinzu addieren
                            Incr Anzahl_karten
    
                            ' ...Kartenadresse um eins verringern
                            Decr Kartenadresse
    
                            ' Nach einer weiteren Karte suchen
                            Goto Ermittlung
    
                       End If
    
    
                   End If
    
    
    
              ' wenn keine Rückmeldung, dann keine Karte gefunden...
             Else
    
                ' Restdaten im Eingangspuffer löschen
                Clear Serialin
              ' ... und Schleife wird verlassen
    
             End If
    
    
    
    
    
    ' HAUPTSCHLEIFE
    
    
    Do
    
    ' RINGABFRAGE DER KARTEN
    
    If Schritt1 = 1 And Anzahl_karten > 0 And Anlaufphase = 0 Then
    
       Clear Serialin
    
       ' Watchdogtimer starten
       Start Timer1
    
       ' Sendedaten und Kartenadresse zuordnen
       If Aktuelle_karte = 1 Then
       Kartenadresse = 255
       Sendeword = An_k1
       End If
    
       If Aktuelle_karte = 2 Then
       Kartenadresse = 254
       Sendeword = An_k2
       End If
    
       If Aktuelle_karte = 3 Then
       Kartenadresse = 253
       Sendeword = An_k3
       End If
    
       If Aktuelle_karte = 4 Then
       Kartenadresse = 252
       Sendeword = An_k4
       End If
    
       If Aktuelle_karte = 5 Then
       Kartenadresse = 251
       Sendeword = An_k5
       End If
    
       If Aktuelle_karte = 6 Then
       Kartenadresse = 250
       Sendeword = An_k6
       End If
    
       ' Sendedaten als Adresse deklarieren (TXB8 High = Adresse ; TXB8 Low = Daten)
       Ucsr0b.txb8 = 1
    
       Schritt1a = 1
       Schritt1 = 0
    
    End If
    
    
    ' Warten bis das TXB8 bit gesetzt ist
    If Schritt1a = 1 And Ucsr0b.txb8 = 1 Then
    
         ' Daten an Karte senden
       Printbin Kartenadresse ;
    
       ' Schritt2 für das Empfangen freigeben
       Schritt1a = 0
       Schritt2 = 1
    
    End If
    
    
    
    ' Auf Rückmeldung der Karte warten
    If Schritt2 = 1 Then
    
          ' Ein Byte wurde empfangen
          If _rs_bufcountr0 > 0 Then
    
                Err_fehlende_antwort = 0
    
                ' Quelladresse auslesen und mit gesendeter vergleichen
                Inputbin Empfangene_kartenadresse
    
                   ' Die richtige Karte hat geantwortet
                   If Empfangene_kartenadresse = Kartenadresse Then
    
                            ' Sende Daten als Daten deklarieren (TXB8 High = Adresse ; TXB8 Low = Daten)
                            Ucsr0b.txb8 = 0
    
    
                            Schritt2a = 1
                            Schritt2 = 0
    
                   Else
    
                            Schritt2 = 0
                            Err_falscher_teilnehmer = 1
    
                   End If
    
          Else
    
             Err_fehlende_antwort = 1
    
          End If
    
    End If
    
    
    ' Warten bis das TXB8 bit zurückgesetzt ist
    If Schritt2a = 1 And Ucsr0b.txb8 = 0 Then
    
          ' Daten an Karte senden
          Printbin Sendeword ;
    
          Schritt2a = 0
          Schritt3 = 1
    
    End If
    
    
    ' Auf Daten von der Karte warten
    If Schritt3 = 1 Then
    
       ' Wenn erstes Byte der Daten empfangen dann...
       If _rs_bufcountr0 > 0 Then
    
       Err_fehlende_antwort = 0
       Err_falsche_protokolllaenge = 1
    
          ' Sind beide Bytes im Puffer eingegangen, dann...
          If _rs_bufcountr0 = 2 Then
    
                ' Empfangszähler erhöhen
                Incr Rs485_count1
    
                ' 5 Zyklen lang warten ob weitere Bytes eingehen...
                If Rs485_count1 > 5 Then
    
                   Rs485_count1 = 0
    
                      ' Stimmt die Anzahl an Daten noch überein, dann...
                      If _rs_bufcountr0 = 2 Then
    
                         Err_falsche_protokolllaenge = 0
    
                             ' Empfangswort auslesen
                             Inputbin Empfangsword
    
    
                             ' Empfangene Daten auf Speicherbereiche verteilen.
                             If Aktuelle_karte = 1 Then
                                       Von_k1 = Empfangsword
                             End If
    
                             If Aktuelle_karte = 2 Then
                                       Von_k2 = Empfangsword
                             End If
    
                             If Aktuelle_karte = 3 Then
                                       Von_k3 = Empfangsword
                             End If
    
                             If Aktuelle_karte = 4 Then
                                       Von_k4 = Empfangsword
                             End If
    
                             If Aktuelle_karte = 5 Then
                                       Von_k5 = Empfangsword
                             End If
    
                             If Aktuelle_karte = 6 Then
                                       Von_k6 = Empfangsword
                             End If
    
                             ' Aktuellen Teilnehmer um eins erhöhen
                             Incr Aktuelle_karte
    
                             ' Alle Teilnehmer durchgelaufen, wieder von vorne beginnen
                             If Aktuelle_karte > Anzahl_karten Then
                             Aktuelle_karte = 1
                             End If
    
                             ' WatschdogTimer zurücksetzen bzw. auf neuen Startwert einstellen (1s)
                             Timer1 = 34286
    
                             ' Schritt3 beenden
                             Schritt3 = 0
                             ' Schritt1 starten
                             Schritt1 = 1
    
                      End If
                End If
          End If
    
       Else
    
       Err_fehlende_antwort = 1
    
       End If
    
    End If
    
    
    
    
    ' BUSKOPPLER WIRD ANGESPROCHEN
    
    
    ' Wenn erstes Byte eines Protokolls empfangen dann...
    If _rs_bufcountr1 > 0 Then
    
    
        ' Der Koppler befindet sich im Adressmodus
        If Datenmodus = 0 Then
    
              ' Adresse auslesen
              Inputbin #1 , S_bus_empfangsarray(1) , 1
    
             ' Adresse mit eingestellter Koppleradresse vergleichen und prüfen ob Daten für mich.
             If S_bus_empfangsarray(1) = Koppleradresse Then
    
                   ' Weiter mit Sendeschritt1
                   Sendeschritt1 = 1
    
             End If
    
    
        End If
    
    
    
        ' Der Koppler befindet sich im Datenmodus
        If Datenmodus = 1 Then
    
             ' Sind die geforderten 14 Byte eingetroffen
             If _rs_bufcountr1 = 14 Then
    
                Incr Rs485_1_count1
    
                ' 10 Zyklen lang warten ob weitere Bytes eingehen.
                If Rs485_1_count1 > 10 Then
    
                   Rs485_1_count1 = 0
    
                   ' Ist die Anzahl an Bytes noch korrekt, dann...
                   If _rs_bufcountr1 = 14 Then
    
                      ' Lese 14 Bytes aus dem Empfangspuffer und schreibe in Array ab Position 2
                      Inputbin #1 , S_bus_empfangsarray(2) , 14
    
                      ' Checksumme der empfangenen Bytes berechnen
                      S_bus_empfangschecksum = Checksumme_berechnen(s_bus_empfangsarray(1))
    
                        ' Empfangene Checksumme mit errechneter vergleichen
                         If S_bus_empfangschecksum = S_bus_empfangsarray(15) Then
    
                              ' Empfangene Bytes mappen.
                              Kopplersteuerbyte = S_bus_empfangsarray(2)
                              An_k1 = Makeint(s_bus_empfangsarray(3) , S_bus_empfangsarray(4))
                              An_k2 = Makeint(s_bus_empfangsarray(5) , S_bus_empfangsarray(6))
                              An_k3 = Makeint(s_bus_empfangsarray(7) , S_bus_empfangsarray(8))
                              An_k4 = Makeint(s_bus_empfangsarray(9) , S_bus_empfangsarray(10))
                              An_k5 = Makeint(s_bus_empfangsarray(11) , S_bus_empfangsarray(12))
                              An_k6 = Makeint(s_bus_empfangsarray(13) , S_bus_empfangsarray(14))
    
    
                              ' Sende Daten Mappen
                              S_bus_sendearray(2) = Kopplerstatusbyte
                              S_bus_sendearray(3) = Low(von_k1)
                              S_bus_sendearray(4) = High(von_k1)
                              S_bus_sendearray(5) = Low(von_k2)
                              S_bus_sendearray(6) = High(von_k2)
                              S_bus_sendearray(7) = Low(von_k3)
                              S_bus_sendearray(8) = High(von_k3)
                              S_bus_sendearray(9) = Low(von_k4)
                              S_bus_sendearray(10) = High(von_k4)
                              S_bus_sendearray(11) = Low(von_k5)
                              S_bus_sendearray(12) = High(von_k5)
                              S_bus_sendearray(13) = Low(von_k6)
                              S_bus_sendearray(14) = High(von_k6)
    
                              ' Checksumme der Sendebytes berechnen
                              S_bus_sendechecksum = Checksumme_berechnen(s_bus_sendearray(1))
    
                              ' Checksumme an das Sendearray übergeben
                              S_bus_sendearray(15) = S_bus_sendechecksum
    
                              ' Weiter mit Sendeschritt2
                              Sendeschritt2 = 1
    
    
                          End If
    
                   End If
    
                End If
    
             End If
    
        End If
    
    
    
    End If
    
    
    ' Prüfen ob der Koppler im Empfangsmodus ist
    If Sendeschritt1 = 1 And Rs485dir1 = 0 Then
    
    Waitus 500
    
             ' Timeouttimer starten
             Start Timer3
    
             ' wenn ja, dann Koppleradresse als Antwort senden
             Printbin #1 , Koppleradresse ;
    
             ' in den Datenmodus schalten
             Datenmodus = 1
    
             ' MPCM abschalten um Daten empfangen zu können
             Ucsr1a.mpcm = 0
    
             ' Sendeschritt1 beenden
             Sendeschritt1 = 0
    
    End If
    
    
    ' Prüfen ob der Koppler im Empfangsmodus ist
    If Sendeschritt2 = 1 And Rs485dir1 = 0 Then
     Waitus 500
             ' Sende 14 Bytes aus dem Bytearray ab Position 2
             Printbin #1 , S_bus_sendearray(2) , 14 ;
    
             ' in den Datenmodus abschalten
             Datenmodus = 0
    
             ' MPCM einschalten um Adressen empfangen zu können
             Ucsr1a.mpcm = 1
    
             ' Sendeschritt2 beenden
             Sendeschritt2 = 0
    
             ' TimeoutTimer zurücksetzen (Startwert für eine Sekunde)
             Timer3 = 34286
    
    End If
    
    
    
    'RACK-BUS FEHLER AUSWERTEN UND AUSGEBEN
    
    If Watch_dog = 1 Then
    
       ' Kopplerstatus n.i.O.
       Kopplerstatusbyte.7 = 0
    
       ' Ringabfrage der Karten stoppen
       Schritt1 = 0
       Schritt2 = 0
       Schritt3 = 0
    
       ' Teilnehmer hat nicht geantwortet
       If Err_fehlende_antwort = 1 And Fehler_erkannt = 0 Then
    
              Fehler_erkannt = 1
    
             ' Fehlercode 8: Teilnehmer antwortet nicht
             Call Koppler_fehlercode(8)
    
       End If
    
    
       ' Falsche Protokolllänge empfangen
       If Err_falsche_protokolllaenge = 1 And Fehler_erkannt = 0 Then
    
              Fehler_erkannt = 1
    
               ' Fehlercode 5: Falsche Protokolllänge empfangen
              Call Koppler_fehlercode(5)
    
       End If
    
    
       ' Unerwarteter Teilnehmer hat geantwortet
       If Err_falscher_teilnehmer = 1 And Fehler_erkannt = 0 Then
    
             Fehler_erkannt = 1
    
             ' Fehlercode 7: Unerwarteter Teilnehmer hat geantwortet
              Call Koppler_fehlercode(7)
    
       End If
    
    
    
       ' FEHLER GENAUER DEFINIEREN
       If Karten_error = 0 And Rack_bus_error = 0 Then
    
             ' Eine Karte hat nicht innerhalb der vorgegebenen Zeit geantwortet
             ' Überprüfen ob die nächste Karte Antworten würde.
             Folge_karte = Aktuelle_karte + 1
    
             If Folge_karte > Anzahl_karten Then
             Folge_karte = 1
             End If
    
             ' Kartenadresse der nachfolgenden Karte ermitteln
             If Folge_karte = 1 Then
             Kartenadresse = 255
             End If
             If Folge_karte = 2 Then
             Kartenadresse = 254
             End If
             If Folge_karte = 3 Then
             Kartenadresse = 253
             End If
             If Folge_karte = 4 Then
             Kartenadresse = 252
             End If
             If Folge_karte = 5 Then
             Kartenadresse = 251
             End If
             If Folge_karte = 6 Then
             Kartenadresse = 250
             End If
    
            ' Restdaten im Eingangspuffer löschen
            Clear Serialin
    
            ' Gesendete Daten als Adresse deklarieren (TXB8 High = Adresse ; TXB8 Low = Daten)
             Ucsr0b.txb8 = 1
    
            ' Anfrage an Kartenr. X senden
            Printbin Kartenadresse ;                            'Leerbyte ; Leerbyte;
    
            ' Die Karte hat 10ms Zeit zu antworten
            Waitms 10
    
            ' Ein Zeichen empfangen und...
            If _rs_bufcountr0 > 0 Then
    
                      '... es bleibt bei einem Kartenfehler.
    
                        Karten_error = 1
    
                      ' An das Statusbyte übergeben um welche Karte es sich handelt.
    
                      Kopplerstatusbyte.2 = Aktuelle_karte.2
                      Kopplerstatusbyte.1 = Aktuelle_karte.1
                      Kopplerstatusbyte.0 = Aktuelle_karte.0
    
            Else
            ' Keine Antwort ...
                      '... es handelt sich um einen Rack-Busfehler
    
    
                        Rack_bus_error = 1
    
                        ' Fehlercode 9: R-Bus gestört, kein Teilnehmer antwortet mehr
                        Call Koppler_fehlercode(9)
    
            End If
    
    
       End If
    
    
       ' KARTENFEHLER AN ERROR LED AUSGEBEN
       If Karten_error = 1 Then
    
          Call Blink_code_karten_error
    
       End If
    
    
       ' RACKBUSFEHLER AN ERROR LED AUSGEBEN
       If Rack_bus_error = 1 Then
    
          Call Blink_code_rbus_error
    
       End If
    
    
    End If
    
    
    
    Loop

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    29.07.2011
    Beiträge
    345
    Was ich noch vergessen habe zu schreiben. Die beiden UARTS laufen absolut asynchron, was ein Problem für Interrupts ist oder? Denn solange ein Inerrunpt aktiv ist kann ein zweites nicht gestartet werden.

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Hallo demmy,
    in der Hilfe zu Config SerialIn steht, dass man nicht direkt mit den _rs... Variablen arbeiten soll. Du machst das hier sehr ausgiebig. Aber wenn es so funktioniert ist es wohl ok.
    Geschwindigkeit zu erhöhen sehe ich einige Möglichkeiten:
    1. Du verzichtest auf den Eingangspuffer und rufst die ISR vom UART direkt auf. Dort speicherst du die ankommenden Bytes direkt in dein Array s_bus_empfangsarray() und erhöhst einen Counter. Das ist dann sehr ähnlich zu der von Bascom erzeugten ISR, die im Hintergrund existiert.
    In deinem Code ist die Funktion Checksumme_berechnen() nicht enthalten. Wenn möglich, würde ich in der Sub schon die fortlaufende Checksumme vorhalten. Dann brauchst du am Ende nicht den Wert von allen 14 zu berechnen.

    2. Du setzt An_k1 auf die Adresse von s_bus_empfangsarray(3)
    Dim An_k1 As Word At S_bus_empfangsarray(3) Overlay.
    Dadurch ersparst du dir die MakeInt Berechnung. Ebenso machst du es für die anderen Werte, immer auf die Adresse des Low_Bytes.

    3. Wahrscheinlich kannst du den gleichen Trick bei dem Array s_bus_sendearray() und den Variablen von_k* anwenden.
    Evtl. kannst du auch da die Berechnung der Checksumme mit jedem Byte direkt fortschreiten lassen.

    4. Evtl. kannst du dierekt beim Empfang eines einzelnen Bytes schon die Ausgabe durchführen. Dafür habe ich den Code allerdings noch nicht genau genug analysiert, um hier eine definitive Aussage machen zu können.

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    29.07.2011
    Beiträge
    345
    Hi, danke schon mal für deine Ideen. Ich hab aber noch ein paar Fragen dazu.
    was passiert wenn das Interrupt einer UART aktiv ist während die zweite auch ein Byte empfängt? Geht dieses dann nicht verloren?
    aktuell prüfe ich ja auch ob die Länge des Frames korrekt ist. Langt es zu prüfen ob der ankommende Frame zu kurz ist? Kann es überhaupt sein das er aufgrund eines Fehlers mehr Bytes enthält als gesendet wurden? Ist dieser Fehler in der Übertragung überhaupt möglich? also zu viele Bytes?
    zu deinem Punkt 2. Das müsste ich ganz oben in der Variablendeklaration machen oder? Aber würde er dann nicht immer sofort wenn das Array neu beschrieben wurde den wert an die variable übergeben? Ich muss doch vorher prüfen ob die checksumme der eingetroffenen Daten korrekt ist. Ist dies nicht der Fall sind die empfangenen Daten ungültig und werden einfach wieder überschrieben.
    Oder versteh ich dich gerade falsch?

    Gruß

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Zitat Zitat von demmy Beitrag anzeigen
    was passiert wenn das Interrupt einer UART aktiv ist während die zweite auch ein Byte empfängt? Geht dieses dann nicht verloren?
    Nein. Die beiden HW UARTs haben getrennte Eingangspuffer. Nur sollte deine ISR wie immer möglichst kurz sein.

    Zitat Zitat von demmy Beitrag anzeigen
    aktuell prüfe ich ja auch ob die Länge des Frames korrekt ist. Langt es zu prüfen ob der ankommende Frame zu kurz ist? Kann es überhaupt sein das er aufgrund eines Fehlers mehr Bytes enthält als gesendet wurden? Ist dieser Fehler in der Übertragung überhaupt möglich? also zu viele Bytes?
    Würde ich zunächst mal nicht ausschließen. Peaks auf der Leitung könnten schon zusätzliche Bits darstellen.

    Zitat Zitat von demmy Beitrag anzeigen
    zu deinem Punkt 2. Das müsste ich ganz oben in der Variablendeklaration machen oder? Aber würde er dann nicht immer sofort wenn das Array neu beschrieben wurde den wert an die variable übergeben? Ich muss doch vorher prüfen ob die checksumme der eingetroffenen Daten korrekt ist. Ist dies nicht der Fall sind die empfangenen Daten ungültig und werden einfach wieder überschrieben.
    Oder versteh ich dich gerade falsch?
    Wäre es denn in deinem Code schlimm, wenn die empfangenen Zeichen direkt in die Variablen übernommen würden? In der Regel werden die Daten doch korrekt übertragen, oder ist die Verbindung so schlecht?
    Der Check auf Gültigkeit kann dann am Ende immer noch erfolgen.

  9. #9
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    29.07.2011
    Beiträge
    345
    mhh ja das wäre insofern schlimm, da die zweite UART ja quasie die Schnittstelle zu einem Sekundärbus ist, auf dessen Teilnehmer die Daten verteilt werden. Diese könnten dann unter Umständen ungültige Daten erhalten, die evtl. Fehlerhaft sind, was dann wiederum zu Fehlverhalten der Teilnehmer führen kann. Deshalb lese ich erst den gesammten Frame ein, Prüfe die Checksumme und wenn diese dann gültig ist, verteile ich die Daten auf die einzelnen Speicherbereiche, von wo sie dann über die 2. UART weiter verteilt werden. Die "An" und "Von" Variablen sind sozusagen nur Zwischenspeicher die von der einen UART gelesen und von der anderen beschrieben werden. Was auch zyklisch passiert aber eben nicht synchron zueinander. Ich hoffe ihr versteht was ich meine?

    Was passiert denn wenn jetzt durch "Peaks" auf der Leitung zusätzliche Bits eingestreut werden!? Müsste das dann nicht zu einem Framing Error führen? Da die Bytes nicht mehr dem vorgegebenen Format entsprechen? Die UART würde diese Bytes ignorieren oder?

Ähnliche Themen

  1. Timingproblem !? mit Tiny13
    Von Desastro im Forum Assembler-Programmierung
    Antworten: 1
    Letzter Beitrag: 10.10.2008, 17:54
  2. Antworten: 27
    Letzter Beitrag: 29.07.2008, 14:35
  3. Timingproblem
    Von Rev0luTio im Forum PIC Controller
    Antworten: 8
    Letzter Beitrag: 05.04.2007, 21:02
  4. Interrupt mit 2 Seriellen Schnittstellen?
    Von wanderer im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 02.01.2007, 13:20
  5. Wie beide seriellen Schnittstellen des Mega 128 nutzen?
    Von annosjokey im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 06.09.2004, 20:04

Berechtigungen

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