PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS485 Datenübertragung



elkokiller
09.12.2006, 21:45
Hallo,

habe mal wieder eine Frage an die RS485 Experten.
Ich habe mir einen kleinen Bus aufgebaut und steuere damit 4 Module (je 5 Relais) an.
Parallel dazu habe ich die Möglichkeit, an jedem Modul per Taster die Relais zu schalten.

Jetzt habe ich festgestellt, dass ich über Rs485 ein Relai z.B. im Modul 1 ansteuern und umschalten kann.
Wenn allerdings im Modul 2 eine örtliche Bedienung stattfindet, reagiert Modul 1 bei einer RS485 ansteuerung nicht mehr.
Ich muss zunächst wieder Modul 1 örtlich bedienen um die RS485 bedienung zu ermöglichen.

Woran kann das liegen?
Meine Busabfrage mache ich über einen Interrupt und folgenden Code



'---------- Einlesen ----------
Onrxd:
Disable Interrupts

Incr N
B(n) = Udr

If N > 9 Then
Preamble = B(1) : Sync = B(2) : Hdb2 = B(3)
Hdb1 = B(4) : Dab1 = B(5)
Sab1 = B(6)
Db1 = B(7)
Db2 = B(8)
Crc2 = B(9)
Crc1 = B(10)
N = 0

Gosub Pruefung
Else

End If
Return
[/code]

Gento
09.12.2006, 23:04
Dein Code ist so Aussagekräftig wie die Variablennamen x1,x2,x3,x4,x5,x6,x7,x8

Gento

Vitis
10.12.2006, 12:39
tja, du disablest die interrupts und wo enablest du die wieder?
Nach dem Disable geht der URXD nämlich nicht mehr

elkokiller
10.12.2006, 14:30
Hallo,

ich habe jetzt versucht, die Interrupts zu enablen.
Leider nicht mit dem gewünschten Erfolg.

Jetzt habe ich meinen gesamten Code angehängt, da sich zwischenzeitlich einige bei mir gemeldet haben, die gerne etwas mehr über die RS485 Steuerung erfahren möchten.
Da das Programm weitestgehend ohne Probleme läuft, kann sich hier jeder etwas abkugen.
Verbesserungsvorschläge nehme ich gerne entgegen!

Vielleicht findet ja auch jemand den oben beschriebenen Fehler im Programm?!

Tobias



'***** RS-485 *************************
' RS485 Ansteuerung von 5 Relais mit Zeitschaltfunktion und manueller vor Ort Bedienung mit Tastern
' Erstellt von Tobias Riesbeck, Dezember 2006
'**************************************

$regfile = "m8def.dat"
$crystal = 7372800
$baud = 4800

'------------------------------------

Config Pind.4 = Input '1 Dil Schalter für Adresse
Config Pind.3 = Input '2 Dieser muss beim programmieren
Config Pinb.4 = Input '3 auf allen Positionen auf 0 stehen
Config Pinb.3 = Input '4

Config Pinc.0 = Input ' Schaltport
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input ' N.N.

Config Portb.0 = Output ' Schaltport's
Config Portb.1 = Output
Config Portb.2 = Output
Config Portd.7 = Output
Config Portd.6 = Output

Config Portb.5 = Output ' Kontrollport

Dim T1 As Long
Dim T2 As Long
Dim T3 As Long
Dim T4 As Long
Dim T5 As Long


Dim Zeit1 As Long
Dim Zeit2 As Long
Dim Zeit3 As Long
Dim Zeit4 As Long
Dim Zeit5 As Long
Dim Sz As Long 'Sendezeit

Zeit1 = 20000000 'Flur EG
Zeit2 = 20000000 'Schlafzimmer
Zeit3 = 20000000 'Keller
Zeit4 = 10000000 'Gang
Zeit5 = 20000000 'Flur OG


Dim Myadress As Byte 'Variable Myadress wird für Adresse über Dip Schalter festgelegt
'"Hex(myadress)" gibt die Adresse in Hex-Format aus
Myadress.0 = Pind.4
Myadress.1 = Pind.3
Myadress.2 = Pinb.4
Myadress.3 = Pinb.3


