PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timingproblem mit 2 Seriellen Schnittstellen



demmy
13.05.2012, 15:28
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

peterfido
13.05.2012, 18:13
Hast du 2 Hardware UART? Wenn ja, dann mit
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):




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

for_ro
13.05.2012, 19:31
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.


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.


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.


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.

demmy
13.05.2012, 21:02
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.



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

demmy
13.05.2012, 21:11
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.

for_ro
13.05.2012, 22:01
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.

demmy
13.05.2012, 23:52
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ß

for_ro
14.05.2012, 23:20
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.


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.


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.

demmy
15.05.2012, 20:34
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?