Hallo,

ich hab einen kleinen Umsetzer gebaut, der einen Handschalter und einen Fußschalter abfragt und dann Steuerinformationen an eine Steuerung sendet. Der Fußschalter hat einfach nur 4 Tasten, die direkt an die I/O´s des PICs angeschlossen sind. Dieser Umsetzer ist der Master.
Zusätzlich ist an dem Master via RS485-Bus noch ein Handschalter angeschlossen.
Der 485-Bus ist ca. 2 Meter lang und hat die erforderliche Terminierung etc.
Die Schaltung arbeitet auch einwandfrei. Nur ab und zu kommt es mal vor, dass der Slave beim Starten (zuschalten der Versorgungsspannung) nicht richtig startet. D.h. der Master arbeitet (LEDS am Fußschalter werden angeschaltet und über den Fußschalter ist eine Bedienung möglich). Nur der Handschalter (Slave) arbeitet manchmal nicht (die entsprechenden LEDs werden nicht angeschaltet).
Bei dem ersten Einschalten funktioniert die Kommunikation problemlos, nur nach einigen Unterbrechungen der Versorgungsspannung startet der Slave nicht korrekt.
Ich habe das Gefühl, dass es daran liegen könnte, dass beim Starten schon mal über den Bus noch undefinierte Daten gesendet werden, die die Slave-Uart zum Aufhängen bringen, quasi das der Empfangsbuffer überläuft.

Hier der Code des Masters (PIC16F873a):

Code:

'Configuration bits
@ DEVICE pic16F873a, hs_osc, wdt_on, pwrt_on, bod_on, lvp_off, cpd_off, wrt_off, protect_on 

' Definitionen
define osc 4 ' Resonator 4 Mhz
include "modedefs.bas"

' Ports als Input bzw. Output definieren
TRISA = %00001111
TRISB = %00000000
TRISC = %10110001

' UART Definitionen
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 19200 ' 19200 Bauds
DEFINE HSER_CLOERR 1

' Port-Definitionen
adcon1 = 7 'Ports auf digital

' Ein- und Ausgänge definieren
m_data var portb.0
m_clk var portb.1
m_wordclk var portb.2

m_mpreached var portc.0		'Memoryposition erreicht

led3 var portc.3'Gelb
led2 var portc.2'Grün
led1 var portc.1'Rot

schalter1 var porta.2'Select
schalter2 var porta.1'Hoch
schalter3 var porta.0'Runter
schalter4 var porta.3'Memory

busrw var porta.4

' Variablen deklarieren
Bus_out var byte		'Ausgabepuffer für Bus
Ebene var word			'Ebene (rot, grün, gelb)
Benutzer var word		'Benutzerebene 1-4
bus_in var byte			'Eingangspuffer für Bus
c_funktion var word		'Counter zur Entprellung der Funktionstaste
c_benutzer var word		'Counter zur Entprellung des Benutzerwechsels
c_save var word			'Counter zur Entprellung der Speichertaste
c_run var byte			'Hilfsvariable, die nur einmal die Übertragung von Word1 und Word2 zulässt
c_word var byte			'Variable des Datenwortes
c_ebene var byte		'Blockiervariable der Ebene (unterbindet Weiterschaltung ohne Taste zu lösen)
c_user var byte			'Blockiervariable des Benutzers (unterbindet Weiterschaltung ohne Taste zu lösen)
c_speichern var byte	'Blockiervariable des Speicherns (unterbindet Weiterschaltung ohne Taste zu lösen)
m_bit0 var bit
m_bit1 var bit
m_bit2 var bit
m_bit3 var bit
m_bit4 var bit
m_bit5 var bit
c_holdmem var byte		'Selbsthaltungsvariable für Memoryfahrt
m_memstop var byte		'Stopvariable der Memory-Funktion

'Initialisierung Display


'Led1 an (Fußschalter)
Ebene = 0
high Led1
low Led2
low Led3

pause 2000

'Led1 an (Handschalter)
Bus_out = 112
gosub SendDisplay
Bus_out = 117
gosub SendDisplay
Bus_out = 121
gosub SendDisplay

'Benutzer1 darstellen (Handschalter)
Benutzer = 0
Bus_out = 130
gosub SendDisplay


' Hauptprogramm
'-----------------
Hauptschleife:
RCSTA.4 = 0
RCSTA.4 = 1

clearwdt

