145 lines
3.8 KiB
C
145 lines
3.8 KiB
C
/*
|
|
* UART.c
|
|
*
|
|
* Created: 25/11/2021 16:26:10
|
|
* Author: n0x
|
|
*/
|
|
|
|
#include "UART.h"
|
|
|
|
/* create structs for TX and TX buffer */
|
|
CircularBuffer TxBuffer;
|
|
CircularBuffer* pTxBuffer = &TxBuffer;
|
|
CircularBuffer RxBuffer;
|
|
CircularBuffer* pRxBuffer = &RxBuffer;
|
|
|
|
volatile uint8_t TxActive;
|
|
|
|
void
|
|
uart_init(void) {
|
|
UBRR0 = 103; /* set BAUD rate to 9600 */
|
|
|
|
UCSR0C |=
|
|
(0<<UMSEL00)|(0<<UMSEL01)| /* Async UART */
|
|
(0<<UPM00)|(0<<UPM01)| /* Disable Parity */
|
|
(1<<UCSZ00)|(1<<UCSZ01)| /* 8 Bit */
|
|
(0<<USBS0); /* 1 Stopbit */
|
|
|
|
UCSR0B |=
|
|
(1<<TXEN0)|(1<<RXEN0)| /* enable send and receive */
|
|
(1<<RXCIE0); /* enable Receive interrupts */
|
|
|
|
|
|
/* Initiate read- and write-pointers with 0 */
|
|
pTxBuffer->Readpointer = 0;
|
|
pTxBuffer->Writepointer = 0;
|
|
pRxBuffer->Readpointer = 0;
|
|
pRxBuffer->Writepointer = 0;
|
|
}
|
|
|
|
/********Sending Data********/
|
|
|
|
void
|
|
uart_send_string(char* string) {
|
|
/* Take a whole string and transmit every char from it */
|
|
int i = 0;
|
|
while(string[i] != '\0'){
|
|
uart_send_byte(string[i]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void
|
|
uart_send_byte(char c) {
|
|
/* Disable the TX Interrupt to prevent issues while writing to the send buffer*/
|
|
UCSR0B &= ~(1<<TXCIE0);
|
|
|
|
/* Check if a transmit is in progress
|
|
if yes -> write the byte to the buffer
|
|
if no -> write the byte to the UDR0 register and enable the transmit in progress flag
|
|
*/
|
|
if(TxActive){
|
|
pTxBuffer->data[pTxBuffer->Writepointer++] = c;
|
|
if (pTxBuffer->Writepointer>=SIZE_BUFFER){
|
|
pTxBuffer->Writepointer = 0;
|
|
}
|
|
} else {
|
|
TxActive = 1;
|
|
UDR0 = c;
|
|
}
|
|
/* Enable the TX Interrupt again*/
|
|
UCSR0B |= (1<<TXCIE0);
|
|
}
|
|
|
|
/* when data (a data frame) is to be send (written to UDR0) */
|
|
ISR(USART0_TX_vect) {
|
|
/* check if the read and write pointer of the send buffer are not aligned
|
|
if not aligned -> read the next byte and write it to UDR0 register
|
|
if aligned -> no more data to send, disable the send in progress flag */
|
|
if(pTxBuffer->Readpointer != pTxBuffer->Writepointer)
|
|
{
|
|
/* writing data to the register withing the interrupt will cause a new interrupt which then will repeat till no more data is to be read from the send buffer */
|
|
UDR0 = pTxBuffer->data[pTxBuffer->Readpointer++];
|
|
|
|
if(pTxBuffer->Readpointer >= SIZE_BUFFER){
|
|
pTxBuffer->Readpointer = 0;
|
|
}
|
|
} else {
|
|
TxActive = 0;
|
|
}
|
|
}
|
|
|
|
/*******Receiving Data*******/
|
|
uint8_t
|
|
uart_data_available(void) {
|
|
uint8_t dataAvailabel = 0;
|
|
/* Disable the RX Interrupt to prevent issues when checking if data is available */
|
|
UCSR0B &= ~(1<<RXCIE0);
|
|
|
|
/* check if read and write pointer are at different locations
|
|
if yes -> data is available and can be read */
|
|
if(pRxBuffer->Readpointer != pRxBuffer->Writepointer){
|
|
dataAvailabel = 1;
|
|
}
|
|
|
|
/* Enable the RX Interrupt again*/
|
|
UCSR0B |= (1<<RXCIE0);
|
|
return dataAvailabel;
|
|
}
|
|
|
|
char
|
|
uart_get_data(void) {
|
|
char data = 0;
|
|
/* Disable the RX Interrupt to prevent issues when reading out a char from the buffer */
|
|
UCSR0B &= ~(1<<RXCIE0);
|
|
|
|
/* check if read and write pointer are at different locations
|
|
if yes -> data is available and can be read */
|
|
if(pRxBuffer->Readpointer != pRxBuffer->Writepointer)
|
|
{
|
|
/* read a char from the buffer and increment the read pointer */
|
|
data = pRxBuffer->data[pRxBuffer->Readpointer++];
|
|
if(pRxBuffer->Readpointer >= SIZE_BUFFER){
|
|
pRxBuffer->Readpointer = 0;
|
|
}
|
|
}
|
|
/* Enable the RX Interrupt again*/
|
|
UCSR0B |= (1<<RXCIE0);
|
|
/* give back the read in character */
|
|
return data;
|
|
}
|
|
|
|
/* when data (a data frame) is received */
|
|
ISR(USART0_RX_vect) {
|
|
uint8_t status = UCSR0A;
|
|
uint8_t data = UDR0;
|
|
|
|
/* check status flags if data is correctly accessible */
|
|
if((status & ((1<<DOR0) | (1<<FE0))) == 0){
|
|
/* Save data to buffer and increment the write pointer */
|
|
pRxBuffer->data[pRxBuffer->Writepointer++] = data;
|
|
if(pRxBuffer->Writepointer >= SIZE_BUFFER) {
|
|
pRxBuffer->Writepointer = 0;
|
|
}
|
|
}
|
|
} |