www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega162 und beide UART's verwenden (Signale durchschleifen)


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich stelle mir gerade die Frage, ob es möglich ist, dass ich den ersten 
UART des ATmega162 mit einem MAX232 an den PC und den zweiten UART an 
einen weiteren Mikrocontroller anschließen könnte.
Der ATmega162 diene dann sozusagen nur als Signaldurchschleifer (oder 
Puffer).
Ich könnte mir vorstellen, dass es zu Datenkollisionen kommen könnte, 
darum müsste man ein definiertes Stop-Zeichen verwenden, z.B. eine 
Raute, damit der ATmega162 "weiß", wann er die gepufferten Daten an den 
anderen UART durchreichen muss.

Beispiel:
PC sendet qwertz#
ATmega162 liest die Daten mit und erkennt das Stop-Zeichen
erst danach reicht der ATmega162 die Daten an den anderen UART weiter
etc.

Ist dieses grundsätzlich (vorzugsweise in C programmiert) möglich?

Ich möchte mich nämlich mit den UART's beschäftigen, und wenn das 
"Durchreichen" klappt, soll z.B. mit einer LED angezeigt werden, wann 
ein Stop-Zeichen empfangen wurde.
Dieses dient erstmal nur als kleine Spielerei zum Lernen.

Autor: einer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Durchreichen statt durchschleifen wäre genauer formuliert.
Geht.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
durchreichen geht problemlos
der AVR ist dafür schnell genug das er noch weitaus viele sachen 
nebenher machen kann
du brauchst dafür nichtmal einen puffer


2x empfangsinterrupt (UART0 und UART1 )
eine senderoutine die schreibt fertig

in die ISR vom UART0 kommt ie senderoutine für UART1 und umgedreht
sobald ein zeichen kommt geht das sofort in den anderen UART rein

über terminierungen und all das brauchst die keine sorgen machen
egal was aufm UART kommt .. das geht immer weiter solange es ein 
gültiger wert ist  ... von 0x00 bis 0xFF

und selbst wenn es ein langer string wäre ...
dieser kommt ja auch nur als byte einzeln nacheinander eingetrudelt


ansonst wenn du puffern willst
einfach einen buffer[] nehmen

in der empfangsISR das byte in den buffer[] werfen und buffer 
incrementieren++

prüfen ob das byte dein '#' war .. wenn ja den buffer mit einer '\0' 
auffüllen
und diesen string in die andere UART werfen

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probleme beim "Durchreichen" gibt es doch nur, wenn die Baudraten 
unterschiedlich sind und dann auch nur, wenn die Datenmenge relativ hoch 
ist, so dass es bei einer Übertragung zu einem Puffer-Überlauf kommen 
kann.
Wenn beide Schnittstellen mit der gleichen Geschwindigkeit betrieben 
werden, sollte es kein Problem geben.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte sowas mal zum Testen des I-Bus bei meinem BMW gemacht.
PC<->UART0<->UART1<->I-Bus-Interface(TH3122)

#define F_CPU 14745460                      // Quarz 14.74546 MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <stdbool.h>

#define UBUFSIZE 64                        // Ringpuffergröße
#define UART1_RXOFF  UCSR1B = (1<<TXEN1);             // wird benötigt, da der TH3122 die Daten bounced
#define UART1_RXON  UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);  // dito

unsigned char uart0_buf[UBUFSIZE];                // UART0 Ringpuffer
unsigned char iptr0 = 0;                    // Eingangszeiger
unsigned char optr0 = 0;                    // Ausgangszeiger

unsigned char uart1_buf[UBUFSIZE];                // UART1 Ringpuffer  
unsigned char iptr1 = 0;                    // Eingangszeiger
unsigned char optr1 = 0;                    // Ausgangszeiger

ISR(USART0_RXC_vect)                      // ISR UART0
{
  uart0_buf[iptr0] = UDR0;                    // schiebe die empfangenen Daten in den Buffer
  iptr0++;
  if (iptr0 == UBUFSIZE) { iptr0 = 0; }            // den Bereich nicht verlassen
}

ISR(USART1_RXC_vect)                      // ISR UART1
{
  uart1_buf[iptr1] = UDR1;                    // schiebe die empfangenen Daten in den Buffer  
  iptr1++;
  if (iptr1 == UBUFSIZE) { iptr1 = 0; }            // den Bereich nicht verlassen
}


void uart0_putchar(char Data)
{
  while (!((UCSR0A) & (1<<UDRE0))) { }            // warte auf UART0 Sender            
  UDR0 = Data;                        // sende die Daten  
}

void uart1_putchar(char Data)
{
  while (!((UCSR1A) & (1<<UDRE1))) { }            // warte auf UART1 Sender
  UDR1 = Data;                        // sende die Daten  
}

unsigned char uart0_getchar()
{
    unsigned char c = uart0_buf[optr0];              // hole Daten und erhöhe den Zeiger
  optr0++;
  if (optr0 == UBUFSIZE) { optr0 = 0; }            // den Bereich nicht verlassen
  return c;                          // gebe Daten zurück
}