'Handschalter abfragen
Bus_in = 099
Bus_out = 100
gosub SendDisplay
pause 10
if PIR1.5 = 1 then Bus_in = RCREG

if Bus_in < 031 and Bus_in > 37 then Bus_in = 099

'Memory Unterbrechung
m_memstop = 0
if schalter1 = 1 or schalter2 = 1 or schalter3 = 1 then m_memstop = 1
if Bus_in > 30 and Bus_in < 37 then m_memstop = 1

if c_holdmem = 1 then
	if m_mpreached = 1 then
		'Stop Memory
		high m_wordclk
		c_holdmem = 0
	endif

	if m_memstop = 1 then
		'User-Unterbrechung
		high m_wordclk
		c_holdmem = 0
		Bus_in = 099
	endif
endif

if c_holdmem <> 1 then

	if schalter4 = 1 then Bus_in = 037
	'Abfrage Tastendruck

	if Bus_in = 031 then gosub Naechste_Ebene	
	if Bus_in = 035 then gosub Speichern
	if Bus_in = 037 then gosub Memory
	if Bus_in = 036 then gosub Naechste_Benutzer

	if Bus_in = 032 and Ebene = 0 then gosub Hoehe_auf
	if Bus_in = 033 and Ebene = 0 then gosub Hoehe_ab
	if Bus_in = 032 and Ebene = 1 then gosub Becken_auf
	if Bus_in = 033 and Ebene = 1 then gosub Becken_ab
	if Bus_in = 032 and Ebene = 2 then gosub Ruecken_auf
	if Bus_in = 033 and Ebene = 2 then gosub Ruecken_ab

	if schalter1 = 1 then gosub Naechste_Ebene
	'if schalter4 = 1 then gosub Memory

	if schalter2 = 1 and Ebene = 0 then gosub Hoehe_auf
	if schalter3 = 1 and Ebene = 0 then gosub Hoehe_ab
	if schalter2 = 1 and Ebene = 1 then gosub Becken_auf
	if schalter3 = 1 and Ebene = 1 then gosub Becken_ab
	if schalter2 = 1 and Ebene = 2 then gosub Ruecken_auf
	if schalter3 = 1 and Ebene = 2 then gosub Ruecken_ab

	if Bus_in = 099 and schalter1 = 0 and schalter2 = 0 and schalter3 = 0 and schalter4 = 0 then gosub Zurueck
endif

goto Hauptschleife


'Unterprogramme
'----------------

'Höhe auf
Hoehe_auf:
	if c_run = 0 then
		m_bit0=1
		m_bit1=1
		m_bit2=1
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 141
	gosub SendDisplay
return

'Höhe ab
Hoehe_ab:
	if c_run = 0 then
		m_bit0=0
		m_bit1=1
		m_bit2=1
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 140
	gosub SendDisplay
return

'Becken auf
Becken_auf:
	if c_run = 0 then
		m_bit0=1
		m_bit1=0
		m_bit2=1
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 143
	gosub SendDisplay
return

'Becken ab
Becken_ab:
	if c_run = 0 then
		m_bit0=0	
		m_bit1=0
		m_bit2=1	
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 142
	gosub SendDisplay
return

'Rücken auf
Ruecken_auf:
	if c_run = 0 then
		m_bit0=1
		m_bit1=1
		m_bit2=0
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 145
	gosub SendDisplay
return

'Rücken ab
Ruecken_ab:
	if c_run = 0 then
		m_bit0=0
		m_bit1=1
		m_bit2=0
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
		c_run = 1
	endif
	
'	low m_wordclk

	Bus_out = 144
	gosub SendDisplay
return

'Ebenenwechsel
Naechste_Ebene:
	c_funktion = c_funktion + 1
	if c_funktion >= 10 then
		if c_ebene = 0 then		
			Ebene = Ebene + 1	
			if Ebene = 3 then Ebene = 0

			if Ebene = 0 then
				high Led1
				low Led2
				Low Led3
				Bus_out = 112
				gosub SendDisplay
				Bus_out = 117
				gosub SendDisplay
				Bus_out = 121
				gosub SendDisplay
				Bus_out = 147
				gosub SendDisplay
			endif

			if Ebene = 1 then
				low Led1
				high Led2
				low led3
				Bus_out = 113
				gosub SendDisplay
				Bus_out = 116
				gosub SendDisplay
				Bus_out = 121
				gosub SendDisplay
				Bus_out = 135
				gosub SendDisplay
			endif	

			if Ebene = 2 then
				low Led1
				low Led2
				high Led3
				Bus_out = 113
				gosub SendDisplay
				Bus_out = 117
				gosub SendDisplay
				Bus_out = 120
				gosub SendDisplay
				Bus_out = 136
				gosub SendDisplay
			endif
			c_ebene = 1
			c_funktion = 0
		endif
	endif
