/*
* Author: Pawel Jablonski
* E-mail: pj@xirx.net
* WWW: xirx.net
* GIT: git.xirx.net
*
* License: You can use this code however you like
* but leave information about the original author.
* Code is free for non-commercial and commercial use.
*/
#include <stm32f0xx.h>
#include <stm32f0xx_hal.h>
#include <stm32f0xx_hal_gpio.h>
#include <stm32f0xx_hal_rcc.h>
#include <stm32f0xx_hal_uart.h>
#include <stm32f0xx_hal_usart.h>
#include <system_stm32f0xx.h>
#include "type.h"
#include "rs232.h"
#define RS232_BUFFER_RX_SIZE 64 //!< Receive buffer size
#define RS232_BUFFER_TX_SIZE 64 //!< Transmit buffer size
static unsigned char bufferRx[RS232_BUFFER_RX_SIZE]; //!< Receive circular buffer
static volatile unsigned int bufferRxStart = 0; //!< Receive data start position
static volatile unsigned int bufferRxEnd = 0; //!< Receive data end position
static unsigned char bufferTx[RS232_BUFFER_TX_SIZE]; //!< Transmit circular buffer
static volatile unsigned int bufferTxStart = 0; //!< Transmit data start position
static volatile unsigned int bufferTxEnd = 0; //!< Transmit data end position
static UART_HandleTypeDef uartHandle; //!< UART HAL handle
//! Init rs232 and set up UART
void rs232Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpioInit = {0};
gpioInit.Pin = (GPIO_PIN_9 | GPIO_PIN_10);
gpioInit.Mode = GPIO_MODE_AF_PP;
gpioInit.Pull = GPIO_PULLUP;
gpioInit.Speed = GPIO_SPEED_FREQ_HIGH;
gpioInit.Alternate = GPIO_AF1_USART1;
HAL_GPIO_Init(GPIOA, &gpioInit);
__HAL_RCC_USART1_CLK_ENABLE();
uartHandle.Instance = USART1;
uartHandle.Init.BaudRate = 1200;
uartHandle.Init.WordLength = UART_WORDLENGTH_8B;
uartHandle.Init.StopBits = UART_STOPBITS_1;
uartHandle.Init.Parity = UART_PARITY_NONE;
uartHandle.Init.Mode = UART_MODE_TX_RX;
uartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
uartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&uartHandle);
__HAL_UART_ENABLE(&uartHandle);
HAL_NVIC_SetPriority(USART1_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_UART_Receive_IT(&uartHandle, bufferRx, 1);
}
/**
* Send char
*
* @param byte Char to send
*/
void rs232Send(unsigned char byte)
{
__disable_irq();
{
if(bufferTxStart == bufferTxEnd)
{
bufferTx[bufferTxEnd] = byte;
bufferTxEnd = ((bufferTxEnd + 1) % RS232_BUFFER_TX_SIZE);
HAL_UART_Transmit_IT(&uartHandle, (bufferTx + bufferTxStart), 1);
}
else
{
if(bufferTxStart == ((bufferTxEnd + 1) % RS232_BUFFER_TX_SIZE))
{
__enable_irq();
}
bufferTx[bufferTxEnd] = byte;
bufferTxEnd = ((bufferTxEnd + 1) % RS232_BUFFER_TX_SIZE);
}
}
__enable_irq();
}
/**
* Read a next char from receive buffer
*
* @return Next char from the receive buffer
*/
unsigned char rs232Receive(void)
{
__disable_irq();
{
if(bufferRxStart == bufferRxEnd)
{
__enable_irq();
return(0);
}
else
{
unsigned char byte = bufferRx[bufferRxStart];
bufferRxStart = ((bufferRxStart + 1) % RS232_BUFFER_RX_SIZE);
__enable_irq();
return(byte);
}
}
}
/**
* Check if is a new data in the buffer
*
* @return Status of waiting data in receive buffer
*/
bool rs232RxIsData(void)
{
__disable_irq();
if(bufferRxStart == bufferRxEnd)
{
__enable_irq();
return(FALSE);
}
else
{
__enable_irq();
return(TRUE);
}
}
//! Take care of the UART IRQ event
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&uartHandle);
}
/**
* Callback of the receive UART HAL event. Read a next char from the UART.
*
* @param handler UART HAL handle
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *handler)
{
if(handler->Instance == USART1)
{
__disable_irq();
{
if(bufferRxStart == ((bufferRxEnd + 1) % RS232_BUFFER_RX_SIZE))
{
bufferRxStart = ((bufferRxStart + 1) % RS232_BUFFER_RX_SIZE);
}
bufferRxEnd = ((bufferRxEnd + 1) % RS232_BUFFER_RX_SIZE);
HAL_UART_Receive_IT(&uartHandle, (bufferRx + bufferRxEnd), 1);
}
__enable_irq();
}
}
/**
* Callback of the of the transmit UART HAL event. Write a next char to the UART.
*
* @param handler UART HAL handle
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *handler)
{
if(handler->Instance == USART1)
{
__disable_irq();
{
bufferTxStart = ((bufferTxStart + 1) % RS232_BUFFER_TX_SIZE);
if(bufferTxStart == bufferTxEnd)
{
__enable_irq();
return;
}
HAL_UART_Transmit_IT(&uartHandle, (bufferTx + bufferTxStart), 1);
}
__enable_irq();
}
}