Forum: Mikrocontroller und Digitale Elektronik UART konfiguration STM32F030XC


von flo (Gast)


Lesenswert?

Hallo zusammen,
ich versuche gerade die UART3 des STM32F32030XC ans laufen zu kriegen 
aber es tut sich gar nichts.
Meine Vermutung ist, dass ich irgendwo in dem Code unten was vergessen 
habe und hoffe dass einer von euch mir einen Hinweis geben kann.

Vielen Dank dafür.
1
void UART3_Config(void)
2
{
3
4
    RCC->AHBENR |= RCC_AHBENR_GPIOCEN;    // Enable GPIO clock Port C
5
6
    /* Configure UART */
7
     GPIOC->MODER |= (GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_1);  // Switch to alternate function mode
8
     GPIOC->AFR[1] |= (GPIO_AFRH_AFSEL10 | GPIO_AFRH_AFSEL11);    // Select UART3 RX and TX
9
10
     RCC->APB1ENR |= RCC_APB1ENR_USART3EN;    // Enable clock UART3
11
12
     /* Clear UART Configuration */
13
     USART3->CR1 = 0x00000000;
14
     USART3->CR2 = 0x00000000;
15
     USART3->CR3 = 0x00000000;
16
17
     USART3->BRR = 2500;  // Set Baudrate to 19200
18
19
     USART3->CR1 |= (USART_CR1_TE | USART_CR1_RE);  // Enable TX and RX
20
     USART3->CR1 |= (USART_CR1_RXNEIE);    // Enable RX interrupt
21
22
     USART3->CR1 |= USART_CR1_UE;    // Enable UART
23
24
     NVIC_SetPriority(USART3_6_IRQn, 1);
25
     // Enable USART3 interrupts
26
     NVIC_EnableIRQ(USART3_6_IRQn);
27
}

von Pieter (Gast)


Lesenswert?

UART3_Config..und wo ist der Rest?

von flo (Gast)


Lesenswert?

Hier nochmal der IRQ Handler, main und die Clock config.
1
void USART3_6_IRQHandler(void)
2
{
3
  unsigned int test;
4
  // Test for RXNE pending interrupt
5
  if ((USART3->ISR & USART_ISR_RXNE) == USART_ISR_RXNE)
6
    {
7
      test = USART3->RDR;
8
      // RXNE flags automatically clears when reading RDR.
9
    }
10
}
11
12
13
void SystemClock_Config(void)
14
{
15
  RCC->CR |= RCC_CR_HSION;
16
17
  RCC->CFGR &= ~(RCC_CFGR_SW);
18
19
  while(!(RCC->CR & RCC_CR_HSIRDY));
20
21
  RCC->CR &= ~(RCC_CR_PLLON);
22
23
  FLASH->ACR |= FLASH_ACR_LATENCY;
24
25
  RCC->CFGR |= RCC_CFGR_PLLSRC_HSI_PREDIV;
26
27
  RCC->CFGR = (RCC_CFGR_PLLMUL12 | RCC_CFGR_PPRE_DIV1);
28
29
  RCC->CR |= RCC_CR_PLLON;
30
31
  while(!(RCC->CR & RCC_CR_PLLRDY));
32
33
  RCC->CFGR &= ~(RCC_CFGR_SW);
34
  RCC->CFGR |= RCC_CFGR_SW_PLL;
35
}
36
37
38
int main(void)
39
{
40
  SystemClock_Config();
41
  UART3_Config();
42
  Timer6_Config();
43
44
  while(1)
45
  {
46
      Delay_ms(1000);
47
      USART3->TDR = '#';
48
  }
49
}

von A. B. (Gast)


Lesenswert?

flo schrieb:
>      GPIOC->MODER |= (GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_1);  //
>      GPIOC->AFR[1] |= (GPIO_AFRH_AFSEL10 | GPIO_AFRH_AFSEL11);    //

Was sollen diese beiden Zeilen bewirken? Die machen nun nicht gerade 
das, was
in den Kommentaren steht. Ich würde mal gründlich lesen, was im RM zu 
den GPIO-Registern und im Datenblatt zu den AF steht. Und es schader 
auch nicht, in den
CMSIS Headern nachzusehen, was diese Makros eigentlich bedeuten.

UART3 liegt bei Port C auf AF01.

Das '|=' macht hier wenig Sinn, da damit ja höchstens Bits gesetzt 
werden können.
Zwar werden nach einem Reset die meisten (aber nicht alle!) Bits auf 0 
gesetzt,
aber spätestens, wenn man Pins *um*konfiguriert, fällt einem das auf die 
Füße.
Besser wäre es, mit GPIO_AFRH_AFSEL10_Msk erst alle Bits auszumaskieren 
(daher der Name _Msk) und dann die benötigten zu setzen.

Außerdem wäre es sinnvoll, erst AFR zu setzen, und erst danach den Port 
auf AF umzuschalten (sonst ist der --- wenn auch nur kurz --- eventuell 
auf eine andere AF eingestellt).

