RS485 Übertragung passt nicht

OP #5336388
Lesenswert?

Hallo Leute,
ich wollte einen RS485 Bus aufbauen.
Folgender Chip wird verwendet: ADM3485 und Atmega32.

Bisher hab ich nur meine Controller und einen RS485 auf USB Wandler 
dran.
Der wandler funktioniert da ich ihn auch mit anderen Geräten nutze.

Es muss also eher an der Software/Hardware liegen.

Wenn ich RX und TX vor dem ADM abgreife werden auch die richtigen 
Charakters gesendet. Nur auf den Bus kommt nix mehr an.
Folgenden Code verwende ich:
1
/* define CPU frequency in Mhz here if not defined in Makefile */
2
#ifndef F_CPU
3
#define F_CPU 8000000UL
4
#endif
5

6
/* 9600 baud   */
7
#define BAUD1 9600UL          // Baudrate
8
#define UBRR_VAL_UART ((F_CPU+BAUD1*8)/(BAUD1*16)-1)   // clever runden
9

10
//RS485 Definitionen***********************************************
11

12

13
#define TRANSMIT_CONF  DDRA|= (1<<DDA4)
14
#define TRANSMIT_ON    PORTA |= (1<<PA4)
15
#define TRANSMIT_OFF  PORTA &= ~(1<<PA4)
16

17

18
//************** RS485 Funktionen *********************************************************
19
void USART_Transmit( char data )
20
{
21

22
  /* Wait for empty transmit buffer */
23
  while ( !( UCSRA & (1<<UDRE)) )
24
    ;
25
  /* Put data into buffer, sends the data */
26
  UDR = data;
27
}
28

29

30
void USART_SendS(uint8_t *werte, uint8_t rep)
31
{
32
  //receive_string[0] = 1;
33
  uint8_t i;
34
  for(i=0;i<rep;i++)
35
  {
36
    TRANSMIT_ON;
37
    USART_Transmit(werte[i]);
38
  }
39
}
40

41
ISR(USART_TXC_vect)
42
{
43
  TRANSMIT_OFF;
44
}
45

46
void uart_putc(char c)
47
{
48
    TRANSMIT_ON;
49
    USART_Transmit(c);
50
}
51

52
    //USART initialisieren
53

54
    TRANSMIT_CONF; // Transmit Pin als Ausgang
55
  //USART0
56
    UBRRH = UBRR_VAL_UART >> 8;
57
    UBRRL = UBRR_VAL_UART& 0xFF;
58

59
    //USART0
60
    UCSRB |= (1<<TXEN);                // UART TX einschalten
61
    UCSRB |= (1<<RXEN);
62
    UCSRB |= (1<<RXCIE);
63
    UCSRB |= (1<<TXCIE);
64
    UCSRC |= (1<<URSEL)|(1<<UCSZ0)| (1<<UCSZ1);    // Asynchron 8N1
65

66
    //Sensor-Interrupts aktivieren
67
   // MCUCR |= (1<<ISC11) | (1<<ISC01); //fallende Flanke auf INT0 und INT1
68
   // MCUCSR &= ~(1<<ISC2);
69
   // GICR |= (1<<INT0) | (1<<INT1) | (1<<INT2);
70

71
    sei();
72
    uart_putc('O');
73
    uart_putc('K');

Es wird auch zwei Bytes empfangen aber anstatt OK bekomme ich XZ.

Ich sehe leider den Fehler nicht.

Kann mir jemand helfen?
Angehängte Dateien:
OP #5339762
Lesenswert?

Ich muss das Thema leider nochmal hoch holen.
Senden klappt ja soweit,
aber mit dem Empfangen habe ich so meine Probleme.
Das Hauptproblem ist, das ich ja alles was ich sende auch erstmal wieder 
empfange.
Das habe ich versucht schon mal raus zu nehmen.
Aber wenn ich dem Controller was schicke und dann in meiner Main 
auswerte dann kommt da Mist bei raus, bzw. wird mir ein Zählwert nicht 
richtig ausgegeben...
Blöd das ich keine jtag Schnittstelle habe...

Aber hier mal der Code, wahrscheinlich kann man das viel besser lösen 
aber ich habe leider keinen Ansatz...
1
//RS485 Definitionen***********************************************
2

3

4
#define TRANSMIT_CONF  DDRA|= (1<<DDA4)
5
#define TRANSMIT_ON    PORTA |= (1<<PA4)
6
#define TRANSMIT_OFF  PORTA &= ~(1<<PA4)
7

8
volatile uint8_t uart_transmit_progress = 0;
9
volatile uint8_t uart_r_array[10];
10
volatile uint8_t uart_back_read = 0;
11
volatile uint8_t u_rx_start = 0;
12
volatile uint8_t receive_max = 6;
13
volatile char u_receive_string[15];
14
volatile uint8_t u_r_c = 0; //Daten an UART empfangen
15

