#include "uart.h" #include "registers.h" #include "stm32f401xe.h" void usart_init(uart_t *uart, USART_TypeDef *peripheral, uint8_t idx) { uart->periph = peripheral; uart->idx = idx; } void usart_configure_speed(uart_t *uart, uint32_t clock_freq, uint32_t baud) { // 12 000 000 / 9600 / 16 = 78.125 uint32_t temp = clock_freq / baud; uint32_t mantissa = temp / 16; uint32_t fraction = temp % 16; if (fraction == 15 && ((temp + 8) % 16) == 0) { mantissa++; fraction = 0; } uart->periph->BRR = (mantissa << USART_BRR_DIV_Mantissa_Pos) | (fraction << USART_BRR_DIV_Fraction_Pos); } void usart_configure_uart(uart_t *uart, bool enable, usart_word_length_t length, bool parity_control, usart_parity_t parity, usart_stop_bits_t stop_bits) { reg_write_bits(&uart->periph->CR1, (enable << USART_CR1_UE_Pos) | (parity << USART_CR1_PS_Pos) | (parity_control << USART_CR1_PCE_Pos) | (length << USART_CR1_M_Pos), USART_CR1_UE_Msk | USART_CR1_PS_Msk | USART_CR1_PCE_Msk | USART_CR1_M_Msk); reg_write_bits(&uart->periph->CR2, (stop_bits << USART_CR2_STOP_Pos), USART_CR2_STOP_Msk); } void usart_configure_receiver(uart_t *uart, bool enable) { reg_write_bits(&uart->periph->CR1, enable << USART_CR1_RE_Pos, USART_CR1_RE_Msk); } void usart_configure_transmitter(uart_t* uart, bool enable) { reg_write_bits(&uart->periph->CR1, (enable == true) << USART_CR1_TE_Pos, USART_CR1_TE_Msk); } uint16_t usart_transmit(uart_t *uart, char *data, uint16_t size) { for (int16_t i = 0; i < size; i++) { while (!(uart->periph->SR & USART_SR_TXE)); char byte = *(data++); uart->periph->DR = byte; } return size; } uint16_t usart_receive(uart_t* uart, char *buffer, uint16_t max_size) { uint16_t size = 0; while (size < max_size && (uart->periph->SR & USART_SR_RXNE)) { *(buffer + (size++)) = (char)(uart->periph->DR & USART_DR_DR_Msk); } return size; } bool usart_can_transmit(uart_t* uart) { return uart->periph->SR & USART_SR_TXE; } uint16_t usart_can_receive(uart_t* uart) { return ((uart->periph->SR & USART_SR_RXNE) != 0) ? 1 : 0; } void usart_enable_interrupt(uart_t *uart, bool tx, bool rx) { reg_write_bits(&uart->periph->CR1, (tx << USART_CR1_TXEIE_Pos) | (rx << USART_CR1_RXNEIE_Pos), USART_CR1_TXEIE | USART_CR1_RXNEIE); // TODO: proper irq by idx NVIC_SetPriority(USART2_IRQn, 1); NVIC_EnableIRQ(USART2_IRQn); }