Forum: Mikrocontroller und Digitale Elektronik UART to I2C Schleife so richtig?


von Chris (Gast)


Lesenswert?

Hallo,

ich benötige eine Schleife die Daten auf dem UART annimmt und direkt 
unverändert weiterschickt.

Der UART soll mit einer Baudrate von 38400 laufen. Der I2C Bus läuft mit 
100khz.

Ich dachte also daran das Zeichen an den UART zu senden, eine ISR 
auszulösen die das Zeichen per I2C weiter schickt und dann wieder das 
nächste Zeichen usw.

Ist das ganze dann so richtig?

Das ist mein erster Versuch mit dem UART. Es kommt ein ATMega128 mit 
16Mhz externem Quarz zum Einsatz.

Die uart.c Datei
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "uart.h"
5
#include "i2c.h"
6
7
8
void uart_init(void)
9
{
10
11
  UBRR0H = (BAUDRATE>>8);
12
    UBRR0L = BAUDRATE;
13
    UCSR0B|= (1<<TXEN) | (1<<RXEN) | (1<<RXCIE0);
14
    UCSR0C|= (1<<UCSZ0) | (1<<UCSZ1);
15
16
}
17
18
ISR(USART0_RX_vect)
19
{
20
  char data = UDR0;
21
  i2c_write(data);
22
}

Die uart.h Datei
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define BAUD  38400L
5
#define BAUDRATE  ((F_CPU)/(BAUD*16UL)-1)
6
7
void uart_init(void);

Ich danke euch schonmal

von Falk B. (falk)


Lesenswert?

Prinzipiell ja, praktisch nein. Bei der I2C Kommunikation gibt es 
üblicherweise ein Protokoll. Mindestens muss man zuerst ein I2C_Start + 
Adresse erzeugen und die Antwort abwarten, erst dann kann man Daten mit 
I2C_write() senden. Am Ende kommt ein I2c_Stop();

Fürs Erste macht man das besser ohne Interrupts nur mit Polling, das 
reicht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chris schrieb:
> Das ist mein erster Versuch mit dem UART.
Dann würde ich zum Testen auf das empfangene Zeichen 1 draufaddieren und 
es wieder über den UART zurück schicken...

von Christian B. (christian_buchner)


Lesenswert?

Die uart.c Datei
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "uart.h"
5
#include "i2c.h"
6
7
int sendstart = 1;
8
9
void uart_init(void)
10
{
11
  UBRR0H = (BAUDRATE>>8);
12
  UBRR0L = BAUDRATE;
13
  UCSR0B|= (1<<TXEN) | (1<<RXEN) | (1<<RXCIE0);
14
  UCSR0C|= (1<<UCSZ0) | (1<<UCSZ1);
15
}
16
17
ISR(USART0_RX_vect)
18
{
19
  if(sendstart == 1)
20
    {
21
        i2c_start(DISPLAY_ADDRESS+I2C_WRITE);
22
        sendstart = 0;
23
    }
24
  char data = UDR0;
25
  i2c_write(data);
26
 }

Um zu testen ob der UART auch funktioniert hatte ich mir dir Zeichen 
zurückgeben lassen. Klappte super. Dann habe ich testweise Daten in ein 
Array geschrieben die dann LEDs bei einer 1 einschalten und bei einer 0 
ausschalten. Schicke ich eine 1 oder 0 mit HTerm gingen die LEDs an oder 
aus. Perfekt. Uart funktioniert. Also zurück zur ISR. Das i2c start 
eingefügt, und was passiert? Nichts passiert.

Auf dem Display läuft ein Bootloader. Sobald also die "flashendaten" 
kommen zeigt das Display das Grafisch an. Aber wenn ich nun die 
Flashdaten für das Display so wie oben sende macht das Display 
garnichts.

