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
Lesezeichen