Guten Morgen,
auf einem STM32F439 möchte ich gerne den USART1 verwenden.
Mein bisheriger Code funktioniert auch und tut das, was er soll aber
leider nur im Debugger bzw. wenn ich einen Breakpoint ab einer
bestimmten Stelle ich Code habe. Ohne Debugger bzw. Breakpoint habe ich
ein für mich unerklärliches Verhalten.
1 | RCC->APB2ENR |= ((uint32_t)1) << 4;
|
2 |
|
3 | // Port PA9 -> Transmitter Out
|
4 | GPIOA->MODER |= ((uint32_t)1) << 19; // Alternate Function UART-TX
|
5 | GPIOA->OSPEEDR |= ((uint32_t)1) << 18; // Output Speed -> Medium
|
6 | GPIOA->PUPDR |= ((uint32_t)1) << 18; // Pull-Up Enable
|
7 | GPIOA->AFR[1] |= ((uint32_t)7) << 4; // Alternate Funktion 8 UART-TX
|
8 |
|
9 | // Port PA10 -> Receiver In
|
10 | GPIOA->MODER |= ((uint32_t)1) << 21; // Alternate Function UART-RX
|
11 | GPIOA->PUPDR |= ((uint32_t)1) << 20; // Pull-Up Enable
|
12 | GPIOA->AFR[1] |= ((uint32_t)7) << 8; // Alternate Funktion 8 UART-RX
|
13 |
|
14 | // Port PC9 -> RS485 Treiber Enable
|
15 | GPIOC->MODER |= ((uint32_t)1) << 18; // Output
|
16 | GPIOC->OSPEEDR |= ((uint32_t)1) << 18; // Output Speed -> Medium
|
17 | GPIOC->PUPDR |= ((uint32_t)1) << 18; // Pull-Up Enable
|
18 |
|
19 | // Allgemeine USART-1-Tx-Rx Einstellungen
|
20 | USART1->CR1 = 0x3800; // 9 Datenbits, UART Peripherie enable
|
21 | // aber Transmitter und Receiver disable, keine
|
22 | // Parity Control. Oversampling by 16.
|
23 | USART1->CR2 = 0x00; // 1 Stop Bit
|
24 | USART1->CR3 = 0x808; // CTS/RTS abgestellt, Half-Duplex Mode
|
25 |
|
26 | // Baudrate einstellen
|
27 | USART1->BRR = 0x0000222E; // 9600 Baud. Bei einem 84 MHz USART1
|
28 |
|
29 | // Außgänge richtig setzen.
|
30 | GPIOA->ODR |= ((uint32_t)1)<<9; // Transmitter und Receiver abgeschaltet.
|
31 | // Tx bin wird auf High gestellt.
|
32 |
|
33 | GPIOC->ODR &= ~(((uint32_t)1)<<9); // RS485 Treiber Disable
|
Das war die Initialisierung vom USART 1.
Im zweiten Teil mache ich ein paar Einstellungen, damit der USART so
funktioniert, wie ich es gerne hätte.
1 | //UART ist eine von mir angelegte Struktur
|
2 | // Alle USART1 Interupts werden zur Sicherheit abgeschaltet
|
3 | USART1->CR1 &= ~(0x000001F0);
|
4 | UART.TxData = stdata;
|
5 | UART.TxLength = -1; // wegen den Dummy Daten
|
6 | // Tx PortPin auf GPIO setzen, damit die Dummydaten nicht
|
7 | // an den Treiber übertragen werden.
|
8 | // Port PA9 -> Transmitter Out
|
9 | GPIOA->MODER &= ~(((uint32_t)1) << 19); // Alternate Function ausgestellt
|
10 | GPIOA->MODER |= ((uint32_t)1) << 18; // GPIO Mode für UART-TX PinA9
|
11 |
|
12 |
|
13 | GPIOC->ODR |= ((uint32_t)1)<<9; // RS485 Treiber Enable
|
14 | USART1->DR = 0x111; // Nur ein Dummybyte
|
15 | USART1->CR1 |= 0x00000088; // TXE und TXE Interupt enable
|
Setze ich an einer beliebigen Stelle ! nach ! der Befehlszeile
RCC->APB2ENR |= ((uint32_t)1) << 4;
einen Breakpoint, dann funktioniert mein Code wie gewünscht. Habe ich am
Oszi nachgemessen. Fehlt dieser Breakpoint kommt es zu einem
Vehlverhalten.
Folgende IF-Bedinung wird in der USART1 Interuptroutine nur erfüllt,
wenn irgendwo zuvor kurz an einem Breakpoint angehalten wurde.
1 | volatile uint32_t ulInterrupt = USART1->SR;
|
2 | if((ulInterrupt & UART_TXE_FLAG) && !(ulInterrupt & UART_TC_FLAG))
|
Im Errata Sheet habe ich folgendes gelesen:
A delay between an RCC peripheral clock enabling and the effective
peripheral enabling should be taken into account in order to manage the
peripheral read/write to registers.
Setze ich ein __asm("DSB"); oder zwei __NOP(); hinter RCC->APB2ENR |=
((uint32_t)1) << 4; bringt das auch nicht das gewünschte Ergebniss.
Könnt ihr mir vielleicht weiterhelfen ?