RS485 geht nicht

OP #3432546
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);
}
Angehängte Dateien:
OP
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
Gast
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
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.
OP
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
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.
OP
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
OP
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.