Forum: Mikrocontroller und Digitale Elektronik RS485 Schaltung funktioniert nicht


von Chris T. (chris0086)


Angehängte Dateien:

Lesenswert?

Moin Leute,
ich habe die Schaltung im Anhang hier aus dem Forum übernommen da ich je 
nach Bestückung RS232 oder RS485 kommunizieren will. Der RS232 Teil 
funktioniert wie er soll (D7 gebrückt, ohne R17).
Jetzt wollte ich mal den RS485 Teil auf einer anderen Platine testen, 
das heißt der ganze RS232 Teil ist nicht bestückt genauso wie R17 und D6 
da ich vorerst nur senden will.
Wie muss der Pegel an der Transmit Leitung sein damit ich senden kann?
Sollte die Schaltung denn so funktionieren? Der 75176 ist ein wenig 
warm.

Grüße Christian

von Mr. X (Gast)


Angehängte Dateien:

Lesenswert?

Ich war mal so frei ...

von spess53 (Gast)


Lesenswert?

Hi

Masseverbindung zur Gegenstelle vorhanden?

MfG Spess

von Chris T. (chris0086)


Lesenswert?

Hey, sorry für das Bild auf dem Kopf, kommt nicht wieder vor, ja 
Masseverbidung ist vorhanden. Die Transmitleitung wird aber noch nicht 
angesteuert, was muss diese denn für einen Pegel haben wenn ich etwas 
senden will?

von transmit (Gast)


Lesenswert?

Mein nicht vorhandenes Datenblatt des 75176 sagt die Leitung muß auf 
high liegen.

Etwas warm werden die 176 immer, sie verbrauchen auch gut Strom.

von Purzel H. (hacky)


Lesenswert?

Klopp den 75176 in die Tonne. Der verbrennt 40mA ohne etwas dafuer zu 
tun. Modernere Chips laufen mit zB 0.4mA.

