2022-12-26 05:53 AM
Hi, I am doing a MOOC for learning STM32 programming, in the UART topic, we are supposed to implement UART. The course follows STM32F4 but I have an STM32F303RE and I tried to adapt it to my board but it is still not showing anything on the serial monitor (I tried CuteCom and Arduino Serial Monitors as I use a Mac). Can you please tell me what is wrong with the code below? I tried to input various values directly into the BRR register as I had doubts about the baud rate formula in the course.
#include <stdio.h>
#include <stdint.h>
#include "stm32f303xe.h"
#define IOPAEN (1U<<17)
#define UART2EN (1U<<17)
#define CR1_TE (1U<<3)
#define CR1_UE (1U<<13)
#define SR_TXE (1U<<7)
#define SYS_FREQ 16000000
#define APB1_CLK SYS_FREQ
#define UART_BAUDRATE 115200
static void uart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t BaudRate);
static uint16_t compute_uart_bd(uint32_t PeriphClk, uint32_t BaudRate);
void uart2_tx_init(void);
void uart2_write (int ch);
int main (void){
uart2_tx_init();
while(1){
uart2_write('Y');
}
}
void uart2_tx_init(void){
//Configure UART GPIO pin
// Enable clock access to GPIOA
RCC->AHBENR |= IOPAEN;
// Set PA2 to Alternate Function Mode
GPIOA->MODER &= ~(1U<<4);
GPIOA->MODER |= (1U<<5);
// Set PA2 Alternate Function type to UART_TX (AF07)
GPIOA->AFR[0] |= (1U<<8);
GPIOA->AFR[0] |= (1U<<9);
GPIOA->AFR[0] |= (1U<<10);
GPIOA->AFR[0] &= ~(1U<<11);
//Configure UART Module
// Enable clock access to UART2
RCC->APB1ENR |= UART2EN;
// Configure baud rate
uart_set_baudrate(USART2, APB1_CLK, UART_BAUDRATE);
// Configure the transfer direction
USART2->CR1 = CR1_TE;
// Enable UART module
USART2->CR1 |= CR1_UE;
}
void uart2_write (int ch){
//Make sure transmit data register is empty
while (!(USART2->ISR & SR_TXE)){}
//Write to transmit data register
USART2->TDR = (ch & 0xFF);
}
static void uart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t BaudRate){
USARTx->BRR = compute_uart_bd(PeriphClk,BaudRate);
}
static uint16_t compute_uart_bd(uint32_t PeriphClk, uint32_t BaudRate){
return ((PeriphClk + (BaudRate/2U))/BaudRate);
}
2022-12-26 06:15 AM
One thing I have found is that APB1 frequency is 36Mhz, I tried various values with the formula 36000000/(16*115200) but even that does not work with the BRR register.
2022-12-26 07:09 AM
Perhaps send a stream of U characters and use a scope?
BRR = 36000000 / 115200 is probably a better formula.
Some of the code is also very inefficient. The compiler can't optimize or fold them.
I would enable the clocks first, so you have a slight dwell time before using the registers they clock.
2022-12-26 07:25 AM
Unfortunately I don't have a scope so checking it on a serial monitor on my laptop. I used the formula you suggested and things still don't work. Optimisation is turned off for the compiler. Yes, the clocks are enabled in the init function.
2022-12-26 08:02 AM
Go to debug mode and manually plau woth jart registere
2022-12-26 10:17 AM
Unfortunately I find the debug mode quite complicated but I will try..
2022-12-26 10:18 AM
Another thing I am suspecting is that the course made us configure word length as 8 but my microcontroller's Transmit Data Register has space for 9 bits.. I will try changing the code to adjust for a 9 bit word length.
2022-12-26 10:58 AM
The CR1 register is 0 on POR. You've only enabled CR1_UE and CR1_TE bits. The M bit should be zero so your word length is 8 bits.
2022-12-26 11:12 AM
Yes, but the thing is it 8 bits word length alright or should I change it to 9 bits as the TDR has a space for 9 bits.
2022-12-26 11:43 AM
Unless the course says to change to 9 bits, leave it as 8 bits. How is the UART communicating to the serial program? USB to Serial adapter (TTL level) and hopefully not a USB to RS232 adapter?