von Sergey (Gast)


Lesenswert?

Isn't it easier to use STM32CubeMX?

von Ben S. (bensch123)


Lesenswert?

Sergey schrieb:
> Isn't it easier to use STM32CubeMX?

Einfacher, aber das ist eher was für die Klicki-Bunti Fraktion.

von flo (Gast)


Lesenswert?

Danke für die Antworten, ich lese mich gerade ein und schaue was die 
Makros so bedeuten.

>Isn't it easier to use STM32CubeMX?
Es ist zwar einfacher aber die Hintergründe hat man dann noch nicht 
verstanden.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Zum Pinstatus setzen empfehle ich eine Funktion zu bauen um das nicht 
immer neu zu machen.
Das ist fehlerträchtig und nervt irgendwann ;)
Die Funktion bekommt:
- Port -> GPIOA/B/C usw, also direkt dieses Makro welches vom Typ 
"GPIO_TypeDef*" ist.
- Pinnummer
- modus (output, input, pulldown/up, alternate, etc)
- geschwindigkeit (davon gibts 4)
- alternate function als nummer (bei manchen L0 kommt ein UARt auch mal 
als verschiednene AF numemrnr aus, wodurch ein enum leider nicht geht)
Kann man auch in ein struct packen wen man will ud dann kan man den pin 
"uart3_rx" durch die Gegend schubsen im Programm.

Anstatt ein UART3_config zu schreiben wäre doch eine allgemeinere 
Funktion besser.
UART_config und es wird übergeben welcher uart da konfiguiert werden 
soll.
Beispiel:
1
void uart_init(USART_TypeDef* uart) {
2
  
3
  uart->CR1  = USART_CR1_FIFOEN | USART_CR1_TE | USART_CR1_RE;
4
  uart->CR1 |= USART_CR1_UE;
5
}

von Stefan F. (Gast)


Lesenswert?

Die CMSIS, auf welcher auch die HAL aufbaut, enthält hilfreiche Makros 
zum Ändern einzelner Bits. Beispiel für USART1 auf dem STM32L073:
1
#include <stdio.h>
2
#include "stm32l0xx.h"
3
4
uint32_t SystemCoreClock=2097000;
5
6
// delay loop for the default 2.1 MHz CPU clock with optimizer enabled
7
void delay(uint32_t msec)
8
{
9
    for (uint32_t j=0; j < 419UL * msec; j++)
10
    {
11
        __NOP();
12
    }
13
}
14
15
// Redirect standard output to the serial port
16
int _write(int file, char *ptr, int len)
17
{
18
    for (int i=0; i<len; i++)
19
    {
20
        while(!(USART1->ISR & USART_ISR_TXE));
21
        USART1->TDR = *ptr++;
22
    }
23
    return len;
24
}
25
26
// Called after each received character
27
void USART1_IRQHandler(void)
28
{
29
    // read the received character
30
    char received=USART1->RDR;
31
32
    // send echo back
33
    while(!(USART1->ISR & USART_ISR_TXE));
34
    USART1->TDR = received;
35
}
36
37
int main(void)
38
{
39
    // Enable clock for Port A
40
    SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);
41
42
    // PA5 = Output for the LED
43
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE5, GPIO_MODER_MODE5_0);
44
45
    // Use system clock for USART1
46
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);
47
    MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART1SEL, RCC_CCIPR_USART1SEL_0);
48
49
    // PA9 (TxD) shall use the alternate function 4 (see data sheet)
50
    MODIFY_REG(GPIOA->AFR[1], GPIO_AFRH_AFSEL9, 4UL<<GPIO_AFRH_AFSEL9_Pos);
51
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE9, GPIO_MODER_MODE9_1);
52
53
    // PA10 (RxD) shall use the alternate function 4 (see data sheet)
54
    MODIFY_REG(GPIOA->AFR[1], GPIO_AFRH_AFSEL10, 4UL<<GPIO_AFRH_AFSEL10_Pos);
55
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE10, GPIO_MODER_MODE10_1);
56
57
    // Set baudrate
58
    USART1->BRR = (SystemCoreClock / 2400);
59
60
    // Enable transmitter, receiver and receive-interrupt of USART1
61
    USART1->CR1 = USART_CR1_UE + USART_CR1_TE + USART_CR1_RE + USART_CR1_RXNEIE;
62
63
    // Enable interrupt in NVIC
64
    NVIC_EnableIRQ(USART1_IRQn);
65
66
    while (1)
67
    {
68
        // LED on
69
        WRITE_REG(GPIOA->BSRR, GPIO_BSRR_BS_5);
70
        delay(500);
71
72
        puts("Hello");
73
74
        // LED off
75
        WRITE_REG(GPIOA->BSRR, GPIO_BSRR_BR_5);
76
        delay(500);
77
    }
78
}

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.