PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Byte über RS485 schlägt fehl



BlaueLed
01.03.2007, 19:56
Hallo,

ich habe 2 Module mit je einem SN751768 RS485 Treiber. Ich versuche mit folgenden Codes ein Byte von einem zum anderen Modul zu übertragen:

Empfänger :



'----------------- CPU Config ---------------------------
$regfile = "m16def.dat"
$crystal = 8000000
$baud = 1200
'--------------- Portdefinition ------------------------
Config Porta = Output
Config Portb = Output
Config Portd.7 = Input
Config Portd.6 = Input
Config Portc = Output
Config Portd.2 = Output
'---------------------------------------- LCD ----------------------------------
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
'----------------------------------- Timer --------------------
Enable Interrupts
'-------------- Alias -----------------------------------
Led1 Alias Porta.7
Led2 Alias Porta.6
Led3 Alias Porta.5
Led4 Alias Porta.4
Backlight Alias Portb.4
Rs485 Alias Portd.2
'-------------------------- RS485 -----------------------
Rs485 = 0
On Urxc Onrxd
Enable Urxc
'-------------------- Dims ---------------------------
Dim Wert As Byte
'------------------- Main -------------------------------
Cls
Cursor Off Noblink
Backlight = 1
Led2 = 1
Led3 = 1
Led4 = 1
'-------------------- Hauptprogramm ---------------
_start:
nop
Goto _start
'---------- Einlesen ----------
Onrxd:
Inputbin Wert
Locate 1 , 1
Lcd Wert
Return

Sender :



'------------------------ CPU Config -------------------------
$regfile = "m8def.dat"
$crystal = 8000000
$baud = 1200
'------------------------ Port Config --------------------------
Config Portb = Output
Config Portd.2 = Output
'------------------------ Alias ----------------------------------
Rs485 Alias Portd.2
'-------------------------- Subs -------------------------------

'--------------------------- RS485 -------------------------------
Rs485 = 0
Enable Interrupts
'----------------------------- Dims ------------------------------
Dim I As Byte
I = &B11111111
'---------------------------------- Mainprogramm ------------------
Main:

Rs485 = 1

Print I
Do
Loop Until Ucsra.txc = 1
Set Ucsra.txc

Rs485 = 0

Wait 1

Goto Main


Nur leider zeigt mein Display beim Empfänger nur "105" egal was ich mache, werden nur 3 Zeichen angezeigt. Könnte bitte mal jemand drüber schauen, ob ich einen Fehler gemacht habe ?

mfg BlaueLed

PS: Abschlusswiderstände von je 160 Ohm habe ich an A und B

Stromi
01.03.2007, 23:49
Schau dir mal das Beispiel imSamble\serial-Verzeichnis von Bascom an.
Da wird in der Interuproutine ein Flag gesetzt, ein Buffer ausgelesen und im Loop abgefragt:

SERINT.BAS

'--------------------------------------------------------------------
' SERINT.BAS
' (c) 1999-2005 MCS Electronics
' serial interrupt example for AVR
' also look at CONFIG SERIALIN for buffered input routines
'--------------------------------------------------------------------
$regfile = "m88def.dat"
$baud = 19200
$crystal = 8000000

Const Cmaxchar = 20 'number of characters

Dim B As Bit 'a flag for signalling a received character
Dim Bc As Byte 'byte counter
Dim Buf As String * Cmaxchar 'serial buffer
Dim D As Byte

'Buf = Space(20)
'unremark line above for the MID() function in the ISR
'we need to fill the buffer with spaces otherwise it will contain garbage

Bc = 0
Print "Start"

On Urxc Rec_isr 'define serial receive' ISR
Enable Urxc 'enable receive isr



Enable Interrupts 'enable interrupts to occur

Do
If B = 1 Then 'we received something
Disable Serial
Print "{" ; Buf ; "}" 'print buffer
Print "BC:" ; Bc 'print character counter


'now check for buffer full
If Bc = Cmaxchar Then 'buffer full
Buf = "" 'clear
Bc = 0 'rest character counter
End If

Reset B 'reset receive flag
Enable Serial
End If
Loop

Rec_isr:
D = Udr 'read UDR only once
Print "*" ' show that we got here
If Bc < Cmaxchar Then 'does it fit into the buffer?
Incr Bc 'increase buffer counter

If D = 13 Then 'return?
Buf = Buf + Chr(0)
Bc = Cmaxchar 'at the end
Else
Buf = Buf + Chr(d) 'add to buffer
End If


' Mid(buf , Bc , 1) = Udr
'unremark line above and remark the line with Chr() to place
'the character into a certain position
'B = 1 'set flag
End If
B = 1 'set flag
Return

BlaueLed
02.03.2007, 15:58
danke für den Tip. werde das mal probieren.

mfg Kay

Vitis
02.03.2007, 19:16
deine Inputroutine ist nicht besonders sinnvoll.
da brauchste kein input, weil ein Zeichen wurde empfangen,
du kannst also das Register UDR mit dem Bytewert direkt auslesen