return

'Benutzerwechsel
Naechste_Benutzer:
	c_benutzer = c_benutzer + 1
	if c_benutzer >= 10 then
		if c_user = 0 then		
			Benutzer = Benutzer + 1	
			if Benutzer = 4 then Benutzer = 0

			if Benutzer = 0 then
				Bus_out = 130
				gosub SendDisplay
			endif

			if Benutzer = 1 then
				Bus_out = 131
				gosub SendDisplay
			endif

			if Benutzer = 2 then
				Bus_out = 132
				gosub SendDisplay
			endif

			if Benutzer = 3 then
				Bus_out = 133
				gosub SendDisplay
			endif

			c_user = 1
			c_benutzer = 0
		endif
	endif
return

'Memory speichern
Speichern:
	c_save = c_save + 1
	if c_save >= 100 then
		if c_speichern = 0 then
			Bus_out = 146
			gosub SendDisplay

			'Benutzer 0
			if Ebene = 0 and Benutzer = 0 then
				m_bit0=1
				m_bit1=0
				m_bit2=1
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 1 and Benutzer = 0 then
				m_bit0=0
				m_bit1=0
				m_bit2=1
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 2 and Benutzer = 0 then
				m_bit0=1
				m_bit1=1
				m_bit2=0
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			'Benutzer 1
			if Ebene = 0 and Benutzer = 1 then
				m_bit0=0
				m_bit1=1
				m_bit2=0
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 1 and Benutzer = 1 then
				m_bit0=1
				m_bit1=0
				m_bit2=0
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif
	
			if Ebene = 2 and Benutzer = 1 then
				m_bit0=0
				m_bit1=0
				m_bit2=0
				m_bit3=1
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif


			'Benutzer 2
			if Ebene = 0 and Benutzer = 2 then
				m_bit0=1
				m_bit1=1
				m_bit2=1
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 1 and Benutzer = 2 then
				m_bit0=0
				m_bit1=1
				m_bit2=1
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 2 and Benutzer = 2 then
				m_bit0=1
				m_bit1=0
				m_bit2=1
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif


			'Benutzer 3
			if Ebene = 0 and Benutzer = 3 then
				m_bit0=0
				m_bit1=0
				m_bit2=1
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 1 and Benutzer = 3 then
				m_bit0=1
				m_bit1=1
				m_bit2=0
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			if Ebene = 2 and Benutzer = 3 then
				m_bit0=0
				m_bit1=1
				m_bit2=0
				m_bit3=0
				m_bit4=0
				m_bit5=1
				gosub WordOut
			endif

			c_save = 0
			c_speichern = 1
			high m_clk
			pause 10
			low m_wordclk
			pause 100
			high m_wordclk
		endif
	endif
return

'Memory abrufen
Memory:
	Bus_out = 138
	gosub SendDisplay

	'Benutzer 1
	if Ebene = 0 and Benutzer = 0 then
		m_bit0=1
		m_bit1=0
		m_bit2=0
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 1 and Benutzer = 0 then
		m_bit0=0
		m_bit1=0
		m_bit2=0
		m_bit3=1
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 2 and Benutzer = 0 then
		m_bit0=1
		m_bit1=1
		m_bit2=1
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif

	'Benutzer 2
	if Ebene = 0 and Benutzer = 1 then
		m_bit0=0
		m_bit1=1
		m_bit2=1
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 1 and Benutzer = 1 then
		m_bit0=1
		m_bit1=0
		m_bit2=1
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 2 and Benutzer = 1 then
		m_bit0=0
		m_bit1=0
		m_bit2=1
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif

	'Benutzer 3
	if Ebene = 0 and Benutzer = 2 then
		m_bit0=1
		m_bit1=1
		m_bit2=0
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 1 and Benutzer = 2 then
		m_bit0=0
		m_bit1=1
		m_bit2=0
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 2 and Benutzer = 2 then
		m_bit0=1
		m_bit1=0
		m_bit2=0
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif

	'Benutzer 4
	if Ebene = 0 and Benutzer = 3 then
		m_bit0=0
		m_bit1=0
		m_bit2=0
		m_bit3=0
		m_bit4=1
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 1 and Benutzer = 3 then
		m_bit0=1
		m_bit1=1
		m_bit2=1
		m_bit3=1
		m_bit4=0
		m_bit5=1
		gosub WordOut
	endif
	if Ebene = 2 and Benutzer = 3 then
		m_bit0=0
		m_bit1=1
		m_bit2=1
		m_bit3=1
		m_bit4=0
		m_bit5=1
		gosub WordOut
	endif

	c_holdmem = 1
	high m_clk
	pause 10
	low m_wordclk