Dim Db1_ As Byte ' db1 zur Aufnahme des Modulzustandes in Hex


T1 = 0
T2 = 0
T3 = 0
T4 = 0
T5 = 0
Sz = 0


Config Portd.2 = Output ' RS485


Config Debounce = 50

Dim I As Byte
Dim Key As Byte


Dim S As String * 10
Dim B(10) As Byte 'At S Overlay
Dim N As Byte


' Adresse festlegen -------------------------------------------------

Dim Preamble_ As Byte 'Preamble-Byte
Dim Sync_ As Byte 'Syncronisation-Byte
Dim Hdb2_ As Byte 'Kopf-Byte 1
Dim Hdb1_ As Byte 'Kopf-Byte 2
Dim Dab1_ As Byte
Dim Crc2_ As Byte 'CRC2


Preamble_ = &H55 'H55
Sync_ = &H54 'H54
Hdb2_ = &H51 'H51
Hdb1_ = &H42 'H42
Dab1_ = &H00


' Protokoll ---------------------------------------------------------

Dim Preamble As Byte 'Preamble-Byte
Dim Sync As Byte 'Syncronisation-Byte
Dim Hdb2 As Byte 'Kopf-Byte 1
Dim Hdb1 As Byte 'Kopf-Byte 2
Dim Dab1 As Byte 'Empfänger-Byte 1
Dim Sab1 As Byte 'Sender-Byte 1 Adresse
Dim Db1 As Byte 'Daten-Byte 1 (in diesem Modul als Hex)
Dim Db2 As Byte 'Date-Byte 2 fals erforderlich
Dim Crc2 As Byte 'CRC2
Dim Crc1 As Byte 'CRC1



Dim Aktion As Byte 'CRC1 als Sender


Const Keys = 5

On Urxc Onrxd
Enable Urxc
Enable Interrupts

Portd.2 = 0 ' R/W für RS485

'---------- Programm ----------

Gosub Zustand

Prog_start:

N = 0



Do

If Sz > 0 Then Sz = Sz + 1
If Sz > 10000 Then Gosub Zustand


'Zeitschalter (Zähler)

If T1 > 0 Then T1 = T1 + 1

If T1 > Zeit1 Then
Portd.6 = 0
T1 = 0
Aktion = &H00
Sz = 1
Else
End If


If T2 > 0 Then T2 = T2 + 1

If T2 > Zeit2 Then
Portb.0 = 0
T2 = 0
Aktion = &H00
Sz = 1
Else
End If


If T3 > 0 Then T3 = T3 + 1

If T3 > Zeit3 Then
Portb.2 = 0
T3 = 0
Aktion = &H00
Sz = 1
Else
End If


If T4 > 0 Then T4 = T4 + 1

If T4 > Zeit4 Then
Portd.7 = 0
T4 = 0
Aktion = &H00
Sz = 1
Else
End If


If T5 > 0 Then T5 = T5 + 1

If T5 > Zeit5 Then
Portb.1 = 0
T5 = 0
Aktion = &H00
Sz = 1
Else
End If




For I = 1 To Keys
Key = I
Select Case Key
Case 1 : Debounce Pinc.0 , 0 , Key_o1 , Sub 'Port 1.
Case 2 : Debounce Pinc.1 , 0 , Key_o2 , Sub 'Port 2
Case 3 : Debounce Pinc.2 , 0 , Key_o3 , Sub 'Port 3
Case 4 : Debounce Pinc.3 , 0 , Key_o4 , Sub 'Port 4
Case 5 : Debounce Pinc.4 , 0 , Key_o5 , Sub 'Port 5

End Select
Next

Loop

End


Key_o1:
Toggle Portb.0 'Buchse 1
Aktion = &HFF
Sz = 1
If T2 = 0 Then
T2 = 1
Else
T2 = 0
End If
Return



Key_o3:
Toggle Portb.2 'Buchse 3
Aktion = &HFF
Sz = 1
If T3 = 0 Then
T3 = 1
Else
T3 = 0
End If
Return


Key_o5:

Toggle Portd.6 'Buchse 4
Aktion = &HFF
Sz = 1
If T1 = 0 Then
T1 = 1
Else
T1 = 0
End If
Return


