cancel
Showing results for 
Search instead for 
Did you mean: 

How to use LPUART1 on the STM32WB55 Nucelo Board without using STMCubeMX and HAL

BGibs
Associate II

I am having trouble getting the LPUART1 on the STM32WB55 Nucelo Board to transmit. I would like to transmit a character at 9600 bps using LPUART1 on the STM32WB55 Nucelo Board. I read the reference manual on how to calculate the baud rate divisor for LPUART but, I am confused on how to set the baud rate to 9600. I sure it is somethign wrong in my c program. Can someone help me configure LPUART1 at 9600bps. Please see me code below for details:

/* Includes */

#include <stddef.h>

#include <stdint.h>

#include <string.h>

#include <stddef.h>

#include "stm32wbxx.h"

#include "stm32wbxx_gpio_driver.h"

#define PCLK  32000000U                  // Peripheral Clock

#define BAUD  9600U                      // Baud rate

/* Private macro */

/* Private variables */

/* Private function prototypes */

void Delay(uint32_t d);

void Toggle_GREEN_LED();

void Toggle_BLUE_LED();

void Toggle_RED_LED();

void Configure_LPUART1();

void LPUART1_putChar(char ch);

void DelayMS(int delay);

void printString(char * string);

void SendMsg(const char msg[]);

void LPUART1_Init(void);

void LPUART1_Init(void)

{

 // Enable Peripheral Clock bit for PC1

 RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;

 // Enable Peripheral Clock bit for LPUART_1

 RCC->APB1ENR2 |= RCC_APB1ENR2_LPUART1EN;

 // PC1 to alternate function 0b10

 GPIOC->MODER &= ~(GPIO_MODER_MODE1_0);     // Clear first bit

 GPIOC->MODER |= GPIO_MODER_MODE1_1;      // Set second bit

 // Set PC1 GPIO to low speed mode 0b11

 GPIOC->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED1_0;   // GPIO MODER Register 0 bit 1

 GPIOC->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED1_1;   // GPIO MODER Register 1 bit 1

 // Set PC1 as Push Pull

 GPIOC->OTYPER &= ~GPIO_OTYPER_OT1;

 // Set PC1 as no pull up, no pull down

 GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPD1_1 | GPIO_PUPDR_PUPD1_0);

 // Enable AF8 for PC1 0b1000

 GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL8;

 GPIOC->AFR[1] |= GPIO_AFRH_AFSEL8_3;

 GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL8_0;

 GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL8_1;

 GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL8_2;

 // Set Prescaler

 //LPUART1->PRESC &= ~USART_PRESC_PRESCALER;

 // Set baud rate to 9600

   //LPUART1->BRR = 0x06D3;

  LPUART1->BRR = (PCLK/BAUD/16);

 //LPUART1->BRR = 0x5555;

 // Set Word Length to 8-bits

 LPUART1->CR1 &= ~USART_CR1_M;

 // 1-Stop Bit

 LPUART1->CR2 &= ~(USART_CR2_STOP_1 | USART_CR2_STOP_0);

 // Set No Parity

 LPUART1->CR1 &= ~USART_CR1_PCE;

 // Enable LPUART TX and RX

 LPUART1->CR1 |= USART_CR1_TE;

 LPUART1->CR1 |= USART_CR1_RE;

 LPUART1->CR1 |= USART_CR1_TXEIE;

 // Enable LPUART

 LPUART1->CR1 |= USART_CR1_UE;

}

void DelayMS(int delay)

{

int i;

for(;delay<0;delay--)

{

for(i=0;i<3195;i++);

}

}

void SendMsg(const char msg[])

 {

  int i = 0;

 while(msg[i] != 0)

  {

LPUART1_putChar(msg[i]);

   i++;

  }

 }

void LPUART1_putChar(char ch)

{

// WHile the TX Buffer is empty

while((LPUART1->ISR & USART_ISR_TXE) == 0)

{

LPUART1->TDR = ch;

}

}

void printString(char * string)

