0,0 → 1,106 |
#include <xc.h> |
#include "defines.h" |
#include "UART.h" |
|
static UART_DATA *data_ptr; |
|
void UART_Init(UART_DATA *data) { |
data_ptr = data; |
|
APFCON0bits.RXDTSEL = 1; // Change RX from RB5 to RC5 |
APFCON0bits.TXCKSEL = 1; // Change TX from RB7 to RC4 |
UART_RX_TRIS = 1; |
UART_TX_TRIS = 0; |
|
SPBRG = 16; // Set baud rate to 115200 @ 32MHz |
BAUDCONbits.BRG16 = 0; // 8-bit baud rate generator |
TXSTAbits.BRGH = 1; // High baud rate select |
|
TXSTAbits.SYNC = 0; // Async operation |
RCSTAbits.CREN = 1; // Enable reception module |
TXSTAbits.TXEN = 1; // Enable transmission module |
RCSTAbits.SPEN = 1; // Enable EUSART module |
|
PIE1bits.RCIE = 1; // UART RX interrupt starts enabled |
PIE1bits.TXIE = 0; // UART TX interrupt starts disabled |
|
// Initialize local variables |
data_ptr->buffer_in_read_ind = 0; |
data_ptr->buffer_in_write_ind = 0; |
data_ptr->buffer_in_len = 0; |
data_ptr->buffer_out_ind = 0; |
data_ptr->buffer_out_len = 0; |
} |
|
void UART_TX_Interrupt_Handler(void) { |
// Send more data when transmit buffer is empty |
if (data_ptr->buffer_out_ind != data_ptr->buffer_out_len) { |
TXREG = data_ptr->buffer_out[data_ptr->buffer_out_ind]; |
data_ptr->buffer_out_ind++; |
} else { |
// Stop processing TX interrupts if there is no more data to send |
while (!TXSTAbits.TRMT); |
PIE1bits.TXIE = 0; |
data_ptr->buffer_out_ind = 0; |
data_ptr->buffer_out_len = 0; |
} |
} |
|
void UART_RX_Interrupt_Handler(void) { |
char c = RCREG; |
|
// Read received data into buffer |
data_ptr->buffer_in[data_ptr->buffer_in_write_ind] = c; |
if (data_ptr->buffer_in_write_ind == UART_BUFFER_SIZE - 1) { |
data_ptr->buffer_in_write_ind = 0; |
} else { |
data_ptr->buffer_in_write_ind++; |
} |
|
// Increment read counter to keep only the latest data |
if (data_ptr->buffer_in_len < UART_BUFFER_SIZE) { |
data_ptr->buffer_in_len++; |
} else { |
if (data_ptr->buffer_in_read_ind == UART_BUFFER_SIZE - 1) { |
data_ptr->buffer_in_read_ind = 0; |
} else { |
data_ptr->buffer_in_read_ind++; |
} |
} |
|
// Reset receiver module on overrun error |
if (RCSTAbits.OERR == 1) { |
RCSTAbits.CREN = 0; |
RCSTAbits.CREN = 1; |
} |
} |
|
void UART_Write(char *data, char length) { |
// Ensure that no transmission is currently running |
while (PIE1bits.TXIE); |
|
data_ptr->buffer_out_len = length; |
data_ptr->buffer_out_ind = 0; |
for (char i = 0; i < length; i++) { |
data_ptr->buffer_out[i] = data[i]; |
} |
|
// Start transmission |
PIE1bits.TXIE = 1; |
} |
|
char UART_Read(char *buffer) { |
PIE1bits.RCIE = 0; // Disable receiver interrupt |
char length = data_ptr->buffer_in_len; |
for (char i = 0; i < length; i++) { |
buffer[i] = data_ptr->buffer_in[data_ptr->buffer_in_read_ind]; |
if (data_ptr->buffer_in_read_ind == UART_BUFFER_SIZE - 1) { |
data_ptr->buffer_in_read_ind = 0; |
} else { |
data_ptr->buffer_in_read_ind++; |
} |
} |
data_ptr->buffer_in_len -= length; |
PIE1bits.RCIE = 1; // Re-enable receiver interrupt |
return length; |
} |