cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 UART Rx not working

RS.2
Associate

I was trying to configure USART on an STM32L476 Discovery board. I know that register level coding is not great but it really works well for what I need to use the board for. I was able to send messages out using the transmit but I'm not able to get the receiver to work. When I investigated with a scope I could see that the characters I was sending were appearing at the Rx pin of the MCU but the RXNE pin doesn't seem to be setting. Any help would be greatly appreciated. Here is my main.cpp:

#include "mbed.h"
#include "stm32l476xx.h"
#include <string.h>
 
#define GPIO_MODER_AF 0x2UL //select alternate function for GPIO
#define GPIO_OSPEEDR_VHS 0x3UL //High speed GPIO
#define GPIO_AFR_AF7 0x7UL //alternate function 7
 
void setMSI(double frequency); //function to set MSI frequency
void setLatency(); //function to set flash read latency
 
void init_GPIOA();//initialise GPIOA
 
void printserial(char[]); //print serial message on USART Tx
 
double F_CPU = 80; //frequency of CPU in MHZ
 
// main() runs in its own thread in the OS
int main()
{
    init_GPIOA();
    setMSI(4);
 
    //USART GPIO init
    //PA2 and PA3 as alternate functions
    GPIOA->MODER = (GPIOA->MODER & (~GPIO_MODER_MODE2_Msk) & (~GPIO_MODER_MODE3_Msk)) | (GPIO_MODER_AF << GPIO_MODER_MODE2_Pos) | (GPIO_MODER_AF << GPIO_MODER_MODE3_Pos); 
    //very high speed output
    GPIOA->OSPEEDR |= (GPIO_OSPEEDR_VHS << GPIO_OSPEEDR_OSPEED2_Pos) | (GPIO_OSPEEDR_VHS << GPIO_OSPEEDR_OSPEED3_Pos); 
    //configure as pull up
    GPIOA->PUPDR = (GPIOA->PUPDR & (~GPIO_PUPDR_PUPD2_Msk) & (~GPIO_PUPDR_PUPD3_Msk)) | GPIO_PUPDR_PUPD2_0 | GPIO_PUPDR_PUPD3_0; 
    //Alternate function 7 for both pins
    GPIOA->AFR[0] = (GPIOA->AFR[0] & (~GPIO_AFRL_AFSEL2_Msk) & (~GPIO_AFRL_AFSEL3_Msk)) | (GPIO_AFR_AF7 << GPIO_AFRL_AFSEL2_Pos) | (GPIO_AFR_AF7 << GPIO_AFRL_AFSEL3_Pos);
 
    //calculate div register value based on baud
    unsigned long baud = 9600;
    uint32_t usart_div = uint32_t(long(F_CPU * 1000000)/baud);
    USART2->BRR = usart_div; //programmme baud rate
    RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN; //enble USART2 clock
    RCC->CCIPR |= (RCC->CCIPR & ~RCC_CCIPR_USART2SEL_Msk) | RCC_CCIPR_USART2SEL_0; //select system clock as USART clock
    USART2->CR1 |= USART_CR1_UE; //enable USART
    USART2->CR1 |= USART_CR1_TE; //enable transmitter
    USART2->CR1 |= USART_CR1_RE; //enable reciever
 
    char worked[] = "It Worked \n\r"; //message to send out
    char didntwork[] = "It Didnt Work \n\r"; //message to send out
 
    while (true) {
        //if character recieved in RDR, print 'It worked'
        if ((USART2->ISR & USART_ISR_RXNE) == USART_ISR_RXNE){
            printserial(worked);
            USART2->RQR |= USART_RQR_RXFRQ; // clear RXNE bit
        }
    }
}
 
//print message on USART Tx
void printserial(char send[]){
    int length = strlen(send);  
    for (int i=0; i<=length; i++){
        USART2->TDR = send[i];
        while ((USART2->ISR & USART_ISR_TXE) != USART_ISR_TXE){int p = 0;} 
    }
}
 
//initialise GPIOA
void init_GPIOA(){
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; //enable AHB clock for GPIO A
}
 
//set MSI as system clock with chosen frequency
void setMSI(double frequency){
    if (frequency > F_CPU){
        // function to increase frequency
        setLatency();
    }
 
    //find required frequency range
    unsigned long range = RCC_CR_MSIRANGE_6;
    if (frequency == 0.1){range = RCC_CR_MSIRANGE_0;}
    else if (frequency == 0.2){range = RCC_CR_MSIRANGE_1;}
    else if (frequency == 0.4){range = RCC_CR_MSIRANGE_2;}
    else if (frequency == 0.8){range = RCC_CR_MSIRANGE_3;}
    else if (frequency == 1){range = RCC_CR_MSIRANGE_4;}
    else if (frequency == 2){range = RCC_CR_MSIRANGE_5;}
    else if (frequency == 4){range = RCC_CR_MSIRANGE_6;}
    else if (frequency == 8){range = RCC_CR_MSIRANGE_7;}
    else if (frequency == 16){range = RCC_CR_MSIRANGE_8;}
    else if (frequency == 24){range = RCC_CR_MSIRANGE_9;}
    else if (frequency == 32){range = RCC_CR_MSIRANGE_10;}
    else if (frequency == 48){range = RCC_CR_MSIRANGE_11;}  
    RCC->CR |= RCC_CR_MSIRGSEL; //select MSI range from RCC_CR register
    RCC->CR = (RCC->CR & ~RCC_CR_MSIRANGE_Msk) | range; //set MSI range
    RCC->CR |= RCC_CR_MSION; //enable MSI
    while ((RCC->CR & RCC_CR_MSION_Msk) != RCC_CR_MSION_Msk){int i = 0;} //wait for stability
    RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_SW_Msk)) | RCC_CFGR_SW_MSI; //set MSI as system clock source
    while((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_MSI){int i = 0;} //check MSI is system clock
 
    if (frequency < F_CPU){
        // function to decrease frequency
        setLatency();
    }
    F_CPU = frequency;
}
 
//set latency for reading flash memory
void setLatency(){
    //choose number of wait states based on frequency
    unsigned long wait_states = 0;
    if (F_CPU <= 16){wait_states = FLASH_ACR_LATENCY_0WS;}
    else if (F_CPU <= 32){wait_states = FLASH_ACR_LATENCY_1WS;}
    else if (F_CPU <= 48){wait_states = FLASH_ACR_LATENCY_2WS;}
    else if (F_CPU <= 64){wait_states = FLASH_ACR_LATENCY_3WS;}
    else if (F_CPU <= 80){wait_states = FLASH_ACR_LATENCY_4WS;}
    FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | wait_states; //set wait states
    while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != wait_states){int i = 0;} //wait till wait states are programmed
}

1 REPLY 1

You have to enable the clocks before writing the registers, enable the USART2 before writing BRR

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..