{

while(*string)

{

LPUART1_putChar(*(string++));

}

}

void Toggle_GREEN_LED()

{

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;      // Turn on Peripheral clock GPIOB Enable bit

GPIOB->MODER |= (GPIO_MODER_MODE0_0);     // Set first bit

GPIOB->MODER &= ~(GPIO_MODER_MODE0_1);     // Clear MODER Register 0 bit 1

GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED0_1;   // GPIO MODER Register 0 bit 1

GPIOB->ODR ^= (GPIO_ODR_OD0);         // Toggle GPIO ODR Register bit 0

}

void Toggle_BLUE_LED()

{

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;      // Turn on Peripheral clock GPIOB Enable bit

GPIOB->MODER |= (GPIO_MODER_MODE5_0);     // Set first bit

GPIOB->MODER &= ~(GPIO_MODER_MODE5_1);     // Clear GPIO MODER Register 5 bit 1

GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED5_1;   // Set GPIO speed to Medium speed

GPIOB->ODR ^= (GPIO_ODR_OD5);         // Toggle GPIO ODR Register bit 5

}

void Toggle_RED_LED()

{

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;      // Turn on Peripheral clock GPIOB Enable bit

GPIOB->MODER |= (GPIO_MODER_MODE1_0);     // Set first bit

GPIOB->MODER &= ~(GPIO_MODER_MODE1_1);     // Clear MODER Register 1 bit 1

GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED1_1;   // Set GPIO speed to Medium speed

GPIOB->ODR ^= (GPIO_ODR_OD1);         // Toggle GPIO ODR Register bit 1

}

void Delay(uint32_t d)

{

 for(uint32_t i = 0; i < d; i++);

}

/* Private functions */

/**

**===========================================================================

**

** Abstract: main program

**

**===========================================================================

*/

int main(void)

{

  uint32_t clk = 0;

  //SystemCoreClockUpdate();

  //clk = SystemCoreClock;

  //LPUART1_Init();

   while(1){

   LPUART1_Init();

   LPUART1_putChar('H');

   Delay(50000);

   }

  return 0;

}

3 REPLIES 3
Bob S
Principal

Your equation for the BRR calculation looks wrong. Why /16?

From RM0434 rev 4 (latest on st.com):

Baudrate = (256 * lpuartckpres) / LPARTUDIV

where LRUARTDIV is the BRR value and (I presume) lpuartckpres is the pre-scaled clock input to the LPUART. Since you have the prescaler code commented out, the default is "divide by 1", so your clock is whatever clock you are routing to the LPUART. Are you sure that is 32MHz?

I'll leave it to you to solve that equation for LPUARTDIV (i.e. BRR). The good news is that the resulting BRR value just fits in the 20bit BRR register.

BGibs
Associate II

Hi Bob,

Thank you for your quick response. I forgot to mention I'm pretty new to the STM32 devices.

I was using 32MHz in my c program because I thought the "lpuartckpres" was the clock source

for the AP1 peripheral (I used Cubemx clock configuration diagram).

How do I determine the value for "lpuartckpres" ?

Bob S
Principal

The clock is what your code tells it to be. The RCC CCIPR register determines the clock sources for UARTS and some other peripherals. The default for LPUART is PCLK. Do you have a SystemInit() function somewhere? This is a function that, in some development environments, gets called by the startup code before main(). If you do, see if that alters the CCIPR register. If not, then PCLK it is.

Since you don't change the LPUART prescaler value, that should still be "divide by 1". So your uart clock (lpuartckpres) is (or should be) PCLK divided by 1.

I just noticed something else in your code: your putString() function doesn't do what you think it does. You are de-referencing the pointer AFTER you increment it. This will skip the first character, and then send the trailing NULL. Probably not what you want. Leave off the parens around "string++". Also, the parameter to printString() should be "const char *", so that you can pass it strings that are in FLASH. Without the "const", you cannot do things like printString("Hello world").

void printString(const char * string)
{
   while(*string)
   {
      LPUART1_putChar( *string++ );
   }
}