Skip to main content
Visitor II
March 4, 2025
Question

Single byte transmission is not working in USART on nucleo-f411re

  • March 4, 2025
  • 4 replies
  • 620 views

Hi Team,

Currently I am doing bare-metal programming in STM32F411 using Nucleo-F411RE board; pins PC6/PC7.

For USART6, I am trying to transmit string and bytes, in this string is working fine, but for single byte transmission it is not working?

 

 

void rcc_config(void)
{
 RCC->CR |= 1 << 0; // HSI on
 while(!(RCC->CR & (1 << 1))); // wait until HSI on

 RCC->AHB1ENR |= (1 << 2) | (1 << 0); // Enable GPIO A & CFGR
 RCC->APB1ENR |= (1 << 28); // Power Interface clock enable
 RCC->APB2ENR |= (1 << 5) | (1 << 8); // Enable ADC and USART6
}

void uart_init(void)
{
 USART6->CR1 &= ~(1 << 12); // 1:8N1
 USART6->CR1 |= 1 << 9; // Parity Selection
 USART6->CR1 |= 1 << 7; // TXE interrupt enable 
 USART6->CR1 |= 1 << 6; // TCIE enable 
 USART6->CR1 |= 1 << 5; // RXNE interrupt enable 
 USART6->CR1 |= 1 << 3; // TE enable 
 USART6->CR1 |= 1 << 2; // RE enable
 USART6->CR2 |= 0x00 << 12; // 1 Stop bit
 USART6->CR2 &= ~(1 << 11); // CLK disabled
 USART6->CR3 &= ~(1 << 3); // FD is selected
 USART6->CR3 &= ~(1 << 9); // CTS disable
 USART6->CR3 &= ~(1 << 8); // RTS disable
 USART6->CR3 |= (1 << 11); // One bit sample
 USART6->BRR |= 0x08B; // 115200
 USART6->CR1 |= 1 << 13; // Enable USART6 UE
}

void gpio_init(void)
{
 RCC->AHB1ENR |= (1 << 2); // PC6/7 - Tx/Rx
 GPIOC->MODER |= (2 << 12) | (2 << 14); // AF mode for PC6/7 
 GPIOC->OTYPER &= ~(1 << 6);
 GPIOC->OTYPER &= ~(1 << 7);
 GPIOA->MODER |= ((0x3 << (AN0 * 2)) | (0x3 << (AN1 * 2))); // set 0b11 for AN0 & AN1
 GPIOC->OSPEEDR |= (1 << 12) | (1 << 14); // Medium speed
 GPIOC->AFR[0] |= (8 << 24) | (8 << 28); // USART6 on AF8
}


void Uart_tx(int data)
{
 while(!(USART6->SR & (1 << 7)))
 {
 }
 USART6->DR = data & 0x1FF; 
 while(!(USART6->SR & USART_SR_TC));
}

void Uart_transmit_str(char *data)
{
 uint8_t size = strlen(data);

 while(size--)
 {
 Uart_tx(*data++);
 }

 while(!(USART6->SR & (1 << 6)));
}

int main(void)
{
 rcc_config();
 uart_init();
 gpio_init();
 Uart_transmit_str("ADC turned ON!!!\n\r");

 while(1)
 {
 Uart_tx('B');
 }
}

 

 

Let me the any correction needed in the code?