Tempbyte=UDR

ach so, der Interrupt heißt dann URXC

BlaueLed
03.03.2007, 14:11
@Vitis,

habe nunmal deinen Tip ausprobiert. Folgenden Code verwende ich nun :



'-------------------------- RS485 -----------------------
Rs485 = 0
On Urxc Onrxd
Enable Urxc
'-------------------- Dims ---------------------------
Dim Wert As Byte
'------------------- Main -------------------------------
Cls
Cursor Off Noblink
Locate 1 , 1
Lcd "Testempfang"
Backlight = 1
Led2 = 1
Led3 = 1
Led4 = 1
'-------------------- Hauptprogramm ---------------
_start:
nop
Goto _start
'---------- Einlesen ----------
Onrxd:
Wert = Udr
Locate 2 , 1
Lcd Wert
Return


das lcd zeigt mir aber immer noch "105". also keine Veränderung. Ich sende doch "11111111". Wieso bekomme ich dann "105" ? komische Sache. Haste vielleicht noch nen tip für mich ?

mfg Kay

Vitis
03.03.2007, 19:12
dann stimmt vermutlich die Baudrate nicht,
oder A und B Leitung vertauscht.

Checke

crystal
baud
und Fuse Einstellungen.

BlaueLed
03.03.2007, 19:32
also A und B sind richtig.
beide megas stehen auf internal 8 Mhz RC
baud ist bei beiden 1200
in Bascom ist ja auch Crystal = 8000000 eingestellt.

ich komm momentan einfach nicht dahinter, was da falsch läuft. Hatte noch nie so probleme mit RS485.

mfg Kay

BlaueLed
05.03.2007, 13:11
habe meinen Code jetzt mal umgestrickt auf das Senden und Empfangen von Strings. Codes sehen folgendermaßen aus :

Sender :


'------------------------ CPU Config -------------------------
$regfile = "m8def.dat"
$crystal = 1000000
Baud = 1200
'------------------------ Port Config --------------------------
Config Portb = Output
Config Portd.2 = Output
'------------------------ Alias ----------------------------------
Rs485 Alias Portd.2
'-------------------------- Subs -------------------------------

'--------------------------- RS485 -------------------------------
Rs485 = 0
Enable Interrupts
'----------------------------- Dims ------------------------------
Dim Wert As String * 4
'---------------------------------- Mainprogramm ------------------
Main:

Rs485 = 1

Print "test"
Do
Loop Until Ucsra.txc = 1
Set Ucsra.txc

Rs485 = 0

Wait 3

Rs485 = 1

Print "abcd"
Do
Loop Until Ucsra.txc = 1
Set Ucsra.txc

Rs485 = 0

Wait 3

Goto Main


und Empfänger :



----------------- CPU Config ---------------------------
$regfile = "m16def.dat"
$crystal = 1000000
$baud = 1200
'--------------- Portdefinition ------------------------
Config Porta = Output
Config Portb = Output
Config Portd.7 = Input
Config Portd.6 = Input
Config Portc = Output
Config Portd.2 = Output
'---------------------------------------- LCD ----------------------------------
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
'----------------------------------- Timer --------------------
Enable Interrupts
'-------------- Alias -----------------------------------
Led1 Alias Porta.7
Led2 Alias Porta.6
Led3 Alias Porta.5
Led4 Alias Porta.4
Backlight Alias Portb.4
Rs485 Alias Portd.2
'-------------------------- RS485 -----------------------
Rs485 = 0
On Urxc Onrxd
Enable Urxc
'-------------------- Dims ---------------------------
Dim Wert As String * 4
'------------------- Main -------------------------------
Cls
Cursor Off Noblink
Locate 1 , 1
Lcd "Testempfang"
Backlight = 1
Led2 = 1
Led3 = 1
Led4 = 1
'-------------------- Hauptprogramm ---------------
_start:

Goto _start
'---------- Einlesen ----------
Onrxd:
Input Wert
Locate 2 , 1
Lcd Wert
Return

Jetzt habe ich folgendes Phänomen :

Wenn ich den Empfänger einschalte, dann zeigt er mit beim ersten empfang korrekt den Text "test" auf dem lcd an. Sendet der Sender dann abcd, kommt beim empfänger am lcd nur "#abc" und dann wieder "#tes". Also nur beim einschalten funktioniert es einwandfrei. Kann da was mit dem Buffer nicht stimmen ? Im Anhang sind noch zwei Bilder. Beim ersten klappt es nicht, da kommt ein wirres Zeichen und dann die restlichen 3 Buchstaben. Beim zweiten klappt es einwandfrei.

mfg Kay

raggy
05.03.2007, 17:50
Hallo ,Ich würde vor dem umschaten Des Rs485 IC auf Empfang,
wait 1, oder waitms 100 oder ausprobieren Einfügen .die daten könnten eventuell noch nicht raus sein!
Gruß raggy

