mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 USART muss künstlich verlangsamt werden?


Autor: Max M. (maxmicr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,

ich arbeite mich gerade in den USART des STM32F103 ein. Übertragung von 
Daten funktioniert soweit, allerdings bin ich auf etwas seltsames 
Verhalten gestoßen. Und zwar zeigt mir mein Terminal Window (ich benutze 
das von Atmel Studio) nur die zu erwartenden Wörter an, wenn ich nach 
jedem übertragenen Zeichen einen Delay einlege, fällt der Weg, zeigt das 
Terminal nur noch bruchstückhafte Zeichen an. Das hier ist meine 
USART-Initialisierung:
void initUART(){
  RCC->APB2ENR |= (1<<2); //Port A clock enable

  GPIOA->CRH |= (0xB << 4); //Pin A9 as Alternative PP & 50MHz Output mode

  RCC->APB2ENR |= (1<<14); //USART1 Clock enable

  USART1->CR1 |= (1<<13); //Enable UART
  USART1->BRR = 72000000 / 14400; //72MHZ / 14400 BAUD
  USART1->CR1 |= (1<<3); //Enable Transmitter
}

So sehen die Funktionen zum Senden von Zeichen aus:
void sendChar(char c){
  while(USART1->SR & (0<<7)){ //Wait until data is transferred to shift register
    ;
  }
  USART1->DR = c;
  while(USART1->SR & (0<<6)){ //Wait until transmission is complete
    ;
  }
  delay(4500); //dieses Delay!
}

void sendString(const char *str){
  while(*str){
    sendChar(*str++);
  }
}

Hier findet sich auch das eben genannte Delay wieder. Die Funktion dazu 
sieht so aus:
void delay(long cycles){
  while(cycles > 0)
    cycles--;
}

So wird beispielsweise ein String gesendet:
char buffer[50];
uint32_t adcVal = getADCTempValue(16);
itoa((int)adcVal,buffer,10);
sendString(buffer);

Ich benutze 1 Start bit und 8 Datenbits, parity control ist deaktiviert. 
Ich bin für jeden Tipp dankbar!

Autor: Heiko G. (heikog)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Max M. schrieb:
> while(USART1->SR & (0<<7)){ //Wait until data is transferred to shift
> register
>     ;
>   }
>   USART1->DR = c;
>   while(USART1->SR & (0<<6)){ //Wait until transmission is complete
>     ;
>   }

Hallo!

Das sollte wohl jeweils (1<<6) oder (1<<7) sein, eine Null schieben 
bleibt ja Null (ich hab die Registerdefinitionen nicht überprüft).

Heiko

Autor: Max M. (maxmicr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko G. schrieb:
> Das sollte wohl jeweils (1<<6) oder (1<<7) sein, eine Null schieben
> bleibt ja Null (ich hab die Registerdefinitionen nicht überprüft).

Ich überprüfe dort den Zustand des Bits, zum Beispiel würde der Zustand 
0 des 6. Bits im SR-Register "Data is not transferred to shift 
register" entsprechen (das bedeutet für mich: Das Bit steckt noch fest, 
jetzt kann ich noch kein weiteres Datenpaket ins DR-Register laden). Ich 
hätte natürlich auch schreiben können:
while(!(USART1->SR & (1<<6)){
}

Das dürfte sich doch gleich bleiben, oder?

Edit: Okay, das ist nicht egal. Kam mir auch gerade beim überlegen.
Es funktioniert jetzt, danke Heiko für die schnelle Lösung!

: Bearbeitet durch User
Autor: rmu (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Heiko G. schrieb:
> while(USART1->SR & (0<<6))

Max M. schrieb:
> while(!(USART1->SR & (1<<6))

Max M. schrieb:
> Das dürfte sich doch gleich bleiben, oder?

der war gut.

(0<<6) ist 0, also wird aus ersterem while (USART1->SR & 0), das wird 
schon der compiler zum nop machen bzw. zu einer lese-op auf USART1->SR.

Autor: holger (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
>Das dürfte sich doch gleich bleiben, oder?

Nein.

>   while(USART1->SR & (0<<6)){ //Wait until transmission is complete

0 << 6 ist 0.
USART1->SR & 0 ist 0.

Die Schleife wird abgebrochen bevor alle Bits gesendet wurden.
Nur das Delay sorgt noch dafür das korrekt gesendet wird.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Max M. schrieb:
> Das dürfte sich doch gleich bleiben, oder?

Nö. Du musst trotzdem mit (1 << 6) die Maske bilden, die dann verundet 
wird mit dem Register.
Eine Maske aus (0 << 6) ist immer null - der verundete Ausdruck wird 
immer null sein.

Max M. schrieb:
> while(!(USART1->SR & (1<<6)){
> }

Das hingegen funktioniert wie erwartet. Wenn Bit 6 im USART0->SR 
Register  null ist, wird die Klammer wahr.

: Bearbeitet durch User
Autor: Heiko G. (heikog)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hallo!

Das ist nicht dasselbe, (0<<6) ist immer noch 0 (alle Bits auf 0), damit 
maskiert das 'Und' alle Bits weg, und die while-Schleifen werden gar 
nicht erst ausgeführt. Die Lösung mit dem !-Not sollte aber richtig 
sein.

Heiko

Autor: Max M. (maxmicr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hinweise, da hätte ich mal genauer überlegen sollen. Im 
ersten Moment kam mir das richtig vor :D

Heiko G. schrieb:
> Die Lösung mit dem !-Not sollte aber richtig
> sein.

Danke, funktioniert jetzt.

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.