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
Lesezeichen