BlaueLed
05.03.2007, 19:40
@raggy:

danke für den Tip, hat aber leider nicht geklappt.

@all :
habe jetzt mal folgendes gemacht:

dim wert as String * 6

jetzt bekomme ich alles angezeigt, aber immer mit diesem komischen wirren Zeichen am anfang.

mfg Kay

raggy
05.03.2007, 21:22
Versuche das mal so zB Print "raggy";
ansonsten kommen die steuerzeichen für neue Zeile mit glaube chr(10)
chr(13)
raggy

raggy
05.03.2007, 21:43
$regfile = "m32def.dat"
$crystal = 8000000
$baud = 9600
Config Portc = Output

Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcd = 40 * 2

Dim Test As String * 10



Portc.0 = 0


Cls ' Clear the LCD display



Do

Inputbin Test


Locate 1 , 1
Lcd Test



Loop




$regfile = "m32def.dat"
$crystal = 8000000
$baud = 9600

'Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.5 , Rs = Portc.4
'Config Lcd = 40 * 2

Config Portc = Output

Portc.0 = 1 ' RS485 Treiber auf senden

Do

Print "AVR-Atmega" ;
Wait 1


Loop


also oben erst senden, dann Empfang. zum Testen ob der Bus in Ordnung ist! Hab ich auch erst so probiert.Ist zwar nicht schön Programiert aber es muss so klappen.
Gruß raggy

BlaueLed
05.03.2007, 22:06
@raggy:

Du bist mein Retter. es fehlte natürlich das ;

habe noch ne kleine andere Frage. Ich werte einen SRF02 Ultraschall Sensor aus. Den SRF02 lese ich folgendermaßen aus :





'------------------------ CPU Config -------------------------
$regfile = "m8def.dat"
$crystal = 1000000
$baud = 1200
$framesize = 42
$swstack = 42
$hwstack = 42
'------------------------ Port Config --------------------------
Config Portb = Output
Config Portd.2 = Output
Config Scl = Portc.5
Config Sda = Portc.4
Const Srf02_slaveid = &HE0
'------------------------ Alias ----------------------------------
Led1 Alias Portb.0
Led2 Alias Portb.1
Led3 Alias Portb.2
Led4 Alias Portb.3
Rs485 Alias Portd.2
'-------------------------- Subs -------------------------------

'--------------------------- RS485 -------------------------------
Rs485 = 0
Enable Interrupts
'----------------------------- Dims ------------------------------
Dim Entfernung As Integer
Dim V As Byte
'----------------------- Funcitons -------------------------
Declare Function Srf02_firmware(byval Slaveid As Byte) As Byte
Declare Function Srf02_entfernung(byval Slaveid As Byte) As Integer
'------------------------- Boot ---------------------------------
Wait 1
I2cinit
V = 1
Waitms 100
'---------------------------------- Mainprogramm ------------------
Main:
Entfernung = Srf02_entfernung(srf02_slaveid)
Waitms 100
Rs485 = 1

Print Entfernung ;
Do
Loop Until Ucsra.txc = 1
Set Ucsra.txc



Rs485 = 0

Wait 2

Goto Main
'--------------------------------- SRF_02 ------------------------------------------
Function Srf02_firmware(byval Slaveid As Byte) As Byte
Local Firmware As Byte
Local Slaveid_read As Byte

Slaveid_read = Slaveid + 1

I2cstart
I2cwbyte Slaveid
I2cwbyte 0 'Leseregister festlegen
I2cstop

I2cstart
I2cwbyte Slaveid_read
I2crbyte Firmware , Nack
I2cstop

Srf02_firmware = Firmware
End Function



Function Srf02_entfernung(byval Slaveid As Byte) As Integer
Local Lob As Byte
Local Hib As Byte
Local Firmware As Byte
Local Temp As Byte
Local Slaveid_read As Byte

Slaveid_read = Slaveid + 1

'Messvorgang in starten
I2cstart
I2cwbyte Slaveid
I2cwbyte 0
I2cwbyte 81 'in Zentimetern messen
I2cstop


Warteaufmessung:
Waitms 1
Firmware = Srf02_firmware(slaveid)
If Firmware = 255 Then Goto Warteaufmessung

I2cstart
I2cwbyte Slaveid
I2cwbyte 2 'Leseregister festlegen
I2cstop


I2cstart
I2cwbyte Slaveid_read
I2crbyte Hib , Ack
I2crbyte Lob , Nack
I2cstop


Srf02_entfernung = Makeint(lob , Hib)
End Function


ich übertrage ja den integerwert. auf der Empfängerseite wird mir aber nicht die cm angezeigt sondern wieder wirres Zeug. Kann ich denn von Integer nach String wandeln um es zu übertragen ?

mfg Kay

raggy
05.03.2007, 22:28
seh mal das Forum hier durch, hab da mal was gelesen.damit habe ich mich noch nicht befast.
gruß raggy viel Glück.