Forum: Mikrocontroller und Digitale Elektronik LPC1768 UART Problem beim Senden/Empfangen mehrere Bytes


von hoxplus (Gast)


Lesenswert?

Hallo Leute,

ich habe derzeit ein Problem mit dem Senden und Empfangen mehrere Bytes 
über UART. Das Senden und Empfangen einzelner Bytes klappt. Das ist 
meine Methode zum Senden eines Bytes, was wie gesagt funktioniert:
1
int UART0_SendByte (int iData)
2
{
3
    while (!(LPC_UART0->LSR & 0x20));
4
    LPC_UART0->THR = iData;
5
}

Mit dieser Methode habe ich dann eine Funktion erstellt, die einen 
String senden soll, was nicht funktioniert. Das Problem ist, dass wenn 
ich  zum Beispiel eine String mit 16 Zeichen versende nur 13 ankommen 
und von denen nur die wenigsten stimmen
1
void UART0_SendString (unsigned char *s) 
2
{
3
    while (*s != 0) 
4
  {
5
       UART0_SendByte(*s++);
6
  }
7
}

Beim Empfangen ist das Problem, dass bei jedem empfangenen Byte der/das 
Interrupt gefeuert wird, obwohl ich mit:
1
LPC_UART0->FCR  |= 0x40;

das Triggern auf alle 4 Bytes gestellt habe.
Ich hoffe, dass ihr mir helfen könnt, da ich nicht allzu viel Erfahrung 
mit Mikrocontrollern habe. Ich bedanke mich im Voraus.

Viele Grüße!

von Jim M. (turboj)


Lesenswert?

hoxplus schrieb:
> Interrupt gefeuert wird, obwohl ich mit:
> LPC_UART0->FCR  |= 0x40;
>
> das Triggern auf alle 4 Bytes gestellt habe.

Du musst den FIFO auch einschalten (UM10360.pdf, Kapitel 14.4.6):
LPC_UART0->FCR  = 0x41;
oder
LPC_UART0->FCR  = 0x47;

hoxplus schrieb:
> Das Problem ist, dass wenn
> ich  zum Beispiel eine String mit 16 Zeichen versende nur 13 ankommen
> und von denen nur die wenigsten stimmen

Der gepostetet Sende-Code sieht OK aus. Was ist Deine Taktquelle? Was 
ist der Empfänger, könnte es bei dem einen FIFO Overrun geben?

von hoxplus (Gast)


Lesenswert?

Hallo,

erst einmal danke für deine Antwort! Zu ersterem: ich habe FIFO in meine 
Programm bereits in einer vorherigen Anweisung aktiviert, aber selbst 
wenn ich das ganze so wie du in eine Zeile schreibe, wird bei jedem Byte 
das Interrupt gefeuert. Zu zweitens: Der Empfänger ist ein Terminal 
Programm am PC, daher halt ich einen FIFO Overrun für sehr 
unwahrscheinlich. Die Kommunikation läuft über RS232. Am Programm liegt 
es nicht, da habe ich auch schon andere getestet.
Die Taktfrequenz liegt bei 1/4 des Systemtaktes. Ich poste mal meinen 
Code zum Initialisieren von UART, vielleicht liegt da ja ein Fehler
1
    uint16_t usFdiv;
2
    int pclk = SystemCoreClock / 4;
3
    
4
    LPC_SC->PCLKSEL0 &= ~(3<<6);
5
    LPC_SC->PCLKSEL0 |=  (0 << 6);              // PCLK_periph = CCLK/4
6
  
7
    LPC_PINCON->PINSEL0 |= (1 << 4);            // Pin P0.2 -> TXD0 
8
    LPC_PINCON->PINSEL0 |= (1 << 6);            // Pin P0.3 -> RXD0  
9
10
    LPC_UART0->LCR  = 0x83;                      // 8 bits, keine Parität, 1 Stop bit, DLAB = 1
11
  
12
    // setzen der Baudrate
13
    usFdiv = (pclk / 16) / UART0_BPS;            // 115200 S/s
