#include "rcc.h" #include "gpio.h" #include "usart.h" void usart2_init(void) { // Enable clock for GPIOA as USART2 is on PORT A pins RCC->AHB1ENR |= (1 << PORT('A')); // Configure PA2 and PA3 (USART2 pins) to use alternative functions uint16_t txPin = PIN('A', 2); gpio_set_mode(txPin, GPIO_MODE_AF); gpio_set_af(txPin, GPIO_AF_USART2_TX); uint16_t rxPin = PIN('A', 3); gpio_set_mode(rxPin, GPIO_MODE_AF); gpio_set_af(rxPin, GPIO_AF_USART2_RX); // Enable USART RCC->APB1ENR |= RCC_APB1ENR_USART2EN_ENABLE; // Clear control registers USART2->CR1 = 0; USART2->CR2 = 0; USART2->CR3 = 0; // Calculate Baud rate: // baud = f_clck / (8 * (2 - OVER8) * USARTDIV) => // (8 * (2 - OVER8) * USARTDIV) = f_clock / baud => // baud * (8 * (2 - OVER8) * USARTDIV) = f_clock => // USARTDIV = (f_clock / (baud * (8 * (2 - OVER8))) // Target Baud rate = 115200, f_clock = 48MHz, OVER8 = 0 // USARTDIV = 48E6 / (115200 * 8 * 2) = 26.0416666 // mantissa = 26 = 0x1A // fraction = 0.041666 * 16 = 0.666656 ~= 1 // baud = 48E6 / (8 * 2 * 26) = 115384.61538461539 // error of 0.16% (115384.61538461539 / 115200 ) = 1.001602564102564 // // skipping fractional part as error rate is good. USART2->BRR &= ~(USART_BRR_MANTISSA_MASK << USART_BRR_MANTISSA_BIT); USART2->BRR |= (0x1A << USART_BRR_MANTISSA_BIT); USART2->BRR &= ~(USART_BRR_FRACTION_MASK << USART_BRR_FRACTION_BIT); USART2->BRR |= (0x0 << USART_BRR_MANTISSA_BIT); // Enable transmitter and receiver USART2->CR1 |= USART_CR1_TE_ENABLE; USART2->CR1 |= USART_CR1_RE_ENABLE; } void usart2_start(void) { USART2->CR1 |= USART_CR1_UE_ENABLE; } void usart2_write_byte(uint8_t c) { USART2->DR = c; // Wait indefinitely for transmission to be ready for data while (!(USART2->SR & USART_SR_TC_COMPLETED)); } void usart2_write(char *buf) { while (*buf) usart2_write_byte(*buf++); }