Key_o4:
Toggle Portd.7 'Buchse 5
Aktion = &HFF
Sz = 1
If T4 = 0 Then
T4 = 1
Else
T4 = 0
End If
Return


Key_o2:
Toggle Portb.1 'Buchse 2
Aktion = &HFF
Sz = 1
If T5 = 0 Then
T5 = 1
Else
T5 = 0
End If
Return



'---------- Einlesen ----------
Onrxd:
Disable Interrupts

Incr N
B(n) = Udr

If N > 9 Then
Preamble = B(1) : Sync = B(2) : Hdb2 = B(3)
Hdb1 = B(4) : Dab1 = B(5)
Sab1 = B(6)
Db1 = B(7)
Db2 = B(8)
Crc2 = B(9)
Crc1 = B(10)
N = 0

Enable Urxc
Enable Interrupts

Gosub Pruefung
Else


End If
Return



'---------- Prüfung ----------
Pruefung: 'SNAP Prüfung der eingehenden Byte

If Sync <> Sync_ Then : Goto Prog_start
Elseif Hdb2 <> Hdb2_ Then : Goto Prog_start
Elseif Hdb1 <> Hdb1_ Then : Goto Prog_start
Elseif Dab1 <> Myadress Then : Goto Prog_start
End If

Gosub Steuerung

Return

'---------- Fernsteuerung Steuerung ----------
Steuerung:

Sz = 1
If Db1 = &H01 Then : Gosub Key_o1 : End If
If Db1 = &H02 Then : Gosub Key_o2 : End If
If Db1 = &H03 Then : Gosub Key_o3 : End If
If Db1 = &H04 Then : Gosub Key_o4 : End If
If Db1 = &H05 Then : Gosub Key_o5 : End If
If Db1 = &H06 Then : Sz = 1 : End If
Db1 = 0

Return

'---------- Übertragung des Zustandes --------

Zustand:

Db1_.0 = Portb.0 'Auswertung der Portzustände
Db1_.1 = Portb.1
Db1_.2 = Portb.2
Db1_.3 = Portd.7
Db1_.4 = Portd.6



Portb.5 = 1 ' Übertragungs LED an

Disable Urxc
Disable Interrupts


Portd.2 = 1 : Waitms 20 'RS485 PIN auf Senden

Print Chr(preamble_) ; Chr(sync_) ;
Print Chr(hdb2_) ; Chr(hdb1_) ;
Print Chr(dab1_) ; Chr(myadress);
Print Chr(db1_) ; Chr(db2);
Print Chr(crc2) ; Chr(aktion) ;
Waitms 100

Do
Loop Until Ucsra.txc = 1
Reset Ucsra.txc

Waitms 10 : Portd.2 = 0 'RS485 PIN auf Enpfang

Enable Urxc
Enable Interrupts


Aktion = ""

Sz = 0
Portb.5 = 0 ' Übertragungs LED aus
N = 0


Return

End

bertl100
10.12.2006, 21:38
Also ich machs mit gepufferten USART ala config serialin
funktioniert prima.

Vitis
10.12.2006, 22:54
hab noch kosmetische Vorschläge.

die print cht(xy) gefallen mir nicht so recht, find printbin oder
die interruptbasierende Ringpuffervariante mit schreiben
ind UDR-Register schöner, aber das ist Geschmackssache.
Brintbin wär etwas übersichtlicher denk ich.
hinter dem letzten Print die 100ms brauchste eigentlich
nicht, du hast ja den loop dahinter.
ich verwende in Programmen gern die Alias Funktion,
da kann man schön bei jeder Aktion sehen was da
bewirkt werden soll, das macht die Programme schöner
lesbar fürs Debuggen im nachhinein.
Du belegst für mindestens 120ms nach dem senden des letzten
Steuerzeichens den Bus, das könnte etwas zu lang sein,
weil für n µC ist das ne Ewigkeit. versuch mal kürzere Zeiten,
bzw. mach die 100ms mal raus.
In der Mainloop versteh ich den Sinn der For - Next Schleife nicht
für die Debounce-Pinabfrage