Add usart.{h, c}
This commit is contained in:
66
src/usart.c
Normal file
66
src/usart.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#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++);
|
||||
}
|
||||
Reference in New Issue
Block a user