PDA

View Full Version : RS485 bus - starting probem



wurm
- 26th January 2010, 21:21
Hi!

I´ve got a problem with the communication between two pic16f873a connected via a rs485 bus.
The master sends a request to the slave and the slave answers which key is pressed. At the beginning of the program the masters sends some data to turn on some leds on the slave.
This works most time fine.
But sometimes when the devices get power the communicatoin fails.
The master works (there are some leds on it), but the slave doesn´t turn on the leds and there´s no communication.

I think the problem is that there is a serial buffer overrun at the start of the devices because there are some characters on the bus produced through power up.

Hope somebody has an idea to solve my problem.


Here is the master 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

...
return


And here is the slave 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
...

return

Cobra_Phil
- 27th January 2010, 04:25
Running 19200 baud from a 4 Mhz osc, isn't that kind of pushing it a bit?

Charles Linquis
- 27th January 2010, 04:50
You can easily run that baud rate if you use the hardware serial port, but why are you reading the receive register directly?
Why not use HSERIN?

wurm
- 27th January 2010, 09:48
Where is the difference between reading the receive register by x = rcreg or hserin?
Does hserin do a little more than only shift the receive buffer in a variable?

Charles Linquis
- 27th January 2010, 13:35
Not much more - if you are receiving only one byte, but it does a good job of checking CREN and clearing it, if necessary. That is something your code doesn't do and the hardware doesn't automatically clear the bit. The CLOERR define in your header does nothing in your case.