14
    LPC_UART0->DLM  = usFdiv / 256;              
15
    LPC_UART0->DLL  = usFdiv % 256;             
16
  
17
    LPC_UART0->LCR  = 0x03;                     // 8 bits, keine Parität, 1 Stop bit, DLAB = 0            
18
    LPC_UART0->FCR  = 0x47;               // FIFO an, RX/TX buffer reset, Interrupt alle 4 Bytes
19
    LPC_UART0->IER  |= 0x01;                    // RBR Interrupt an
20
    NVIC_EnableIRQ(UART0_IRQn);                  // Interrupt registrieren

von hoxplus (Gast)


Lesenswert?

Hi,

mir ist gerade noch etwas aufgefallen: Wenn ich in einer while Schleife 
0x01 senden lasse, kommt am Terminal immer abwechselnd 0x01, 0x40 
ankommt. Wenn ich einen Delay befehl einfüge, kommen die Daten korrekt 
an. 0x01 = 0b00000001, 0x40 = 0b01000000. Daraus schließe ich, dass das 
THR Register noch nicht leer ist, oder dass im TX-FIFO was nicht stimmt.

von Jim M. (turboj)


Lesenswert?

hoxplus schrieb:
> LPC_SC->PCLKSEL0 &= ~(3<<6);
>     LPC_SC->PCLKSEL0 |=  (0 << 6);              // PCLK_periph = CCLK/4
>
>     LPC_PINCON->PINSEL0 |= (1 << 4);            // Pin P0.2 -> TXD0
>     LPC_PINCON->PINSEL0 |= (1 << 6);            // Pin P0.3 -> RXD0
>
>     LPC_UART0->LCR  = 0x83;                      // 8 bits, keine
> Parität, 1 Stop bit, DLAB = 1
>
>     // setzen der Baudrate
>     usFdiv = (pclk / 16) / UART0_BPS;            // 115200 S/s
>     LPC_UART0->DLM  = usFdiv / 256;
>     LPC_UART0->DLL  = usFdiv % 256;
>
>     LPC_UART0->LCR  = 0x03;                     // 8 bits, keine
> Parität, 1 Stop bit, DLAB = 0
>     LPC_UART0->FCR  = 0x47;

Zu viele magic numbers. Für den LPC17xx gibt es Header mit 
Bitdefinitionen.

Achung: PCLKSEL0 kann nicht geändert werden, sobald die PLL0 an ist. 
Siehe Errata.

hoxplus schrieb:
> Wenn ich in einer while Schleife
> 0x01 senden lasse, kommt am Terminal immer abwechselnd 0x01, 0x40
> ankommt.

Auch da stellt sich sofort die Frage nach der Taktquelle. Denn der 
LPC176x sendet Daten Back-to-Back, nach dem Stop- kommt sofort das 
nachste Startbit. Wenn der PC das nicht erkennt ist was in den 
Einstellungen (Baudrate, Datenbits, Parity) falsch.

Der FiFO im LPC17xx erlaubt einem sogar das hier:
1
 
2
 while (!(LPC_UART0->LSR & UART_LSR_THRE));
3
 LPC_UART0->THR = 'T';
4
 LPC_UART0->THR = 'e';
5
 LPC_UART0->THR = 's';
6
 LPC_UART0->THR = 't';
7
 LPC_UART0->THR = '\n';

Die interne 4 MHz IRC Taktquelle ist IMO nicht unbedingt genau genug, 
man sollte einen Quarz benutzen.

von hoxplus (Gast)


Lesenswert?

Hallo,

dein letzter Hinweis hat das Problem gelöst. In der Tat  ist der interne 
Takt nicht genau genug. Wenn ich nämlich die Baudrate reduziere 
funktioniert das Senden der Daten. Jetzt stellt sich eig. nur noch die 
Frage warum das mit dem Interrupt nicht so ganz funktioniert, aber so 
wichtig ist das jetzt auch nicht.
Ich bedanke mich schon mal sehr für die Hilfe!

Viele Grüße

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.