/** ************************************************************************************************** * @file usart.c * @author Kerem Yollu & Edwin Koch * @date 03.11.2021 * @version 0.4 Unstable ************************************************************************************************** * @brief Implementation of usart.h for the STM32F042K6 MCU * * **Detailed Description :** * * This source code uses bit manipulation in order to minimise the footprint of pin initialisation * and manipulation. It's based on the CMSIS/Device/ST/STM32F0xx/Include/stm32f042x6.h Header file * to get the obtain the right Registers. * * @todo: * - 04.11.21 check if the buad rate calcutation is working good for all awailable baud rates * - 04.11.21 Implment interrupts asap * - 04.11.21 Implment other functionalities as they are needed ************************************************************************************************** */ #include "usart.h" #include "pin.h" #define SYST_CLK 8000000 #define AF1 0x01 #define USART_CHANNEL ((USART_TypeDef *)channel) void usartInit( usartNo_t channel, pinNo_t pinTx, pinNo_t pinRx, uint32_t baud, usartWordLength_t lenght, uint8_t parity, usartHwFlowCtrl_t flowCtrl) { /* Configuring the pins for the uart*/ usartInitTx(pinTx); usartInitRx(pinRx); //Enable the UART Module on the periferal bus this must be done before setting any register. if(channel == usart2) { RCC->APB1ENR |= RCC_APB1ENR_USART2EN; } else { RCC->APB2ENR |= RCC_APB2ENR_USART1EN; } USART_CHANNEL->CR1 = 0; // The = 0 is on purpose to set uart to default mode. USART_CHANNEL->CR2 = 0; // The = 0 is on purpose to set uart to default mode. USART_CHANNEL->CR3 = 0; // The = 0 is on purpose to set uart to default mode. usartSetBaudRate(channel,baud); usartSetWordLenght(channel, lenght); usartSetHwFlowCtrl(channel, flowCtrl); USART_CHANNEL->CR1 |= USART_CR1_TE; //Enbale trasnmit USART_CHANNEL->CR1 |= USART_CR1_RE; //Enable recieve //UART Enable shall allwas be at the end of configuration. USART_CHANNEL->CR1 |= USART_CR1_UE; } void usartInitTx(pinNo_t pinTx) { //pinConfig(pinTx, alternate, def_stage, def_res, def_speed); pinSetMode(pinTx,alternate); pinSetAlternate(pinTx, AF1); } void usartInitRx(pinNo_t pinRx) { //pinConfig(pinRx, alternate, def_stage, def_res, def_speed); pinSetMode(pinRx,alternate); pinSetAlternate(pinRx, AF1); } //this one is special as the register bist's don't follow eachother. void usartSetWordLenght(usartNo_t channel, usartWordLength_t lenght) { if(lenght == seven) { USART_CHANNEL->CR1 |= USART_CR1_M1; USART_CHANNEL->CR1 &= ~USART_CR1_M0; } else if (lenght == eight) { USART_CHANNEL->CR1 &= ~USART_CR1_M0; USART_CHANNEL->CR1 &= ~USART_CR1_M1; } else if(lenght == nine) { USART_CHANNEL->CR1 &= ~USART_CR1_M1; USART_CHANNEL->CR1 |= USART_CR1_M0; } } static uint16_t usartComputeBaudRate(uint32_t clk, uint32_t baud) { //return((clk + (baud/2U))/baud); return(clk/baud); } void usartSetBaudRate(usartNo_t channel, uint32_t baud) { USART_CHANNEL->BRR = usartComputeBaudRate(SYST_CLK,baud); } void usartSetHwFlowCtrl(usartNo_t channel, usartHwFlowCtrl_t flowCtrl) { if(flowCtrl == noFlowControl) { USART_CHANNEL->CR3 &= ~USART_CR3_CTSE; USART_CHANNEL->CR3 &= ~USART_CR3_RTSE; } else if(flowCtrl == cts) { USART_CHANNEL->CR3 |= USART_CR3_CTSE; } else if(flowCtrl == rts) { USART_CHANNEL->CR3 |= USART_CR3_RTSE; } else if(flowCtrl == ctsRts) { USART_CHANNEL->CR3 |= USART_CR3_CTSE; USART_CHANNEL->CR3 |= USART_CR3_RTSE; } } void print_Usart(usartNo_t channel,char *ptr) { uint16_t len = 0; while(ptr[len] != '\0') { usartSendChar(channel, ptr[len]); len++; } } void usartSendChar(usartNo_t channel, uint8_t ch) { // Make sure that TX buffer is empty while(!(USART_CHANNEL->ISR & USART_ISR_TXE)){} USART_CHANNEL->TDR = ch; } uint8_t usartGetChar(usartNo_t channel) { // Make sure that TX buffer is empty while(!(USART_CHANNEL->ISR & USART_ISR_RXNE)){} return USART_CHANNEL->RDR; }