return

'Neutral-Programm (im Leerlauf)
Zurueck:
	high m_data
	high m_clk
	high m_wordclk

	c_run = 0
	c_funktion = 0
	c_save = 0
	c_ebene = 0
	c_user = 0
	c_speichern = 0

	Bus_out = 139

	'Memorybild senden
'	if Ausgang1 = 1 then Bus_out = 138
'	if Ausgang2 = 1 then Bus_out = 138
'	if Ausgang3 = 1 then Bus_out = 138

	gosub SendDisplay
return

'Datenausgabe 485-Bus
SendDisplay:
	high busrw ' Bus auf Schreiben
	hserout [Bus_out] ' Handschalter ansprechen
	while txsta.1 = 0
	wend	
	pauseus 7
	low busrw ' Bus auf Lesen
return

'Datenausgabe Magnetic-Schnittstelle
WordOut:
high m_clk
high m_wordclk

portb.0 = m_bit0
pause 10
low m_clk
pause 10
high m_clk
pause 10

portb.0 = m_bit1
pause 10
low m_clk
pause 10
high m_clk
pause 10

portb.0 = m_bit2
pause 10
low m_clk
pause 10
high m_clk
pause 10

portb.0 = m_bit3
pause 10
low m_clk
pause 10
high m_clk
pause 10

portb.0 = m_bit4
pause 10
low m_clk
pause 10
high m_clk
pause 10

portb.0 = m_bit5
pause 10
low m_clk
pause 10
high m_clk
pause 10


low m_wordclk

return

Und hier der Code des Slaves:

Code:
'Configuration bits
@ DEVICE pic16F873a, hs_osc, wdt_on, pwrt_on, bod_on, lvp_off, cpd_off, wrt_off, protect_on 

' Definitionen
define osc 4 ' Resonator 4 Mhz
include "modedefs.bas"


TRISC  = %10000000    ' PORTC.7 is the RX input
                      ' PORTC.6 is the TX output
' UART Definitionen
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 19200 ' 19200 Bauds
DEFINE HSER_CLOERR 1

' Port-Definitionen
adcon1 = 7 'Ports auf digital
p1 var portb.0'Pin 1
p2 var portb.1'Pin 2
p3 var portb.2'Pin 3
p4 var portb.3'Pin 4
p5 var portb.4'Pin 5
p6 var portb.5'Pin 6
p7 var portb.6'Pin 7
l1 var porta.0'Pin 8 LED 1
l3 var porta.1'Pin 9 LED 3
l5 var porta.2'Pin 10 LED 5
l2 var porta.3'Pin 11 LED 2 Rot
l4 var porta.4'Pin 12 LED 4 Grün
l6 var porta.5'Pin 13 LED 6 Gelb
l7 var portc.0'Pin 14 LED 7
'p15 vcc

ELEIN var portc.1
s1 var word'frei
s2 var word'Function
s3 var word'Hoch
s4 var word'Runter
s5 var word'frei
s6 var word'Pfeil
s7 var word'Benutzer
s8 var word'Memory
s9 var word'frei
s10 var word'frei

Bus_out var byte
zaehler var word
Bus_in var Byte
busrw var portc.5
'checksumme var byte

' Ports als Ein- bzw. Ausgang
input portb.0
input portb.1
input portb.2
input portb.3
input portb.4
input portb.5
input portb.6

output porta.0
output porta.1
output porta.2
output porta.3
output porta.4
output porta.5
output portc.0
output portc.1'Display



