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.
Durchreichen statt durchschleifen wäre genauer formuliert. Geht.
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
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.
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 | }
|
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)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.