Guten Abend allerseits
Ich hab mal wieder eine neue Frage zum STM32. Ich initialisiere gerade
die USART des Controllers mit folgender Funktion:
1
voidinitCOM(){
2
//Initialize USART for comunication
3
//Enable USART3 clock
4
RCC->APB1ENR|=RCC_APB1ENR_USART3EN;
5
//Set baudrate 45MHz/390,625 => 115,2kBd
6
COM->BRR|=(0x186<<USART_BRR_DIV_Mantissa_Pos);
7
COM->BRR|=0b1010;
8
9
//Set oversampling to 8x-oversampling
10
COM->CR1|=USART_CR1_OVER8;
11
12
//Set wordlenght databits to 8
13
COM->CR1&=~USART_CR1_M;
14
15
//Disable parity control
16
COM->CR1&=~USART_CR1_PCE;
17
18
//Select parity mode
19
//COM -> CR1 &= ~USART_CR1_PS;
20
21
//Enable interrupt if TX is empty or RX is'nt empty
22
COM->CR1|=USART_CR1_PEIE;
23
COM->CR1|=USART_CR1_TXEIE;
> COM -> CR1 |= USART_CR1_RXNEIE;
1
//Enable transmitter and reciver
2
COM->CR1|=USART_CR1_TE;
3
COM->CR1|=USART_CR1_RE;
4
5
//Select stopbits => 1 stopbit
6
COM->CR2&=~USART_CR2_STOP_0;
7
COM->CR2&=~USART_CR2_STOP_1;
8
9
//Enable CTS/RTS
10
COM->CR3|=USART_CR3_CTSE;
11
COM->CR3|=USART_CR3_RTSE;
12
}
Es geht mir um die Zeile
COM -> CR1 |= USART_CR1_RXNEIE;
Ich möchte eigentlich einen Interrupt generieren wenn ein Byte
fertiggesendet wurde (nichtblockierendes Senden). Aber sobald das
Programm an dieser Zeile steht, springt es sofort in die
IRQ-Handler-Funktion. Dabei ist die USART nichtmal aktiviert.
Wie macht ihr das...Interrupts nur bei Bedarg aktivieren? Das wäre zwar
eine Möglichkeit, jedoch erscheint mir das häufige Herumfuhrwerken in
den Config-Registern potentiell fehlerträchtig.
Interrupt Bits würde ich immer erste setzen wenn die restliche Hardware
komplett initialisiert ist.
Sehe grade: Du enablest den Receiver Interrupt vor dem Receiver selbst,
das könnte u.U. dort knallen.
Hallo Jim
Ja...ich hab mich erst in den letzten Wochen wieder mal mit C befasst,
du hast recht, das ist einfacher. Danke.
Ich habe die Interrupt-Aktivierung mal komplett rausgenommen, ich werde
vorerst einmal nur senden.
Meine Funktion comSendByte() scheint zu funktionieren, die
Fallunterscheidung ob TX leer ist oder nicht scheint korrekt zu sein.
Allerdings kann ich auf der anderen Seite nichts empfangen... :(
Ich glaub ich hab das Problem...ich hab die Alternate Function vergessen
zu konfigurieren.
Allerdings haut mir der Compiler ständig meinen Code um die Ohren, er
meckert 'assignment to expression with array type'. Was soll die Meldung
bedeuten? Was für ein Array?
Mit dem Code oben gehts, die USART sendet jetzt fröhlich vor sich hin.
War der montagmorgendlichen Unzeit geschuldet...
Allerdings sendet sie stets 0x00, ich schreib allerdings sowas wie 0x5A
in das DR. Hat jemand eine Idee was da noch nicht stimmt?
Ich habs jetzt...die USART sendet, und das sogar fehlerfrei.
Ich hätte allerdings noch eine Frage zu dem was im Datenblatt steht-es
wäre klasse wenn das jemand wüßte.
Die Baudrate wird ja mit fck/(Oversampling*USART_DIV) berechnet. fck
soll die Taktfrequenz sein, mit der die Peripherie auf APB1 angesteuert
wird. Diese hab ich auf 45MHz eingestellt.
Nun ist es aber so, daß ich die Baudrate durch probieren herausfinden
mußte. Ich hab einen Baudrate-Teiler gefunden (ging erstaunlich
schnell), mit dem ich sehr zuverlässig senden konnte. Ich hab in einer
Endlosschleife ein 'U' (0b01010101) gesendet, damit mehrere MB große
Dateien generiert. Dann diese mit einem Text-Editor geöffnet und alle Us
entfernt-Fehler wären übrig geblieben, aber es gab keine.
Wenn ich nun aber mit dem von mir gefundenen Teiler auf fck
zurückrechne, kommt etwas von knapp 19MHz raus-nix mit 45MHz, wie das
eigentlich gedacht war.
Wenn ich nun aber die Taktkonfiguration sein lasse (alles mit 16MHz),
klappen die Baudrateteiler für 16MHz nicht, die USART sendet doppelt so
schnell wie sie soll.
Ist da noch irgendwo ein Taktteiler den ich übersehen habe? Wenn ja, wo?
Weder im Kapitel zur RCC noch zur USART hab ich da was gefunden...
Wühlhase schrieb:> Ist da noch irgendwo ein Taktteiler den ich übersehen habe? Wenn ja, wo?> Weder im Kapitel zur RCC noch zur USART hab ich da was gefunden...
Servus,
hab jetzt nicht speziell im DB zu Deinem Controller nachgeschaut, von
anderen ST32 kenne ich es aber so, daß die USARTs von verschiedenen
PCLKs versorgt werden. Diese haben nicht notwendigerweise die
CPU-Taktfrequenz, je nach eingestellten Teilern im Clock-Tree. Dort
musst Du mal schauen, an welchem PCLK Dein USART hängt und was da an
Teilerfaktoren im Spiel ist.
Aktuell bin ich gerade an einem Projekt mit STM32F303, da kann man in
einem RCC-Register aber auch noch die Clock-Source für die USARTs
umschalten und so z.B. HSI statt PCLK einstellen.
Mit Oversampling/16 ist's übrigens einfacher, da ist BRR einfach
CLOCK/BAUDRATE, ohne umständliches 'rumgeschiebe...
Wühlhase schrieb:> Mit dem Code oben gehts, die USART sendet jetzt fröhlich vor sich hin.
...
> Allerdings sendet sie stets 0x00, ich schreib allerdings sowas wie 0x5A> in das DR. Hat jemand eine Idee was da noch nicht stimmt?
Bei dir ist der Name Programm, gelle?
Also, mir scheint es bei deinem UART-Wagnis am Konzept zu fehlen. Was
willst du eigentlich draus machen? Normalerweise richtet man sich einen
Ringpuffer ein, den man völlig asynchron zur Schnittstelle befüllen kann
und der zwischenzeitlich per Interrupt geleert wird, bis er dann
irgendwann (wenn vom Programm kein Nachschub kommt) leer ist. Dann
sollte der TX mit Senden aufhören und erst dann wieder beginnen, wenn
irgendwas in den Ringpuffer hineinkommt.
Guck dir mal als Lehrbeispiel die angehängte Datei näher an. Ist zwar
nicht für exaktemang deinen Chip, aber ich habe eben diesen Code nur mit
dezenten Änderungen schon auf NEC 78K3+4, Fujitsu FR, ARM7TDMI, LPC11xx,
LPC13xx, LPC17xx, LPC4088, STM32F1xx..3xx benutzt.
Und damit du mein generelles I/O-Konzept verstehst, hänge ich dir auch
noch gio.zip mit dran, ist ein ganz primitives Interface. Damit kriegt
man aber auf den unterschiedlichsten Plattformen ohne viel Aufwand den
niederen Treiberkram recht wirkungsvoll von den projektabhängigen
höheren Schichten getrennt.
W.S.
Hallo
@Thomas Elger:
Hm...beim F446 weiß ich nur von den zwei verschiedenen
Peripherie-Bussen. Wobei Timer noch über einen Multiplikator versorgt
werden.
USART3 (die ich verwenden will) hängt z.B. am Peripherie-Bus1. Von
mehreren PLLs weiß ich aber nichts, nur von einer (bzw. es gibt noch
eine zweite, die versorgt aber nur einige wenige Peripherie, die bei mir
keine Rolle spielt).
@W.S.:
W.S. schrieb:> Bei dir ist der Name Programm, gelle?
Verstehe ich nicht...
Ich gebe aber freimütig zu, daß ich kein Programmierer bin, obgleich ich
versuche auch da stetig besser zu werden.
Ansonsten hast du aber gut beobachtet-ein Konzept ist daraus definitiv
noch nicht ersichtlich. Es ging erstmal darum, das Ganze überhaupt zum
Laufen zu bringen. Der Controller soll nachher mit einem PC
kommunizieren (da gibt es dann auch ein etwas größeres Protokoll). Über
einen Ringpuffer hab ich mal kurz nachgedacht, aber soweit ist das Ganze
definitiv noch nicht. Danke für den Code, den schaue ich mir doch gleich
mal an.