Edited to apply proper code formatting - please see How to insert source code for future reference.
    This topic has been closed for replies.

    4 replies

    Graduate
    March 4, 2025

    1. Use bit names from MCU header file instead of magic numbers to avoid simple mistakes.

    2. Set BRR before enabling UART in CR1. (ok, this one is actually correct, but it is enough to write the whole CR1 after BRR). Just assigne BRR, don't do |= on it.

    3. Use single assignments instead of sequences of boolean operations on CR2 and CR1. For basic UART operation, you only need to write to BRR and then to CR1, no need to touch CR2, CR3.

    4. Don't transmit a character without any pause in the main loop.

    5. Don't enable interrupts if you don't plan to service them.

    Super User
    March 4, 2025

    While all items by @gbm  above are valid, I've just tried and it does transmit 'B' continuously.

    However, whatever receiver you are using, it may be confused by a continuous stream with no gaps.

    JW

    Visitor II
    March 5, 2025

    Thanks the feedback.. But still i face issue with USART, i cant print properly

    #include "stm32f411xe.h"
    #include <stdio.h>
    #include <string.h>

    #define AN0         0
    #define AN1         1
    #define MAX         21

    void rcc_config(void);
    void uart_init(void);
    void gpio_init(void);
    void adc_init(void);
    void adc_read(void);

    void Uart_tx(char data);
    void Uart_transmit_str(char *data);

    volatile uint16_t an0_data = 0;
    volatile uint16_t an1_data = 0;
    char arr[MAX];

    int main(void)
    {
        char *buf;
        int len = MAX;
        rcc_config();
        uart_init();
        gpio_init();
        adc_init();
       
        Uart_transmit_str("ADC Testing!!!\n\r");
        while(1)
        {
            adc_read();
            Uart_transmit_str("ADC Values\n\r");
            snprintf(arr, MAX, "A0: %u\nA1: %u\n",an0_data, an1_data);
           
            buf = &arr;
            while(len--)
            {
                Uart_tx(*buf++);
            }
            // Simple delay
            for (volatile int i = 0; i < 1000000; i++);      
            Uart_transmit_str("End\n\r");
        }
    }
     
    void rcc_config(void)
    {
        RCC->CR     |= 1 << 0;                  // HSI on
        while(!(RCC->CR & (1 << 1)));           // wait until HSI on
        RCC->AHB1ENR    |= (1 << 2) | (1 << 0); // Enable GPIO A & CFGR
        RCC->APB1ENR    |= (1 << 28);           // Power Interface clock enable
        RCC->APB2ENR    |= (1 << 5) | (1 << 8); // Enable ADC and USART6
    }

    void uart_init(void)
    {
        USART6->BRR     |= 0x08B;               // 115200
        //   0010 0000 1110 1100 -> 0x20EC
        USART6->CR1 |= 0x200C;
    }

    void gpio_init(void)
    {
        RCC->AHB1ENR    |= (1 << 2);                // PC6/7 - Tx/Rx
        GPIOC->MODER    |= (2 << 12) | (2 << 14);   // AF mode for PC6/7
        GPIOC->OTYPER   &= ~(1 << 6);
        GPIOC->OTYPER   &= ~(1 << 7);
        GPIOA->MODER    |= ((0x3 << (AN0 * 2)) | (0x3 << (AN1 * 2)));      // set 0b11 for AN0 & AN1
        GPIOC->OSPEEDR  |= (1 << 12) | (1 << 14);   // Medium speed
        GPIOC->AFR[0]   |= (8 << 24) | (8 << 28);   // USART6 on AF8
    }

    void adc_init(void)
    {
        // Enable Scan, Interrupt disable @ EOC
        ADC1->CR1 |= 0x0100 ;  // 0b 0000 0001 0000 0000

        // EOC enable, CONT disable, ADC ON
        ADC1->CR2 |= 0x0401;   // 0b 0000 0100 0000 0001

        // Sample time - 56 cycles
        ADC1->SMPR2 |= 0x3 << 3 | 0x3 << 0;  // 0b 011 011

        // Regular sequence
        ADC1->SQR1 |= 1<<20;   // 2 Conversion
        ADC1->SQR3 |= 0<<0 | 1<<5;
    }

    void adc_read(void)
    {
        // Start ADC Conversion
        ADC1->CR2 |= ADC_CR2_SWSTART;

        // Wait for conversion to finish (by checking EOC (End of Conversion) flag)
        while (!(ADC1->SR & ADC_SR_EOC));

        an0_data = (uint16_t)ADC1->DR;         // Read the data  - AN0
        an1_data = (uint16_t)ADC1->DR;         // Read the data  - AN1
    }

    void Uart_tx(char data)
    {
       //int i = 50;
        while(!(USART6->SR & USART_SR_TXE))
        {
        }
        USART6->DR = data & 0x1FF;
        //while(!(USART6->SR & USART_SR_TC));       // with & without this its working

       // while(i){ i--;}
    }

    void Uart_transmit_str(char *data)
    {
        uint8_t size = strlen(data);

        while(size--)
        {
            Uart_tx(*data++);
        }
        while(!(USART6->SR & (1 << 6)));
    }
     
    /// ADC values are not printing 
    Prasannaraj_0-1741187915876.png

     



    Let me what is the problem in this..


    Super User
    March 7, 2025

    Please use the '</>' icon at the top of editor, when posting code.

    At the first glance, I don't see anything very wrong with your code, but that was the case with the first piece of code, too. Did you get it working as expected?

    JW