von Stefan (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
> Masseverbindung zur Gegenstelle vorhanden?
>
> MfG Spess

wozu?
Stefan

von Kurt B. (kurt-b)


Lesenswert?

Stefan schrieb:
> spess53 schrieb:
>> Hi
>>
>> Masseverbindung zur Gegenstelle vorhanden?
>>
>> MfG Spess
>
> wozu?

Damit das Differenzsignal innerhalb des Arbeitsbereiches liegt.


 Kurt

von Stefan (Gast)


Lesenswert?

Kurt B. schrieb:
> Damit das Differenzsignal innerhalb des Arbeitsbereiches liegt.
>
>  Kurt

Inwiefern hat das Differenzsignal zwischen A und B einen Bezug zur 
Masse, solange ich mir meine saubere differentielle Übertragung nicht 
durch den meistens überflüssigen Bias versaue.

Stefan

von spess53 (Gast)


Lesenswert?

Hi

>Inwiefern hat das Differenzsignal zwischen A und B einen Bezug zur
>Masse, solange ich mir meine saubere differentielle Übertragung nicht
>durch den meistens überflüssigen Bias versaue.

Lies dir das

https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCQQFjAAahUKEwiOjuqet7jHAhUFPxoKHd0AC_A&url=http%3A%2F%2Fwww.ti.com%2Flit%2Fan%2Fsnla049b%2Fsnla049b.pdf&ei=Vy_WVc6GBYX-aN2BrIAP&usg=AFQjCNFP1T__GMeEkt8jhZLIrR7nFkPXBw

mal durch.

MfG Spess

von Chris T. (chris0086)


Lesenswert?

So ich melde mich denn mal zurück.
Ich habe nun den Schaltplan so umgesetzt bis auf D6. Ist die Diode denn 
notwendig wenn rein RS232 Receiver verbaut ist?

Der Sender sendet nun auch was er soll aber er bekommt was er gesendet 
hat auch direkt wieder zurück. Da ich einen Atmega162 verwende mit 2 
UARTS hab ich in der UART0 Empfangsroutine folgendes stehen:
1
ISR(USART0_RXC_vect)
2
{
3
  uint8_t dummy;
4
  dummy = UDR0;
5
  UART1_Transmit(dummy);
6
}
Das heißt alles was an UART0 ankommt wird parallel an UART1 ausgegeben.
Und nun bekomme ich im gleichen Moment das zurück was UART0 sendet. Das 
ist doch nicht normal oder?

Weiterhin kann ich nicht empfangen über RS485 liegt das an der fehlenden 
Diode und R17?

Grüße Christian

von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Chris T. schrieb:
> Der Sender sendet nun auch was er soll aber er bekommt was er gesendet
> hat auch direkt wieder zurück.

Der Empfangsteil des 75176 ist ja auch die ganze Zeit aktiv und liest 
das zurück, was du auf's Kabel gibst. Wenn du das verhindern möchtest, 
musst du das TRANSMIT Signal auch an Pin 2 (Rx Enable) des 75176 
anschließen -- bei high wird dann der Empfänger abgeschaltet. Das Signal 
darf erst wieder low werden, wenn das letzte Bit gesendet ist.

Sebastian

: Bearbeitet durch User
von Chris T. (chris0086)


Lesenswert?

Danke für die Ausführung, jetzt weis ich damit schon mal bescheid. Mache 
Grand meine ersten Gehversuche mit RS485 auf Hardwarelevel.(Sonst war 
immer ein Konverter dazwischen)
Gibt's denn noch Anmerkungen dazu das ich nichts empfangen kann?
Woran könnte das liegen?

Edit:
ICh empfange schon "etwas" aber das hat nicht viel mit den gesendeten 
Bytes zu tun, manchmal FF, FE, FD ...

Sollte ich mal R17 entfernen?

: Bearbeitet durch User
von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Wenn du nur RS485 bestückt hast, kannst du Pin 1 vom 75176 direkt mit 
dem AVR verbinden, D6 wird also überbrückt und kann entfallen. Ich nehme 
an, das meinst du?

Ob R17 vorhanden ist oder nicht sollte dann keine Rolle spielen.

von Chris T. (chris0086)


Lesenswert?

Ja das meine ich.

von rmf (Gast)


Lesenswert?

Bitte nicht übel nehmen, aber kann es sein das dir noch nicht bewußt ist 
das der RS485 so wie im Schaltplan dargestellt  eine sogenannte 
halbduplex Verbindung darstellt.
Das bedeutet es kann immer nur eine Sation geben die sendet und alle 
anderen haben geälligst nicht zu senden. (So wie früher, in der vor 
Handy zeit beim Funk)
Das bedeutet wenn du mit dem Senden fertig bist (und das Letzte Bit die 
UART verlassen hat) muss die TRANSMIT Leitung wieder auf null gesetzt 
werden.
Wenn mehrere Teilnehmer gleichzeitig den TRANSMIT auf 1 haben geht müll 
über die Leitung, und der wird auch prompt als solcher empfangen.

Ist jetzt einfach mal eine Vermutung weil du sagst RS485 ist für die was 
neues auf dieser Ebene. Viele Adapter machen das automatisch.

Udo

von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Sind A und B am 75176 richt herum angeschlossen? Sonst geht's auch 
nicht.

Hast du ein Oszilloskop? Ich würde TRANSMIT zum Testen fest auf 0 legen, 
von einem anderen RS485-Gerät Daten senden und mit dem Oszi die Rx 
Leitung am 75176 anschauen. Da muessten dann gueltige UART-Frames zu 
sehen sein.

Sebastian

: Bearbeitet durch User
von Chris T. (chris0086)


Lesenswert?

Hm ich hab jetzt mal die Transmitleitung gemessen, die ist immer high 
obwohl ich Sie eigentlich auf Low schalte. Jetzt zweifle ich aber auch 
die anderen Pins auf den Port bleiben high obwohl ich die auf low setze:
1
  DDRC = 0xFF;
2
  PORTC &= ~(1<<PC4);
3
PORTC &= ~(1<<PC5);
Alle Pins auf Ausgang und Pin4 und 5 auf low...


Edit: PIN3 kann ich schalten, 4 und 5 nicht, wird wohl am Prozessor 
liegen. Ich nehm mal ein anderen Pin für Transmit.

: Bearbeitet durch User
von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Welcher Prozessor? JTAG-Fuse aktiv?

von Chris T. (chris0086)


Lesenswert?

BINGO, Sebastian,
ich hab zwar die Pinbelegung vor mir aber hab nicht auf die alternativen 
Funktionen der Pins geachtet, man o man, Datenblatt lesen...

Also ich kann abwechselnd senden und empfangen aber nur wenn ich den 
Code ändere, wie lange vor dem Senden muss der Transmit Pin denn high 
sein?
Mit folgendem Code kann ich nur empfangen:
1
#define TR_DDR      DDRC
2
#define TR_PORT      PORTC
3
#define TR_PIN      3
4
5
6
int main(void)
7
{
8
  LED_DDR |= (1<<DDA0);
9
  LED_DDR |= (1<<DDA1);
10
  TR_DDR |= (1<<DDC3);
11
  TR_PORT |= (1<<TR_PIN);
12
  //Timer konfigurieren
13
  //stetige Wertanforderung
14
  TCCR1B |= (1<<CS12) | (1<<CS10); // standard = 9 Sekunden
15
  TCNT1 = 0; //29536; = 5 Sekunden
16
17
  
18
  LED_PORT |= (1<<LED1);
19
    //USART initialisieren
20
21
  //USART0
22
    UBRR0H = UBRR_VAL_ROTEL >> 8;
23
    UBRR0L = UBRR_VAL_ROTEL & 0xFF;
24
    //USART1
25
    UBRR1H = UBRR_VAL_KNX >> 8;
26
    UBRR1L = UBRR_VAL_KNX & 0xFF;
27
    //USART0
28
    UCSR0B |= (1<<TXEN0);                // UART TX einschalten
29
    UCSR0B |= (1<<RXEN0);
30
    UCSR0B |= (1<<RXCIE0);
31
    UCSR0C |= (1<<URSEL0)|(1<<UCSZ00)| (1<<UCSZ01);    // Asynchron 8N1
32
33
  //USART1
34
35
    UCSR1B |= (1<<TXEN1);                // UART TX einschalten
36
    UCSR1B |= (1<<RXEN1);
37
    UCSR1B |= (1<<RXCIE1);
38
    UCSR1C |= (1<<URSEL1)|(1<<UCSZ10)| (1<<UCSZ11);    // Asynchron 8N1
39
  USART_Transmit('A');
40
  UART1_Transmit('A');
41
42
43
  sei();          //activate Interrupts
44
    TIMSK |= (1<<TOIE1);
45
    while(1)
46
    {
47
      if(wert_anfordern == 1)    //Wertanforderung
48
      {
49
         TR_PORT |= (1<<TR_PIN);
50
        USART_Transmit('B');
51
        USART_Transmit('C');
52
        UART1_Transmit('K');
53
        wert_anfordern = 0;
54
         TR_PORT &= ~(1<<TR_PIN);
55
      }
56
    }
57
}
Wenn ich  TR_PORT &= ~(1<<TR_PIN); auskommentiere dann wird gesendet 
aber ich kann natürlich nicht mehr empfangen.

: Bearbeitet durch User
von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

Die Zeit zwischen TRANSMIT high und Senden steht im Datenblatt des 
75176, ist auf jeden Fall weniger als 100 ns. Ich denke nicht, dass das 
hier ein Problem ist.


Dein Code ist nicht vollständig. Wo kommt wert_anfordern her? Wann wird 
es gesetzt?


Wass willst du überhaupt erreichen?
Was für Geräte hängen am Bus? Wer sendet wann? Siehe Antwort von Udo 
oben, du musst dir den genauen Ablauf überlegen, wann gesendet und wann 
Empfangen werden soll. Aus dem Code lässt sich das nicht erkennen, weil 
der Empfangsteil fehlt.

Sebastian

von Chris T. (chris0086)


Lesenswert?

So hier mal der ganze Code:
Ich will erstmal nur langsam an den Bus heran. Der atmega senden ca. 
alle 10 Sekunden ein paar Bytes, zwischen dieser Zeit sollte ich ja auch 
antworten dürfen. Später gibt es nur einen Master der den Slave zum 
Daten senden auffordert.
1
#ifndef F_CPU        //define F_CPU if not done
2
#define F_CPU 7372800UL
3
#endif
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
#include <stdlib.h>
9
#include <string.h>
10
11
//#include "lcd-routines.h"
12
13
/* 9600 baud  KNX */
14
#define BAUD1 9600UL          // Baudrate
15
#define UBRR_VAL_KNX ((F_CPU+BAUD1*8)/(BAUD1*16)-1)   // clever runden
16
/* 19200 baud Kessel */
17
#define BAUD2 1200UL          // Baudrate
18
#define UBRR_VAL_ROTEL ((F_CPU+BAUD2*8)/(BAUD2*16)-1)   // clever runden
19
20
#define LED_DDR         DDRA
21
#define LED_PORT        PORTA
22
#define TR_DDR      DDRC
23
#define TR_PORT      PORTC
24
#define TR_PIN      3
25
26
#define LED1            0
27
#define LED2            1
28
//#define TRANSMIT_ON    PORTC |= (1<<PC3)
29
//#define TRANSMIT_OFF  PORTC &= ~(1<<PC3)
30
//Statusdefinition
31
32
#define INIT      0
33
#define READY      1
34
35
//Variablen
36
volatile uint8_t PTX;      //Global Variable
37
char itoabuffer[20];
38
volatile uint8_t receive_string[20];
39
volatile uint8_t wert_anfordern = 0;
40
41
void USART_Transmit( char data )
42
{
43
  /* Wait for empty transmit buffer */
44
  while ( !( UCSR0A & (1<<UDRE0)) )
45
    ;
46
  /* Put data into buffer, sends the data */
47
48
  UDR0 = data;
49
}
50
51
void UART1_Transmit( char data )
52
{
53
  /* Wait for empty transmit buffer */
54
  while ( !( UCSR1A & (1<<UDRE1)) )
55
    ;
56
  /* Put data into buffer, sends the data */
57
  UDR1 = data;
58
}
59
60
ISR(USART0_RXC_vect)
61
{
62
  uint8_t dummy;
63
  dummy = UDR0;
64
  UART1_Transmit(dummy);
65
}
66
67
ISR(USART1_RXC_vect)
68
{
69
  uint8_t i = 0;
70
  uint8_t dummy;
71
      dummy = UDR1;
72
}
73
ISR(TIMER0_OVF_vect)
74
{
75
76
}
77
ISR(TIMER1_OVF_vect)
78
{
79
  wert_anfordern = 1;
80
81
  //receive_complete = 0;
82
83
}
84
85
int main(void)
86
{
87
  LED_DDR |= (1<<DDA0);
88
  LED_DDR |= (1<<DDA1);
89
  TR_DDR |= (1<<DDC3);
90
  TR_PORT |= (1<<TR_PIN);
91
  //Timer konfigurieren
92
  //stetige Wertanforderung
93
  TCCR1B |= (1<<CS12) | (1<<CS10); // standard = 9 Sekunden
94
  TCNT1 = 0; //29536; = 5 Sekunden
95
96
  //Timer für senden von Dimmtelegrammen ein Durchlauf ist 0,010s
97
  TCCR0 |= (1<<CS02) | (1<<CS00);
98
99
  TCNT0 = 184; //
100
  LED_PORT |= (1<<LED1);
101
    //USART initialisieren
102
103
  //USART0
104
    UBRR0H = UBRR_VAL_ROTEL >> 8;
105
    UBRR0L = UBRR_VAL_ROTEL & 0xFF;
106
    //USART1
107
    UBRR1H = UBRR_VAL_KNX >> 8;
108
    UBRR1L = UBRR_VAL_KNX & 0xFF;
109
    //USART0
110
    UCSR0B |= (1<<TXEN0);                // UART TX einschalten
111
    UCSR0B |= (1<<RXEN0);
112
    UCSR0B |= (1<<RXCIE0);
113
    UCSR0C |= (1<<URSEL0)|(1<<UCSZ00)| (1<<UCSZ01);    // Asynchron 8N1
114
115
  //USART1
116
117
    UCSR1B |= (1<<TXEN1);                // UART TX einschalten
118
    UCSR1B |= (1<<RXEN1);
119
    UCSR1B |= (1<<RXCIE1);
120
    UCSR1C |= (1<<URSEL1)|(1<<UCSZ10)| (1<<UCSZ11);    // Asynchron 8N1
121
  USART_Transmit('A');
122
  UART1_Transmit('A');
123
124
125
  sei();          //activate Interrupts
126
    TIMSK |= (1<<TOIE1);
127
    while(1)
128
    {
129
      if(wert_anfordern == 1)    //Wertanforderung
130
      {
131
        TR_PORT |= (1<<TR_PIN);
132
        USART_Transmit('B');
133
        USART_Transmit('C');
134
        UART1_Transmit('K');
135
        wert_anfordern = 0;
136
        TR_PORT &= ~(1<<TR_PIN);
137
      }
138
    }
139
}

von Sebastian B. (sfreak) Benutzerseite


Lesenswert?

UART1_Transmit() wartet bis der Sendepuffer leer ist (Flag UDRE), 
schreibt dann ein neues Byte in den Sendepuffer und kehrt sofort zurück. 
Im Hintergrund schickt der UART nun langsam ein Bit nach dem anderen auf 
die Reise... während dein Programm parallel weiter läuft!

Wenn du also sowas schreibst...
1
UART1_Transmit('K');
2
TR_PORT &= ~(1<<TR_PIN);
...wird TRANSMIT mitten in der Übertragung abgeschaltet. Du brauchst 
etwas in dieser Richtung (Register auf deinen unbekannten Prozessor 
anpassen, ungetestet):
1
#define TRANSMIT_ON() ... // Setze 75176 Pins 2,3 HIGH
2
#define TRANSMIT_OFF() ... //  Setze 75176 Pins 2,3 LOW
3
4
// internal
5
void uart_put(unsigned char c)
6
{
7
    while (!(UCSRA & (1<<UDRE))); // warte bis Sendepuffer leer
8
    UDR = c;
9
}
10
 
11
void uart_putc(unsigned char c)
12
{
13
    TRANSMIT_ON();
14
    uart_put(c);
15
16
    // warte bis kompletter Frame gesendet
17
    while (!(UCSRA & (1<<TXC))); 
18
19
    TRANSMIT_OFF();
20
}
21
22
void uart_puts (char *s)
23
{
24
    //
25
    // Fuer vernuenftige Halbduplex-Kommunikation muesste hier 
26
    // erstmal gepueft werden, ob gerade Daten empfangen werden!
27
    // Nur wenn der Bus frei ist darf gesendet werden.
28
    //
29
30
    // 75176 in Sendemodus
31
    TRANSMIT_ON();
32
33
    while (*s)
34
    {
35
        uart_put(*s);
36
        s++;
37
    }
38
39
    // warte bis kompletter Frame gesendet
40
    while (!(UCSRA & (1<<TXC))); 
41
42
    // 75176 in Empfangsmodus
43
    TRANSMIT_OFF();
44
}

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

Zum Umschalten kann man auch TXC-Interrupt nutzen. Der wird ausgelöst, 
wenn das ein Byte vollständig gesendet wurde und im Sendepuffer der 
U(S)ART kein weiteres Byte vorhanden ist.

MfG Spess

von Chris T. (chris0086)


Lesenswert?

Danke an euch hab es jetzt so gelöst, jetzt funktioniert schon mal das 
senden und empfangen. Bei RS232 musste ich mir nie Gedanken ums senden 
machen, einfach übergeben und gut wars ;)
Naja jetzt kanns endlich weiter gehen.
Ich bedanke mich erst mal für die Hilfe hier.
1
#define TRANSMIT_ON    PORTC |= (1<<PC3)
2
#define TRANSMIT_OFF  PORTC &= ~(1<<PC3)
3
4
ISR(USART0_TXC_vect)
5
{
6
  TRANSMIT_OFF;
7
  UART1_Transmit('V');
8
}
9
void uart_putc(unsigned char c)
10
{
11
    TRANSMIT_ON;
12
    USART_Transmit(c);
13
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.