16
//************** RS485 Funktionen *********************************************************
17

18

19
void USART_Transmit( char data )
20
{
21

22
  /* Wait for empty transmit buffer */
23
  while ( !( UCSRA & (1<<UDRE)) )
24
    ;
25
  /* Put data into buffer, sends the data */
26
  UDR = data;
27
}
28

29
void uart_puts(char *s,uint8_t count)
30
{
31

32
  uint8_t i;
33
  uart_transmit_progress = 1;
34
    for (i=0;i<count;i++)
35
    {
36
      TRANSMIT_ON;
37
        USART_Transmit(s[i]);
38
        while(!(uart_back_read))
39
          ;
40
        uart_back_read = 0;
41
        u_rx_start=0;
42
    }
43
    uart_transmit_progress= 0;
44

45
}
46

47
ISR(USART_TXC_vect)
48
{
49
  TRANSMIT_OFF;
50
}
51

52
void uart_putc(char c)
53
{
54
    TRANSMIT_ON;
55
    USART_Transmit(c);
56
}
57

58
ISR(USART_RXC_vect)
59
{
60
  uint8_t i;
61
  if(uart_transmit_progress)
62
  {
63
    uart_r_array[u_rx_start] = UDR;
64
    uart_back_read=1;
65

66
    u_rx_start++;
67
  }
68
  else
69
  {
70

71

72
    //USART_Transmit(receive_string[i]);
73
    //USART_Transmit(i);
74
    i = u_rx_start;
75
    u_receive_string[i] = UDR;
76
    //lcd_putc(i);
77
    /*if (i==1)
78
        {
79
          if((u_receive_string[i]>>4)== 16)
80
          {
81
            receive_max = 10;
82
          }
83
          else
84
          {
85
            receive_max = 9;
86
          }
87
        }
88
        */
89
    if(i == receive_max)
90
    {
91
      u_rx_start=0;
92
      LED3_ON ;
93
      u_r_c = receive_max;
94
      //USART_Transmit('Z');
95

96
    }
97
    else
98
    {
99

100
      i++;
101
      u_rx_start = i;
102
    }
103
  }
104
}
105

106
int main(void)
107
{
108

109
  //Interrupt-Eingänge konfigurieren
110
  PORTD |= (1<<2);
111
  PORTD |= (1<<3);
112
  PORTB |= (1<<2) | (1<<3);
113

114

115
  //Taster pullup akitivieren
116
  TASTER_PULLUP |= (1<<TASTER_PIN);
117

118
  //LED-Ausgänge konfigurieren
119
  DDRA |= (1<<DDA7) | (1<<DDA6) | (1<<DDA5);
120

121

122
    //USART initialisieren
123

124
    TRANSMIT_CONF; // Transmit Pin als Ausgang
125
  //USART0
126
    UBRRH = UBRR_VAL_UART >> 8;
127
    UBRRL = UBRR_VAL_UART& 0xFF;
128

129
    //USART0
130
    UCSRB |= (1<<TXEN);                // UART TX einschalten
131
    UCSRB |= (1<<RXEN);
132
    UCSRB |= (1<<RXCIE);
133
    UCSRB |= (1<<TXCIE);
134
    UCSRC |= (1<<URSEL)|(1<<UCSZ0)| (1<<UCSZ1);    // Asynchron 8N1
135

136
    //Sensor-Interrupts aktivieren
137
   // MCUCR |= (1<<ISC11) | (1<<ISC01); //fallende Flanke auf INT0 und INT1
138
   // MCUCSR &= ~(1<<ISC2);
139
   // GICR |= (1<<INT0) | (1<<INT1) | (1<<INT2);
140

141
    sei();
142
    //uart_putc((uint8_t) receive_max);
143
    //uart_putc('O');
144
    //uart_putc('K');
145
    //Master_send_command(1,16,12312);
146

147

148

149

150

151

152

153
  /*********************************************************************/
154

155
  // Messung der Interruptdauer
156
      tmp =0;
157
      tmp =0;
158
      tmp =0;
159

160
  // Debug
161

162

163
      int16_t be3;
164
      uint8_t testv;
165
      testv = 0;
166
      uint8_t direction;
167
      direction = 1;
168

169
while(1)
170
{
171
  if(u_r_c) //Es wurden Daten empfangen
172
  {
173

174

175

176
    uart_putc((uint8_t) u_r_c);
177
    u_r_c = 0;
178
  }
179
}
180
}

Es wird mir dann zwar ein Byte gesendet, da steht aber 240 drin und 
nicht 6.
Ich übergebe ja in der Receive ISR einfach den Wert von receive_max und 
der ist mit 6 festgelegt.
Gast #5339798
Lesenswert?

