67 lines
1.9 KiB
C
67 lines
1.9 KiB
C
#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++);
|
|
}
|