'----------------------------------------------------------------------------------
' Hauptprogramm
'----------------------------------------------------------------------------------
high ELEIN ' Display beim Einschalten aus
'high l1'LED beim Startem aus
high l2'LED beim Startem aus
'high l3'LED beim Startem aus
high l4'LED beim Startem aus
'high l5'LED beim Startem aus
high l6'LED beim Startem aus
'high l7'LED beim Startem aus


Schleife:
clearwdt
If PIR1.5 <>  1 Then goto Schleife'Zeichen in UART-Interrupt

'RCSTA.4 = 0
'RCSTA.4 = 1
' Zeichen liegt an UART an
Bus_in = RCREG

if Bus_in = 100 then gosub Taste ' Master fordert Tastendruck an
if Bus_in = 105 then gosub Power_on ' Master schaltet Hand/Säule ein
if Bus_in = 106 then gosub Power_off ' Master schaltet Hand/Säule aus
'if Bus_in = 110 then low l1'LED1 anschalten
'if Bus_in = 111 then high l1'LED1 ausschalten
if Bus_in = 112 then low l2'LED2 anschalten
if Bus_in = 113 then high l2'LED2 ausschalten
'if Bus_in = 114 then low l3'LED3 anschalten
'if Bus_in = 115 then high l3'LED3 ausschalten
if Bus_in = 116 then low l4'LED4 anschalten
if Bus_in = 117 then high l4'LED4 ausschalten
'if Bus_in = 118 then low l5'LED5 anschalten
'if Bus_in = 119 then high l5'LED5 ausschalten
if Bus_in = 120 then low l6'LED6 anschalten
if Bus_in = 121 then high l6'LED6 ausschalten
'if Bus_in = 122 then low l7'LED7 anschalten
'if Bus_in = 123 then high l7'LED7 ausschalten

Bus_in = 0
goto Schleife


'----------------------------------------------------------------------------------
' Unterprogramm Tastendruck ausgeben
'----------------------------------------------------------------------------------
Taste:
' Schalter auf Null setzen
s1=0
s2=0
s3=0
s4=0
s5=0
s6=0
s7=0
s8=0
s9=0
s10=0

' Ebene 1 abfragen (B4=1) S1, S4, S7, S10
high p5
low p6
low p7

'if p1 = 1 then s1 = 1
if p2 = 1 then s4 = 1
if p3 = 1 then s7 = 1
'if p4 = 1 then s10 = 1


' Ebene 2 abfragen (B5=1) S2, S5, S8
low p5
high p6
low p7

if p1 = 1 then s2 = 1
'if p2 = 1 then s5 = 1
if p3 = 1 then s8 = 1


' Ebene 3 abfragen (B6=1) S3, S6, S9
low p5
low p6
high p7

if p1 = 1 then s3 = 1
if p2 = 1 then s6 = 1
i'f p3 = 1 then s9 = 1


 
low p5
low p6
low p7

' Bus_out ausgeben

Bus_out = 099
zaehler = 0
if s1 = 1 then Bus_out=030:zaehler = zaehler +1
if s2 = 1 then Bus_out=031:zaehler = zaehler +1
if s3 = 1 then Bus_out=032:zaehler = zaehler +1
if s4 = 1 then Bus_out=033:zaehler = zaehler +1
if s5 = 1 then Bus_out=034:zaehler = zaehler +1
if s6 = 1 then Bus_out=035:zaehler = zaehler +1
if s7 = 1 then Bus_out=036:zaehler = zaehler +1
if s8 = 1 then Bus_out=037:zaehler = zaehler +1
if s9 = 1 then Bus_out=038:zaehler = zaehler +1
if s10 = 1 then Bus_out=039:zaehler = zaehler +1

if zaehler > 1 then Bus_out = 099
if s3 = 1 and s4 = 1 then Bus_out = 098

pauseus 7'???
high busrw
HSEROUT [Bus_out] ' Ausgabe des Tastendrucks auf UART
while txsta.1 <> 1 
wend
pauseus 14'????

low busrw
return


'----------------------------------------------------------------------------------
' Unterprogramm POWER ON
'----------------------------------------------------------------------------------

' Sub POWER_ON
Power_on:
		high ELEIN
return



'----------------------------------------------------------------------------------
' Unterprogramm POWER OFF
'----------------------------------------------------------------------------------

' Sub POWER_OFF
Power_off:
		low ELEIN
return

Hat jemand eine Idee, woran dieses Kommunikationsproblem liegen könnte?

Mfg,
Thorsten Wurm