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


von Andy (Gast)


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.

von einer (Gast)


Lesenswert?

Durchreichen statt durchschleifen wäre genauer formuliert.
Geht.

von gast (Gast)


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

von STK500-Besitzer (Gast)


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.

von Gast (Gast)


Lesenswert?

Ich hatte sowas mal zum Testen des I-Bus bei meinem BMW gemacht.
PC<->UART0<->UART1<->I-Bus-Interface(TH3122)
1
#define F_CPU 14745460                      // Quarz 14.74546 MHz
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
#include <string.h>
7
#include <stdbool.h>
8
9
#define UBUFSIZE 64                        // Ringpuffergröße
10
#define UART1_RXOFF  UCSR1B = (1<<TXEN1);             // wird benötigt, da der TH3122 die Daten bounced
11
#define UART1_RXON  UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);  // dito
12
13
unsigned char uart0_buf[UBUFSIZE];                // UART0 Ringpuffer
14
unsigned char iptr0 = 0;                    // Eingangszeiger
15
unsigned char optr0 = 0;                    // Ausgangszeiger
16
17
unsigned char uart1_buf[UBUFSIZE];                // UART1 Ringpuffer  
18
unsigned char iptr1 = 0;                    // Eingangszeiger
19
unsigned char optr1 = 0;                    // Ausgangszeiger
20
21
ISR(USART0_RXC_vect)                      // ISR UART0
22
{
23
  uart0_buf[iptr0] = UDR0;                    // schiebe die empfangenen Daten in den Buffer
24
  iptr0++;
25
  if (iptr0 == UBUFSIZE) { iptr0 = 0; }            // den Bereich nicht verlassen
26
}
27
28
ISR(USART1_RXC_vect)                      // ISR UART1
29
{
30
  uart1_buf[iptr1] = UDR1;                    // schiebe die empfangenen Daten in den Buffer  
31
  iptr1++;
32
  if (iptr1 == UBUFSIZE) { iptr1 = 0; }            // den Bereich nicht verlassen
33
}
34
35
36
void uart0_putchar(char Data)
37
{
38
  while (!((UCSR0A) & (1<<UDRE0))) { }            // warte auf UART0 Sender            
39
  UDR0 = Data;                        // sende die Daten  
40
}
41
42
void uart1_putchar(char Data)
43
{
44
  while (!((UCSR1A) & (1<<UDRE1))) { }            // warte auf UART1 Sender
45
  UDR1 = Data;                        // sende die Daten  
46
}
47
48
unsigned char uart0_getchar()
49
{
50
    unsigned char c = uart0_buf[optr0];              // hole Daten und erhöhe den Zeiger
51
  optr0++;
52
  if (optr0 == UBUFSIZE) { optr0 = 0; }            // den Bereich nicht verlassen
53
  return c;                          // gebe Daten zurück
54
}
55
56
unsigned char uart1_getchar()
57
{
58
    unsigned char c = uart1_buf[optr1];              // hole Daten und erhöhe den Zeiger  
59
  optr1++;
60
  if (optr1 == UBUFSIZE) { optr1 = 0; }            // den Bereich nicht verlassen
61
  return c;                          // gebe Daten zurück
62
}
63
64
bool uart0_haschar()                      // Gebe 'true' zurück wenn Daten im Puffer sind
65
{
66
  return (iptr0 - optr0);                  
67
  
68
}
69
70
bool uart1_haschar()                      // Gebe 'true' zurück wenn Daten im Puffer sind
71
{
72
                    
73
  return (iptr1 - optr1);                  
74
    
75
}
76
77
void uart0_init(int BaudRate)
78
{
79
  int ubrr0 = (F_CPU / 16 / BaudRate - 1);          // Baudrate UART0 einstellen  
80
  UBRR0H = (unsigned char)(ubrr0>>8);
81
  UBRR0L = (unsigned char)ubrr0;
82
         
83
  UCSR0C = (1<<URSEL0)|(3<<UCSZ00);              // UART0 Frame Format einstellen: 8data, 1 Stop-bit, keine Parity 
84
  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1 << RXCIE0);        // UART0 Receiver und Transmitter einschalten
85
}
86
87
void uart1_init(int BaudRate)
88
{    
89
  int ubrr1 = (F_CPU / 16 / BaudRate - 1);          // Baudrate UART1 einstellen  
90
  UBRR1H = (unsigned char)(ubrr1>>8);
91
  UBRR1L = (unsigned char)ubrr1;
92
93
  UCSR1C = (1<<URSEL1)|(3<<UCSZ10)|(1<<UPM11);        // UART1 Frame Format einstellen: 8data, 1 Stop-Bit, even Parity 
94
  UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);          // UART1 Receiver und Transmitter einschalten 
95
}
96
97
bool uart1_ibusclear()                      // Prüfen ob I-Bus im Leerlauf
98
{
99
  long long i;
100
  for (i=0;i<25000;i++)                     // i-Wert abhängig von F_CPU
101
  {
102
    
103
    if ( (PINB & (1<<PINB1)) )                // für ca.1,5ms lang prüfen, ob SEN/STA Pin des TH3122 low ist
104
    {
105
      return 0;
106
    }
107
  }
108
  return 1;                          // wenn ja, dann: I-Bus ist im Leerlauf
109
}
110
111
void uart1_sendibus(char *msg)                  // sende I-Bus-Nachricht
112
{
113
            
114
115
  for (;;)                          // Schleife bis alles gesendet wurde
116
  {    
117
    if (uart1_ibusclear())                  // wenn I-Bus im Leerlauf
118
    {
119
      UART1_RXOFF                      // schalte UART1 Empfang aus
120
      while (*msg != '\0')
121
      {
122
        char tmp = *msg++;                // hole ein Byte aus dem RAM
123
        uart1_putchar(tmp);                // und sende es    
124
      }                
125
      UART1_RXON                      // schalte UART Empfang ein
126
      return;
127
    }
128
  }  
129
}
130
131
int main()                            // Hauptprogramm
132
133
{
134
                                // Port-Pins einstellen, abhängig von der Schaltung
135
  PORTA =0xFF;
136
  DDRA = 0x00;                 
137
  
138
  PORTE =0xFF;
139
  DDRE = 0x00;
140
  
141
  PORTC = 0xFF;
142
  DDRC = 0x00;
143
  
144
  PORTB =0b11111111;
145
  DDRB = 0b00001001;
146
  
147
  PORTD =0b11111010;
148
  DDRD = 0b00000110;                      //------------
149
150
  sei();                            // Interrupts einschalten
151
152
  uart1_init(9600);                      // USART's initialisieren (Baudrate auf 9600 )
153
  uart0_init(9600);
154
155
  while (1)                          // Daten von USART0 nach USART1 und zurück
156
  {
157
    if (uart0_haschar())
158
    {
159
      char tmp[2];
160
      tmp[0] = uart0_getchar();
161
      tmp[1] = '\0';
162
      uart1_sendibus(tmp);
163
    }
164
165
    if (uart1_haschar())
166
    {
167
      uart0_putchar(uart1_getchar());
168
    }
169
  }
170
171
  cli();
172
  return 0;
173
}

von Andy (Gast)


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:
1
      char tmp[2];
2
      tmp[0] = uart0_getchar();
3
      tmp[1] = '\0';
4
      uart1_sendibus(tmp);

Vielen Dank!

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

von Andy (Gast)


Angehängte Dateien:

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?

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.