cancel
Showing results for 
Search instead for 
Did you mean: 

USART bare metal programming fail to send data - STM32L4R5ZI

KHuyn
Associate II

I am new to embedded programming and trying to learn ARM with my STM32L4 board. I stick to the datasheet and stay away from HAL library to learn how the MCU and its peripherals work. Here I am trying to initiate USART3 and send a line using "printf" but fail to receive anydata from my FTDI chip. Did I miss something here?

#include <stdio.h>
#include <stdint.h>
#include "kfunction.h"
#include "kstm32l4r5xx.h"
/*--Define--------------------------------------------------------------------------------*/
/*--Global-Variable---------------------------------------------------------------------- */
/*--Function Prototypes-------------------------------------------------------------------*/
void initUSART3(void);
void initRCC(void);
void blinkBLUE(void);
void initPORT(void);
int putchar(int);
/*--Main----------------------------------------------------------------------------------*/
int main()
{
  initRCC(); 
  initPORT();
  initUSART3();
  while(1)
  {
    blinkBLUE();
    printf("this is USART3");
    putchar(12);
  }
} // EO Main
 
/*--Function------------------------------------------------------------------------------*/
/************************************************/
/*             Name: initUSART3                 */
/*-Initiating USART3 for STM32L4R5xx            */
/*-Oversampling 8 (OVER8=default/0)             */
/*-Baudrate: 9600-USARTDIV=4Mhz/9600=0x1A0(416) */
/*                                              */
/************************************************/
void initUSART3(void)
{
  USART3_BRR |= 0x1A0U;  //select baudrate for USART3=9600    <---edit baudrate first
  USART3_CR1 |= 0x9U;  // enable USART3 - Transmit Enable        <---enable USART after that
}
/************************************************/
/*             Name: initRCC                    */
/*-Initiating RCC for STM32L4R5xx               */
/*-MCU run on MSI clock 4Mhz(reset value)       */
/*-Open Clock Gate for USART3                   */
/*-Open AHB2 clockgate                          */
/*                                              */
/************************************************/
void initRCC(void)
{
  RCC_APB1ENR1 |= 1U<<18; //USART3 clockgate enable 
  RCC_AHB2ENR |= (1<<1); 	// Enable PB
  RCC_AHB2ENR |= (1<<3); //Enable PD
}
/************************************************/
/*             Name: Blink LED                  */
/*-Blink LED on port B 7 with delay()           */
/*                                              */
/************************************************/
void blinkBLUE(void)
{
 delay();
 GIPOB_ODR ^= (1<<7); // PB7 output = 1
 delay();
 GIPOB_ODR |= (1<<7); // PB7 output = 1
}
/************************************************/
/*             Name: initPORTB                  */
/*-initial PORTB                                */
/*                                              */
/************************************************/
void initPORT(void)
{
  GPIOB_MODER ^= (1U<<15); // Config PB7 general output
  GIPOB_ODR |= (1U<<7); 	// PB7 output = 1
  GPIOD_MODER ^= (1U<<17); // Config PD8 general output-USART3 TX
  GPIOD_MODER |= (1U<<16); // Config PD8 general output-USART3 TX      <---Set PORTD_8/USART3_TX as general output
}
/************************************************/
/*             Name: putchar                    */
/*-printf() from stdlib use putchar() for output*/
/* putchar() is device specific, so we need to  */
/* supply it                                    */
/*                                              */
/************************************************/
int putchar(int c)
{
  while(!USART3_TXE);           //<--define in header file
  USART3_TDR = c;
  return(c);
}

11 REPLIES 11

I documented all the thing I went through and the final code, for people, who happen to have a similar problem, may find it useful for them somehow someday. I known it's silly, because I am a rookie

My name is not strange.

Piranha
Chief II

Agreed that _VAL2FLD() and _FLD2VAL() macros defined in CMSIS headers can be useful. Additionally I'll share my two even more useful macros:

#define REG_MOD_FIELD(rReg, xFld, xVal)    ( (rReg) = ((uint32_t)(rReg) & ~xFld##_Msk) | (((uint32_t)(xVal) << xFld##_Pos) & xFld##_Msk) )
#define REG_MOD_BITS(rReg, fClr, fSet, iPos)    ( (rReg) = ((uint32_t)(rReg) & ~((uint32_t)(fClr) << (iPos))) | ((uint32_t)(fSet) << (iPos)) )

Basically these add a clearing of the previous values.