unsigned char uart1_getchar()
{
    unsigned char c = uart1_buf[optr1];              // hole Daten und erhöhe den Zeiger  
  optr1++;
  if (optr1 == UBUFSIZE) { optr1 = 0; }            // den Bereich nicht verlassen
  return c;                          // gebe Daten zurück
}

bool uart0_haschar()                      // Gebe 'true' zurück wenn Daten im Puffer sind
{
  return (iptr0 - optr0);                  
  
}

bool uart1_haschar()                      // Gebe 'true' zurück wenn Daten im Puffer sind
{
                    
  return (iptr1 - optr1);                  
    
}

void uart0_init(int BaudRate)
{
  int ubrr0 = (F_CPU / 16 / BaudRate - 1);          // Baudrate UART0 einstellen  
  UBRR0H = (unsigned char)(ubrr0>>8);
  UBRR0L = (unsigned char)ubrr0;
         
  UCSR0C = (1<<URSEL0)|(3<<UCSZ00);              // UART0 Frame Format einstellen: 8data, 1 Stop-bit, keine Parity 
  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1 << RXCIE0);        // UART0 Receiver und Transmitter einschalten
}

void uart1_init(int BaudRate)
{    
  int ubrr1 = (F_CPU / 16 / BaudRate - 1);          // Baudrate UART1 einstellen  
  UBRR1H = (unsigned char)(ubrr1>>8);
  UBRR1L = (unsigned char)ubrr1;

  UCSR1C = (1<<URSEL1)|(3<<UCSZ10)|(1<<UPM11);        // UART1 Frame Format einstellen: 8data, 1 Stop-Bit, even Parity 
  UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);          // UART1 Receiver und Transmitter einschalten 
}

bool uart1_ibusclear()                      // Prüfen ob I-Bus im Leerlauf
{
  long long i;
  for (i=0;i<25000;i++)                     // i-Wert abhängig von F_CPU
  {
    
    if ( (PINB & (1<<PINB1)) )                // für ca.1,5ms lang prüfen, ob SEN/STA Pin des TH3122 low ist
    {
      return 0;
    }
  }
  return 1;                          // wenn ja, dann: I-Bus ist im Leerlauf
}

void uart1_sendibus(char *msg)                  // sende I-Bus-Nachricht
{
            

  for (;;)                          // Schleife bis alles gesendet wurde
  {    
    if (uart1_ibusclear())                  // wenn I-Bus im Leerlauf
    {
      UART1_RXOFF                      // schalte UART1 Empfang aus
      while (*msg != '\0')
      {
        char tmp = *msg++;                // hole ein Byte aus dem RAM
        uart1_putchar(tmp);                // und sende es    
      }                
      UART1_RXON                      // schalte UART Empfang ein
      return;
    }
  }  
}

int main()                            // Hauptprogramm

{
                                // Port-Pins einstellen, abhängig von der Schaltung
  PORTA =0xFF;
  DDRA = 0x00;                 
  
  PORTE =0xFF;
  DDRE = 0x00;
  
  PORTC = 0xFF;
  DDRC = 0x00;
  
  PORTB =0b11111111;
  DDRB = 0b00001001;
  
  PORTD =0b11111010;
  DDRD = 0b00000110;                      //------------

  sei();                            // Interrupts einschalten

  uart1_init(9600);                      // USART's initialisieren (Baudrate auf 9600 )
  uart0_init(9600);

  while (1)                          // Daten von USART0 nach USART1 und zurück
  {
    if (uart0_haschar())
    {
      char tmp[2];
      tmp[0] = uart0_getchar();
      tmp[1] = '\0';
      uart1_sendibus(tmp);
    }

    if (uart1_haschar())
    {
      uart0_putchar(uart1_getchar());
    }
  }

  cli();
  return 0;
}


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo @ll.
Das hört sich richtig gut an. freu
Die Baudrate ist übrigens festgelegt.

@Gast (der mit dem Quellcode):
Wenn ich den Code richtig verstehe, werden nur die Daten (also 
Zeichenweise gemäß der Übertragungseinstellung 8N1) durchgereicht?
D.h. man könnte statt den I-Bus-Controller (bzw. Mikrocontroller) auch 
einfach einen MAX232 oder einen MAX485 dahinter hängen?!

Könntest du mir bitte in den folgenden Zeilen '\0' erklären:
      char tmp[2];
      tmp[0] = uart0_getchar();
      tmp[1] = '\0';
      uart1_sendibus(tmp);

Vielen Dank!

Ich werde jetzt mal eine kleine Platine zusammenlöten und dann sehen wir 
weiter... :o)

Autor: Andy (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin gerade beim Bau der Schnittstelle und möchte mit einem Bild 
zeigen, wie ich das angeschlossen habe bzw. anschließen werde.

Ich habe mich entschieden einen MAX485 an den zweiten UART zu hängen, da 
ich nur noch einen MAX232 zur Verfügung hatte.
An den MAX485 (A/B) kann ich erstmal LED's hängen, damit ich sehe, dass 
sich etwas tut.
Außerdem habe ich noch einen alten Computer, der eine 
RS485-Schnittstelle hat, vielleicht lasse ich dann die LED's am MAX485 
weg und schließe mal direkt den alten Rechner an den RS485-Bus an...

Sieht das soweit schon gut aus?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.