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


von Max M. (maxmicr)


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:
1
void initUART(){
2
  RCC->APB2ENR |= (1<<2); //Port A clock enable
3
4
  GPIOA->CRH |= (0xB << 4); //Pin A9 as Alternative PP & 50MHz Output mode
5
6
  RCC->APB2ENR |= (1<<14); //USART1 Clock enable
7
8
  USART1->CR1 |= (1<<13); //Enable UART
9
  USART1->BRR = 72000000 / 14400; //72MHZ / 14400 BAUD
10
  USART1->CR1 |= (1<<3); //Enable Transmitter
11
}

So sehen die Funktionen zum Senden von Zeichen aus:
1
void sendChar(char c){
2
  while(USART1->SR & (0<<7)){ //Wait until data is transferred to shift register
3
    ;
4
  }
5
  USART1->DR = c;
6
  while(USART1->SR & (0<<6)){ //Wait until transmission is complete
7
    ;
8
  }
9
  delay(4500); //dieses Delay!
10
}
11
12
void sendString(const char *str){
13
  while(*str){
14
    sendChar(*str++);
15
  }
16
}

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

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

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

von Heiko G. (heikog)


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

von Max M. (maxmicr)


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:
1
while(!(USART1->SR & (1<<6)){
2
}

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
von rmu (Gast)


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.

von holger (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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
von Heiko G. (heikog)


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

von Max M. (maxmicr)


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.

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.