Loading...
Searching...
No Matches
uart.c
1/***********************************************************************************
2 * @file uart.c *
3 * @author Matt Ricci *
4 * @addtogroup UART *
5 * @brief Brief description of the file's purpose. *
6 * *
7 * @todo Tidy up `_UART_setup` *
8 * @todo Implement printf *
9 * @todo Add println function *
10 ***********************************************************************************/
11
12#include "uart.h"
13
14/* =============================================================================== */
27 UART *uart,
28 char name[DEVICE_NAME_LENGTH],
29 USART_TypeDef *interface,
30 GPIO_TypeDef *port,
31 UART_Pins pins,
32 uint32_t baud,
33 OversampleMode over8
34) {
35 uart->setBaud = UART_setBaud;
36 uart->send = UART_send;
38 uart->print = UART_print;
39 uart->receive = UART_receive;
40 uart->interface = interface;
41 uart->port = port;
42 uart->pins = pins;
43 uart->baud = baud;
44 uart->over8 = over8;
45
46 _UART_setup(uart, pins);
47 DeviceHandle_t handle;
48 strcpy(handle.name, name);
49 handle.device = uart;
50
51 return handle;
52}
53
54/********************************** PRIVATE METHODS *********************************/
55
56#ifndef DOXYGEN_PRIVATE
57
58/* =============================================================================== */
66void _UART_setup(UART *uart, UART_Pins pins) {
67 GPIO_TypeDef *port = uart->port;
68 USART_TypeDef *interface = uart->interface;
69
70 // Clear MODER bits for the TX and RX pins
71 port->MODER &= ~((0x03 << GPIO_MODER(pins.TX)) | (0x03 << GPIO_MODER(pins.RX))); // Clear mode bits
72 port->MODER |= (GPIO_MODE_AF << GPIO_MODER(pins.TX)) | (GPIO_MODE_AF << GPIO_MODER(pins.RX)); // Set mode to AF
73
74 // Clear AFR for the TX and RX pins and set AF8
75 port->AFR[pins.TX / 8] &= ~(0x0F << ((pins.TX % 8) * 4)); // Clear AF bits for TX
76 port->AFR[pins.RX / 8] &= ~(0x0F << ((pins.RX % 8) * 4)); // Clear AF bits for RX
77 port->AFR[pins.TX / 8] |= ((interface <= USART3 ? UART_AF7 : UART_AF8) << ((pins.TX % 8) * 4)); // Set AF8 for TX
78 port->AFR[pins.RX / 8] |= ((interface <= USART3 ? UART_AF7 : UART_AF8) << ((pins.RX % 8) * 4)); // Set AF8 for RX
79
80 // Set pull-up for RX pin
81 port->PUPDR &= ~(0x03 << GPIO_PUPDR(pins.RX)); // Clear pull-up/pull-down bits for RX
82 port->PUPDR |= (GPIO_PULL_UP << GPIO_PUPDR(pins.TX)); // Set pull-up for RX
83
84 // Set speed for TX and RX pins
85 port->OSPEEDR &= ~((0x03 << GPIO_OSPEEDR(pins.TX)) | (0x03 << GPIO_OSPEEDR(pins.RX))); // Clear speed bits
86 port->OSPEEDR |= (GPIO_SPEED_HIGH << GPIO_OSPEEDR(pins.TX)); // Set high speed for TX
87 port->OSPEEDR |= (GPIO_SPEED_HIGH << GPIO_OSPEEDR(pins.RX)); // Set high speed for RX
88
89 // Calculate USARTDIV
90 uint16_t usartDiv = 168000000 / ((2 - (uart->over8)) * uart->baud);
91 interface->BRR &= 0xFFFF0000; // Clear mantissa and div in baud rate reg
92 interface->BRR |= usartDiv; // Set baud rate
93
94 interface->CR1 &= ~USART_CR1_PCE; // disable parity
95 interface->CR2 &= ~USART_CR2_CLKEN; // disable synchrnous mode
96 interface->CR3 &= ~(USART_CR3_CTSE | USART_CR3_RTSE); // disable flow control
97 interface->CR1 |= (USART_CR1_RXNEIE); // enable RXNE interrupt
98 interface->CR1 |= (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE); // enable usart, enable receive and transmit
99}
100
101#endif
102
103/********************************** INTERFACE METHODS ********************************/
104
105void UART_setBaud(UART *uart, uint32_t baud) {
106 GPIO_TypeDef *port = uart->port;
107 USART_TypeDef *interface = uart->interface;
108
109 USART1->CR1 &= ~USART_CR1_UE;
110
111 // Calculate USARTDIV
112 uint16_t usartDiv = 168000000 / ((2 - (uart->over8)) * baud);
113 interface->BRR &= 0xFFFF0000; // Clear mantissa and div in baud rate reg
114 interface->BRR |= usartDiv; // Set baud rate
115
116 USART1->CR1 |= USART_CR1_UE;
117}
118
119/* =============================================================================== */
128void UART_send(UART *uart, uint8_t data) {
129 USART_TypeDef *interface = uart->interface;
130 while ((interface->SR & USART_SR_TXE) == 0);
131 interface->DR = data;
132 while ((interface->SR & USART_SR_TC) == 0);
133}
134
135/* =============================================================================== */
145void UART_sendBytes(UART *uart, uint8_t *data, int length) {
146 for (int i = 0; i < length; i++)
147 UART_send(uart, data[i]);
148}
149
150/* =============================================================================== */
159
160void UART_print(UART *uart, char *data) {
161 int i = 0;
162 while (data[i] != '\0')
163 UART_send(uart, data[i++]);
164}
165
166/* =============================================================================== */
174uint8_t UART_receive(UART *uart) {
175 USART_TypeDef *interface = uart->interface;
176 while ((interface->SR & USART_SR_RXNE) == 0);
177 return (uint8_t)(interface->DR & 0xFF);
178}
void(* print)(struct UART *, char *)
UART print string method.
Definition uart.h:62
void(* sendBytes)(struct UART *, uint8_t *, int)
UART send multiple bytes method.
Definition uart.h:61
void(* send)(struct UART *, uint8_t)
UART send method.
Definition uart.h:60
uint8_t(* receive)(struct UART *)
UART receive method.
Definition uart.h:63
void UART_send(UART *, uint8_t data)
Sends a single byte of data over the UART interface.
Definition uart.c:128
void UART_print(UART *, char *data)
Sends a string of characters over the UART interface.
Definition uart.c:160
void _UART_setup(UART *uart, UART_Pins pins)
Configures the UART interface for communication.
Definition uart.c:66
DeviceHandle_t UART_init(UART *uart, char name[DEVICE_NAME_LENGTH], USART_TypeDef *interface, GPIO_TypeDef *port, UART_Pins pins, uint32_t baud, OversampleMode over8)
Initialiser for a UART device interface.
Definition uart.c:26
void UART_sendBytes(UART *, uint8_t *data, int length)
Sends an array of bytes over the UART interface.
Definition uart.c:145
uint8_t UART_receive(UART *)
Receives a single byte of data from the UART interface.
Definition uart.c:174
Struct definition for UART interface.
Definition uart.h:53