2

I'm a beginner when it comes to using STM chips, and I have a project where I have to use all three USART terminals in Uvision.

I am using an STM32F103RB chip, and I already got the first two USART_init functions working, but I can't get the third one to work for some reason. I would really appreciate any help Here are my USART_init functions:

/*----------------------------------------------------------------------------
  Initialize UART pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART1_Init (void) {
  int i;

  RCC->APB2ENR |=  (   1UL <<  0);        /* enable clock Alternate Function  */
  AFIO->MAPR   &= ~(   1UL <<  2);        /* clear USART1 remap               */

  RCC->APB2ENR |=  (   1UL <<  2);        /* enable GPIOA clock               */
  GPIOA->CRH   &= ~(0xFFUL <<  4);        /* clear PA9, PA10                  */
  GPIOA->CRH   |=  (0x0BUL <<  4);        /* USART1 Tx (PA9) output push-pull */
  GPIOA->CRH   |=  (0x04UL <<  8);        /* USART1 Rx (PA10) input floating  */

  RCC->APB2ENR |=  (   1UL << 14);        /* enable USART#1 clock             */

  USART1->BRR   = 0x0271;                 /* 115200 baud @ PCLK2 72MHz        */
  USART1->CR1   = ((   1UL <<  2) |       /* enable RX                        */
                   (   1UL <<  3) |       /* enable TX                        */
                   (   0UL << 12) );      /* 1 start bit, 8 data bits         */
  USART1->CR2   = 0x0000;                 /* 1 stop bit                       */
  USART1->CR3   = 0x0000;                 /* no flow control                  */
  for (i = 0; i < 0x1000; i++) __NOP();   /* avoid unwanted output            */

  USART1->CR1  |= ((   1UL << 13) );      /* enable USART                     */
}

/*----------------------------------------------------------------------------
  Initialize UART2 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART2_Init (void) {

  RCC->APB2ENR |= 1;                                    // enable clock for AF
    AFIO->MAPR |= 1<<3;                                 // set USART2 remap
    RCC->APB2ENR |= 1<<5;                           // enable clock for GPIOD
    GPIOD->CRL &= ~(0xFF << 20);                // Clear PD5, PD6
    GPIOD->CRL |= (0x0B << 20);                 // USART2 Tx (PD5) output push-pull
    GPIOD->CRL |= (0x04 << 24);                 // USART2 Rx (PD6) input floating
    RCC->APB1ENR |= 1<<17;                          // enable clock for USART2
    USART2->BRR = 0x138;                                // set baudrate -115.2kB from 36MHz
    USART2->CR1 &= ~(1<<12);                        // force 8 data bits
    USART2->CR2 &= ~(3<<12);                        // force 1 stop bit
    USART2->CR3 &= ~(3<<8);                         // force no flow control
    USART2->CR1 &= ~(3<<9);                         // force no parity
    USART2->CR1 |= 3<<2;                                // RX, TX enable
    USART2->CR1 |= 1<<5;                                // Rx interrupts if required
    NVIC->ISER[1] = (1 << 6);                   // enable interrupts if required
    USART2->CR1 |= 1<<13;                           // USART enable
    
}

/*----------------------------------------------------------------------------
  Initialize UART3 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART3_Init (void) {

  RCC->APB2ENR |= 1;                                    // enable clock for AF
    AFIO->MAPR |= 1<<3;                                // set USART3 remap
    RCC->APB2ENR |= 1<<4;                               // enable clock for GPIOC
    
  GPIOC->CRH   &= ~(0xFFUL <<  4);        /* clear PC10, PC11                  */
    GPIOC->CRH   |=  (0x04UL <<  8);        /* USART3 Rx (PC10) input floating  */
  GPIOC->CRH   |=  (0x01UL <<  8);        /* USART3 Tx (PC11) output push-pull */
    RCC->APB1ENR |=  1<<20;                                 // enable clock for USART3
    
    USART3->BRR = 0x138;                                // set baudrate -115.2kB from 36MHz; USART3    
                                                    //should have the same baudrate as USART2
    USART3->CR1 &= ~(1<<12);                        // force 8 data bits
    USART3->CR2 &= ~(3<<12);                        // force 1 stop bit
    USART3->CR3 &= ~(3<<8);                         // force no flow control
    USART3->CR1 &= ~(3<<9);                         // force no parity
    USART3->CR1 |= 3<<2;                                // RX, TX enable
    USART3->CR1 |= 1<<5;                                // Rx interrupts if required
    NVIC->ISER[1] = (1 << 6);                   // enable interrupts if required
    USART3->CR1 |= 1<<13;                           // USART enable
    
}
glts
  • 21,808
  • 12
  • 73
  • 94