Chris T. schrieb:
> Es wird mir dann zwar ein Byte gesendet, da steht aber 240 drin und
> nicht 6.

Das sieht nach abgeschaltetem Empfänger oder falsche Baudrate aus.

Wenn das Senden noch nicht klappt, hat es wenig Sinn, Empfangen zu 
wollen.

Bei manchen Controllern gibt es 1 Flag (mit Interrupt) für 
Transmit-Buffer leer (und damit ist der 1Byte-Fifo gemeint), und noch 
ein weiteres Flag für "jetzt ist das zeichen wirklich komplett mit allem 
versendet, mit Stopp und Pi pa po". Wenn du letzteres nicht hasst, 
brauchst Du eine Pause!
OP #5340745
Lesenswert?

Mein Problem ist ganz einfach das ich nichts richtig empfange.
Das Senden klappt.
Wie würde die Empfangsroutine aussehen damit ich das was ich empfangen 
habe in meiner Main Schleife wieder zurück senden kann...

Das ist das Problem.

Mit
1
u_r_c = receive_max;

wird ja einfach eine konstante in der Empfangsroutine auf die Variable 
geschrieben.

In meiner Main soll mir der Wert zurück gesendet werden, es wird aber 
ein anderer Wert als übergeben gesendet...
OP #5340943
Lesenswert?

Hat niemand ein eIdee woran es liegen könnte das mir der Wert nicht 
korrekt zurück gesendet wird?

Also eigenartig ist, wenn ich einzelne Zeichen mit Hterm sende, dann 
wird mir irgendwann wenn receive_max erreicht ist auch die passend 
eAntwort geliefert.
Wenn ich die Zeichen aber hinterienander eingebe und dann Enter drücke 
damit alle gesendet werden klappt das nicht, als ob er die nicht 
mitbekommt...

Muss irgendwie mit der Hardware zusammen hängen, jemand Ideen? Der 
Controller und RS485 Chip werden mit 3,3V versorgt.
Moderator Persönliche Seite #5341010
Lesenswert?

Chris T. schrieb:
> Hat niemand ein eIdee woran es liegen könnte das mir der Wert nicht
> korrekt zurück gesendet wird?

Hast Du Beitrag "Re: RS485 Übertragung passt nicht" überlesen?

Du setzt u_rx_start=0; nach jedem gesendeten Zeichen, obwohl u_rx_start 
der Index auf Deinen Receive-Buffer ist.

Wenn Du Dich sowieso nicht dafür interessierst, ob die gesendeten Daten 
identisch mit den empfangenen sind, dann ist die Lösung ganz einfach:

1. Verbindung von /RE zu GND unterbrechen
2. /RE mit DE verbinden

Dann kann der Transceiver während des Sendens nichts empfangen.
OP #5341058
Lesenswert?

Frank M. schrieb:
> Du setzt u_rx_start=0; nach jedem gesendeten Zeichen, obwohl u_rx_start
> der Index auf Deinen Receive-Buffer ist.

Ich weis das aber wenn ich nichts sende dann wird da auch nichts auf 
Null gesetzt. Ich empfange ja erstmal nur, und wenn die empfangenen 
Zeichen = receive_max sind dann wird ein Zeichen gesendet...


Also nach Reset sende ich das erste mal:
01 01 01 01 01 01 01 01 01 01
das sind 10 Zeichen
darauf hin kommt erstmal nichts zurück obwohl theoretisch receive_max 
erreicht sein sollte.

Dann sende ich nochmal
01 01 01 01 01 01 01 01 01 01

jetzt kommt als antwort: 7F

Dann sende ich nochmal:
01 01 01 01 01 01 01 01 01 01

jetzt kommt als Antwort endlich 09 was receive_max entspricht.

Wenn ich jetzt wieder sende dann kommt erst wieder nichts, dann 7F und 
dann wieder 09

...
Moderator Persönliche Seite #5341159
Lesenswert?

Chris T. schrieb:
> Hat niemand ein eIdee woran es liegen könnte das mir der Wert nicht
> korrekt zurück gesendet wird?

Chris T. schrieb:
> Ich weis das aber wenn ich nichts sende dann wird da auch nichts auf
> Null gesetzt.

Drück Dich mal klarer aus. Ersteres hört sich so an, als ob der µC sein 
eigenes Echo nicht empfängt: "nicht korrekt zurück gesendet wird".

Letzteres hört sich so an: "µC1 sendet, µC2 empfängt nichts."

Was denn nun? Wenn letzteres: A & B vertauscht?

Was wird empfangen? Nichts oder nur wenig oder nur Schrott?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren