Forum: Mikrocontroller und Digitale Elektronik RS485 geht nicht


von Roland H. (blacksmoke85)


Angehängte Dateien:

Lesenswert?

Hi und zwar habe ich grad ein Problem:

Schaltung besteht aus einem Attiny4313 und einem Max485. dieser soll 
daten an den pc senden. Das ganze soll später mit einem Protokoll 
implementiert werden das grob auch schon steht.

Folgende Fehler finde ich:

1. TX_EN, der die umschaltung am Max485 tun soll, verursacht probleme. 
dieser sendet z.B. nicht alle zeichen von "initial" oder auch nur 'l'

2. in der funktion rx_block() geht er nicht über die zeile

while (! (UCSRA & (1<<RXC)));    // warten bis zeichen da

nun wollte ich mit 2 grundfunktionen beide wege Rx und Tx testen.

als anhang habe ich nochmal die dateien

kann mir jemand helfen ?

 hier mein code:

main:

#include <avr/io.h>
#include <util/delay.h>
#include <ctype.h>
#include <stdio.h>
#include "define.h"
#include "rs485.h"

// -------------------- Main ---------------------
int main (void)
{
DDRD |= TX | TX_EN | LED_GR | LED_RT;  // Ausgänge configurieren
PORTD |= RX | Adr_Pin;          // interne Pull-ups für Eingänge 
//aktivieren
    uint8_t Data_Array[10] = {0,0,0,0,0,0,0,0,0,0}; // Daten-Array
  UART_init();
  _delay_ms(10);
  tx_block('i');
  tx_block('n');
  tx_block('i');
  tx_block('t');
  tx_block('i');
  tx_block('a');
  tx_block('l');
  tx_block('\r');
  while(1)
  {
    tx_block(rx_block());
    _delay_ms(50);
  }

  return 0;
}

dazu noch aus der rs485.c die beiden funktionen die benutzt werden

void tx_block(uint8_t to_send)
{
  PORTD |= TX_EN | LED_RT;           // MAX485 auf Senden + LED an
  while ( !(UCSRA & (1<<UDRE)) );    // Wait for empty transmit buffer
  PORTD &= ~TX_EN & ~LED_RT;         // MAX485 auf Empfang + LED aus
  UDR = to_send;                     // Start transmittion
}

uint8_t rx_block(void)
{
   while (! (UCSRA & (1<<RXC)));    // warten bis zeichen da
     tx_block('b');
      if(UCSRA & (1 << UPE))        // wenn Paritäts-Error
       {parity_error = 1; }           // Paritätsfehler vermerken
      }

  return UDR;
}

und hier die relevanten teile aus define.h

#define RX      (1<<PD0)    // IN
#define TX      (1<<PD1)    // OUT
#define TX_EN    (1<<PD2)    // OUT  wenn 1 : TX wenn 0 : RX
#define LED_GR  (1<<PD3)    // OUT
#define LED_RT   (1<<PD4)    // OUT
#define Adr_Pin  (1<<PD5)    // IN

#define baudrate        51    // 9600
#define FS       (1<<7)    // vorderstes bit (Bit 7) 
// im Uart-block ist Framestart
//als letztes habe ich hier noch die init funktion

void UART_init(void)
{
    // Set the USART baudrate registers
    UBRRH = (uint8_t)baud>>8;
    UBRRL = (uint8_t)baud;
    // --- UART Sender/Empfänger Freigabe 
---------------------------------
    UCSRB = (1<<RXEN)|(1<<TXEN);    // UART Receiver, Transmitter: on
    // --- UART Mode Select 
-----------------------------------------------
    // UMSEL = 0: UART Mode Select - Asynchron Mode
    // UPM0..1 = 10: UART Parity Mode - gerade Parity
    // USBS = 0: UART Stop Bit Select - 1 Stopbit
    // UCSZ0..1 = 11: UART Character Size - 8 Bit
    UCSRC=(0<<UMSEL)|(0<<UPM0)|(1<<UPM1)|(0<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
}

: Bearbeitet durch User
von Roland H. (blacksmoke85)


Lesenswert?

ok einen fehler hab ich selbst gefunden:

Ich darf bei den internen Pull-Ups natürlich nicht den RX mit aktivieren

Das löst aber nur das 1. problem. initial wird jetz vollständig 
gesendet. aber ein zeichen kommt nicht zurück wenn ich eins eingebe

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Das löst aber nur das 1. problem. initial wird jetz vollständig
>gesendet. aber ein zeichen kommt nicht zurück wenn ich eins eingebe

Hast du eine Schaltplan zu dem Programm? Was machen RX, TX, TX_EN.

MfG Spess

von Roland H. (blacksmoke85)


Angehängte Dateien:

Lesenswert?

ich benutze zum testen momentan noch ein pollinboard und den max auf 
einem breadboard.

von (prx) A. K. (prx)


Lesenswert?

Roland Höck schrieb:
> void tx_block(uint8_t to_send)
> {
>   PORTD |= TX_EN | LED_RT;           // MAX485 auf Senden + LED an
>   while ( !(UCSRA & (1<<UDRE)) );    // Wait for empty transmit buffer
>   PORTD &= ~TX_EN & ~LED_RT;         // MAX485 auf Empfang + LED aus
>   UDR = to_send;                     // Start transmittion
> }

Interessanter Ansatz: Driver einschalten und vor dem Absenden wieder 
ausschalten.

Üblicherweise schaltet man ein, sendet einen kompletten Frame, wartet 
bis das letzte Byte raus ist (TXC oder so) und schaltet dann wieder ab.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Interessanter Ansatz: Driver einschalten und vor dem Absenden wieder
>ausschalten.

Rate mal, weshalb ich gefragt habe?

MfG Spess

von Roland H. (blacksmoke85)


Angehängte Dateien:

Lesenswert?

oh du hast recht. g habs jetz unter der zeile UDR = to_send 
ausgeschaltet, aber funktionieren tuts immer noch nicht. das problem, 
war vorher schon, dass er über die zeile while(!(UCSRA & (1<<RXC))) 
nicht drüber hinaus

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Roland Höck schrieb:
> oh du hast recht. g habs jetz unter der zeile UDR = to_send
> ausgeschaltet, aber funktionieren tuts immer noch nicht.

Auch dann schaltest du den Driver bereits aus, bevor das Zeichen raus 
ist. Das dauert ja einen Weile.

von spess53 (Gast)


Lesenswert?

Hi

>Ich darf bei den internen Pull-Ups natürlich nicht den RX mit aktivieren

Was soll die Umschalterei zwischen RXD und Pin mit Pull-Up?

MfG Spess

von Roland H. (blacksmoke85)


Lesenswert?

also das ein und ausschalten von TX_EN wird später wieder geändert, da 
ja wie du schon sagst mehrere zeichen geschickt werden bevor der frame 
zu ende ist.
die pull ups brauch ich für nen ganz normalen eingang.
für z.B. Adr_Pin, der momentan noch nicht benutzt wird. RX ist da 
bereits wieder raus genommen, weil das ja ein UART eingang ist

von (prx) A. K. (prx)


Lesenswert?

spess53 schrieb:
> Was soll die Umschalterei zwischen RXD und Pin mit Pull-Up?

Umschalterei sehe ich keine. Aber einen RxD Pin, der sonst bei 
eingeschaltetem Driver floatet, weil DE=/RE. Da ergibt der Pullup 
durchaus Sinn.

von Roland H. (blacksmoke85)


Lesenswert?

wenn ich aber den RX eingang mit einem pull-up versehe versendet er mir 
nur noch "initia"

von (prx) A. K. (prx)


Lesenswert?

Roland Höck schrieb:
> also das ein und ausschalten von TX_EN wird später wieder geändert, da
> ja wie du schon sagst mehrere zeichen geschickt werden bevor der frame
> zu ende ist.

Schon, aber wenn du dir mal das bizarre Oszi-Diagramm von dem Kram 
ansehen würdest, dann wär die vmtl. klar, was da schief läuft. Dass die 
meisten Bytes funktionieren liegt nur daran, dass der Fehler vom 
nächsten Byte den Fehler im vorigen Byte deckt. Beim letzten Byte gibts 
aber niemanden mehr, der den Fehler in diesem Byte deckt. ;-)

Also nochmal en detail:

Driver einschalten.
do
   Auf UDRE warten
   Byte senden
until alle Bytes gesendet
Auf TXC warten.
Driver ausschalten.

: Bearbeitet durch User
von Roland H. (blacksmoke85)


Lesenswert?

funktioniert leider immer noch nicht

in meinem ersten test, wollte ich nur ein zeichen vom terminal schicken, 
das mit dann der tiny zurück schicken soll.  später werden natürlich 
erst alle zeichen geschickt und dann TX_EN wieder auf empfang. also hab 
ichs ungefähr so wie du geschrieben hast

pull-up für RX ein

TX_EN auf senden
warten auf UDRE
Byte senden
warten auf TXC
TX_EN auf empfang

aber es bleibt bei "initia"

und auch kein zeichen kommt zurück

ohne den pull-up für RX kommt zumindest das "initial" komplett an
mehr aber auch nicht

: Bearbeitet durch User
von Roland H. (blacksmoke85)


Lesenswert?

ahhh ich hab den fehler.
habe mein schlaues buch nochmal durchwühlt und nachdem TXC gekommen ist 
musste ich da noch ne 1 rein schreiben, damit das wieder gelöscht wird. 
nun gehts. nun versteh ich auch was du damit meinst, dass das letzte 
byte keine nachfolger mehr hat der den fehler ausbügeln kann

vielen dank

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.