KonopkaD
  • 21
  • 2
  • 4
    You should get rid of all those "magic numbers", see [How to access a hardware register from firmware?](https://electrical.codidact.com/posts/276290) for examples. As it stands, one can't read this code without having the MCU manual open. – Lundin May 31 '21 at 07:27

2 Answers2

5

Your first line for the USART3 initialization is wrong :-)

RCC->APB2ENR |= 1; // enable clock for AF

must be (without a clock the USART doesn't work)

RCC->APB1ENR |= (1<<18); // enable clock for USART

And as an additional hint, do not use all these magic numbers for the bits. This is much more readable (and the needed defines are already done in the CMSIS:

RCC->APB1ENR |= RCC_APB1ENR_USART3EN; // enable clock for USART

theSealion
  • 1,082
  • 7
  • 13
0

After some research, I found there were more problems than just the clock not being enabled. Below is the complete code of the initialization for UART3 using an STM32F103RB chip

/*----------------------------------------------------------------------------
  Initialize UART3 pins, Baudrate
 *----------------------------------------------------------------------------*/
void USART3_Init (void) {

    RCC->APB2ENR |= 1;                                  // enable clock for AF
    AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP;  // set USART3 to partical remap to use PC10 and PC11
    RCC->APB2ENR |= 1<<4;                               // enable clock for GPIOC
    
    // since our pins are above 8, we use H instead of L
    // since we are using 10 & 11 we will be using bits 8-15 in the CRH register
    /* USART3 Tx (PC10) output push-pull */             
    GPIOC->CRH   &= ~(0xFFUL <<  8);        
  GPIOC->CRH   |=  (0x0BUL <<  8);       
    /* USART3 Rx (PC11) input floating  */
    GPIOC->CRH   |=  (0x04UL <<  12);     
    
    RCC->APB1ENR |=  RCC_APB1ENR_USART3EN; /* enable clock for USART3         */
    USART3->BRR = 0x138;                  /* set baudrate -115.2kB from 36MHz */
    
    USART3->CR1   = ((   1UL <<  2) |     /* enable RX                        */
                   (   1UL <<  3) |       /* enable TX                        */
                   (   0UL << 12) );      /* 1 start bit, 8 data bits         */
    
  USART3->CR2   = 0x0000;                 /* 1 stop bit                       */
  USART3->CR3   = 0x0000;                 /* no flow control                  */
    
    USART3->CR1 |= 1<<13;                 /* USART3 enable                    */
    
    //Configure and enable USART3 interrupt
    NVIC->ICPR[USART3_IRQn/32] = 1UL << (USART3_IRQn%32);   // clear any previous pending interrupt flag
    NVIC->IP[USART3_IRQn] = 0x80;                           // set priority to 0x80
    NVIC->ISER[USART3_IRQn/32] = 1UL << (USART3_IRQn%32);   // set interrupt enable bit
    USART3->CR1 |= USART_CR1_RXNEIE;                        // enable USART3 receiver not empty interrupt
}

and the interrupt I used to prove this works looks like this

// UART3 Interupt Handler
void USART3_IRQHandler (void) {

    uint8_t inKey3 = (int8_t) (USART3->DR & 0x1FF);
    SendCharTo3(inKey3);
    if(inKey3 == 0x0D) {
        SendCharTo3('\n');
    }
}

/*----------------------------------------------------------------------------
  SendChar
  Write character to Serial Port. for UART 3
 *----------------------------------------------------------------------------*/
int SendCharTo3 (uint8_t ch)  {

  while (!(USART3->SR & USART_SR_TXE));
  USART3->DR = ((uint16_t)ch & 0x1FF);

  return (ch);
}
KonopkaD
  • 21
  • 2