2025-03-03 6:31 PM - last edited on 2025-03-04 6:14 AM by Andrew Neil
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');
}
}
2025-03-04 12:53 AM - edited 2025-03-04 12:54 AM
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.
2025-03-04 3:47 AM
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