Ich verstehe das nicht :(

von Falk B. (falk)


Lesenswert?

@  Christian Buchner (christian_buchner)

>Die uart.c Datei

Schön. Aber ohne die main.c eher sinnlos.

>ausschalten. Schicke ich eine 1 oder 0 mit HTerm gingen die LEDs an oder
>aus. Perfekt. Uart funktioniert.

Gut.

>Also zurück zur ISR. Das i2c start
>eingefügt, und was passiert? Nichts passiert.

Teste erstmal ohne UART. Sende in main eine gültige Datensequenz von 
vielleich 10 Bytes. Die müssen angezeigt werden.

>Ich verstehe das nicht :(

Ich schon. Es gibt einen Fehler, der darauf wartet gefunden zu werden 
;-)

von Christian B. (christian_buchner)


Lesenswert?

Wie soll ich das denn ohne testen? Also ich bekomme ein *.DF file vom 
KitEditor (eaDIPTFT Kompilier) und dieses *.DF file muss nun 1 zu 1 vom 
PC zum uC und vom uC über I2C zum Display.

Die i2c Kommunikation mit dem Display funktioniert auch tadelos. Es geht 
aber eben darum das Display zu flashen und somit muss er das weiter 
geben.

LCD-Module sagte mir ich soll das DF File nicht weiter beachten sondern 
es einfach im *.hex Format schicken. Ok, aber wo stelle ich das für 
Dateien in HTerm ein?

Verbindung ist wie folgt:

PC -> USB zum UM232R -> UART -> ATMega128 -> I2C -> Display

Also sicherstellen kann ich das die Verbindung PC <-> ATMega128 also 
UART funktioniert.

Ebenfalls das dass i2c zwischen ATMega128 und Display funktioniert.

Es muss also an UART <-> I2C liegen.

von Falk B. (falk)


Lesenswert?

@ Christian Buchner (christian_buchner)


>Wie soll ich das denn ohne testen? Also ich bekomme ein *.DF file vom
>KitEditor (eaDIPTFT Kompilier) und dieses *.DF file muss nun 1 zu 1 vom
>PC zum uC und vom uC über I2C zum Display.

Öffne die Datei mit einem HEX-Editor und kopier die ersten 10 Bytes in 
deinen Quelltext.

>LCD-Module sagte mir ich soll das DF File nicht weiter beachten sondern
>es einfach im *.hex Format schicken. Ok, aber wo stelle ich das für
>Dateien in HTerm ein?

AHA! Hier könnte ein Missverständnis vorliegen. Poste mal die Datei als 
Anhang.

>Es muss also an UART <-> I2C liegen.

Ja.

von Christian B. (christian_buchner)


Angehängte Dateien:

Lesenswert?

Ich sitze gerade im Zug von Hessen nach NRW. Da ist das bisschen schwer 
g In meiner Cloud habe ich leider nur die Controller codes. Irgendwie 
muss man 3 Std Zugfahrt ja nutzen. Da kann man die Zeit bestens dafür 
nutzen.

Ich hatte die Datei für das Display aber mal mit einem HEX Editor 
geöffnet. Im Anhang kannst du sehen was er mir da angezeigt hat.

Ich bin gegen 17Uhr zuhause dann kann ich die Datei mal hier hochladen. 
Vll kriegst du sie ja "besser" geöffnet.

: Bearbeitet durch User
von Christian B. (christian_buchner)


Angehängte Dateien:

Lesenswert?

So, wie angekündigt hier dann mal die DF Datei.

von holger (Gast)


Lesenswert?

>Also zurück zur ISR. Das i2c start
>eingefügt, und was passiert? Nichts passiert.

Wenn deine I2C Routinen mit Interrupts arbeiten
kann auch nichts passieren. Wenn du im USART0_RX_vect
Interrupt bist, sind alle Interrupts gesperrt.

Da man aber den kompletten Code nicht sieht ist das
mal wieder nur geraten.

von Falk B. (falk)


Lesenswert?

Nun ja, in der Datei stehen am Anfang ein paar normale Kommandos, dann 
kommen viele Binärdaten. Eigentlich sollte man die Daten einfach direkt 
auf das LCD schreiben können, (nach der I2C Adresse) und es sollte 
funktionieren. Ich wiederhole mich. Vergiss erstmal den UART-RX 
Interrupt, den brauchst du hier so oder so nicht, weil deine CPU nichts 
anderes macht als Daten vom UART an den I2C zu senden. Man muss die 
Datei einfach mittels HTERM oder ähnlichem Programm senden. 
Hyperterminal und andere, "normale" Terminalprogrammer (Teraterm, Putty) 
etc. gehen möglicherweise NICHT, weil die möglicherweise extra 
Steuerzeichen mit einfügen. Man müsste auf dem LCD was sehen, wenn es 
losgeht, denn die Befehle schalten auf das Terminalfenster um.

Etwas so.
1
void uart_init(void)
2
{
3
  UBRR0H = (BAUDRATE>>8);
4
  UBRR0L = BAUDRATE;
5
  UCSR0B|= (1<<TXEN) | (1<<RXEN);
6
  // keine Interrupts
7
  UCSR0C|= (1<<UCSZ0) | (1<<UCSZ1);
8
}
9
10
// im main
11
12
  int timeout=0;
13
14
  i2c_start(DISPLAY_ADDRESS+I2C_WRITE);
15
16
  while(1) {
17
    if (UCSR0A & (1<<RXC0)) {
18
      i2c_write(UDR0);
19
      timeout=0; 
20
    } else {
21
      _delay_us(150); // ~ 1/2 Zeichen warten @38400 Baud
22
      timeout++;
23
    }
24
    if (timeout > 1000) break;
25
  }
26
27
  i2c_stop();


Wenn das alles nicht klappt, sollte man zumindest den Anfang der Datei 
mal im Controller als String senden, das MUSS gehen. Wenn nicht, klemmt 
dein I2C.
1
"#MS0;#AA0;#YA0;#VA0;#EA0;#DL;#TC0;#FT8,0;#TE#TW2,1,1,100,30;program eDIPTFT70-A\r\n\nNismo Car-Soft v1#TP2000,$4000;#TP169556,$2ADF;#FB4,3,8;#BM0;#BR1,0,64,799,90,0,165,1;#BR2,0,64,799,90,0,165,1;"

von Christian B. (christian_buchner)


Lesenswert?

Also mein Programm macht nichts ausser eine RTC auslesen und aufs 
Display schreiben. DS1307. Klappt perfekt.

Die funktion für die Uhr deaktiviert.

Versucht per UART zu flashen. Nix.

Deinen Code versucht. Nix

Emails gecheckt. Ah, eine E-Mail von Electronic Assembly:
.....
.....
Ihr Code stimmt soweit. Das muss klappen. Haben sie auch Pin 17 am 
Display auf LOW geschaltet und somit das SmartProtokoll deaktiviert? 
Andernfalls möchte das Display noch ein DC1 sowie die länge wie beim 
normalen Einsatz des Displays auch
.....
.....

Ok, also Pin17 auf LOW gelegt, meinen Code mit dem ISR geflasht. Nix

Deinen Code geflasht und siehe da, das Display wird geflasht.

Nur warum funktioniert dein Code aber meiner mit der ISR nicht?

Und das hätte EA auch mal irgendwo beschreiben können das man den Pin 
auf Low legen muss.

Deren FAQ:
1
FLASH updaten ohne PC und Kit Compiler
2
Frage:
3
Ich setze in einem Gerät das Display EA eDIPTFT43 ein. Derzeit muss ich es vor dem Einbau mit dem Programmer programmieren. Will ich nachträglich etwas verändern, muss ich es ausbauen und neu programmieren.Das ist recht umständlich. Alle anderen Microkontrollersysteme in dem Gerät kann ich derzeit im eingebauten Zustand über entsprechende Bootloader programmieren, nur das Display nicht.
4
Gibt es eine Möglichkeit, wie ich ein Data-Flash-Upload-File *.df über die Schnittstelle in den Flash bekomme? Ich benutze derzeit die I²C-Schnittstelle.
5
6
Antwort:
7
Der Flash-Speicher in den EA eDIP-Modulen kann auch ohne Ausbauen mit neuen Makros, Bildern etc. beschrieben werden. Das geht ganz einfach.
8
Beispiel: Ihr Mikrokontroller spricht via I²C-Bus mit dem EA eDIP. Außerdem ist der Mikrokontroller per RS-232 mit dem PC, auf dem die DF-Datei (*.df) liegt, verbunden.
9
Jetzt schicken Sie die *.df-Datei vom PC zu Ihrem µC, der diese unverändert an das eDIP weiterreicht. Fertig.
10
Wenn Sie das Smallprotokoll verwenden, muss Ihr µC natürlich die Häppchen der *.df-Datei im Protokollrahmen verpackt an das EA eDIP senden.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Christian Buchner (christian_buchner)

>Ok, also Pin17 auf LOW gelegt,

Das hätte ja auch vorher schon so sein müssen. Oder hast du das 
Smallprotokoll mit Checksum benutzt?

>meinen Code mit dem ISR geflasht. Nix

Du hast hier nie vollständigen Code gepostet. Dort steckt wahrscheinlich 
ein KLITZEKLEINER Fehler. sei() vergessen?

>Deinen Code geflasht und siehe da, das Display wird geflasht.

AHA!

>Nur warum funktioniert dein Code aber meiner mit der ISR nicht?

Weil ich ich bin ;-)

>Und das hätte EA auch mal irgendwo beschreiben können das man den Pin
>auf Low legen muss.

Steht doch drin, wenn gleich nicht explizit. Sollte man ändern.

>Außerdem ist der Mikrokontroller per RS-232 mit dem PC, auf dem die >DF-Datei 
(*.df) liegt, verbunden.
>Jetzt schicken Sie die *.df-Datei vom PC zu Ihrem µC, der diese >unverändert an 
das eDIP weiterreicht. Fertig.

Stimmt auch, wenn das Pin auf LOW liegt.

>Wenn Sie das Smallprotokoll verwenden,

 = Pin auf HIGH!

> muss Ihr µC natürlich die Häppchen >der *.df-Datei im Protokollrahmen >verpa

Ist ein typisches Problem von Betriebsblindheit, die wissen wie es geht 
und denken nicht DAU-artig.

Schick mal deinen VOLLSTÄNDIGEN Code als Anhang, den Fehler finden wir 
schon.

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.