Blame | Last modification | View Log | RSS feed
#include <xc.h>
#include <plib.h>
#include "defines.h"
#include "UART1.h"
static UART1_DATA *uart_data_ptr;
void UART1_Init(UART1_DATA *data, void (*rx_callback)(char)) {
uart_data_ptr = data;
uart_data_ptr->rx_callback = rx_callback;
uart_data_ptr->buffer_out_len = 0;
uart_data_ptr->buffer_out_ind = 0;
INTDisableInterrupts();
IEC0CLR = 0x1C000000; // Disable all UART1 interrupts
IFS0CLR = 0x1C000000; // Clear any existing events
IPC6SET = 0x00000009; // Set Priority = 2, Subpriority = 1
U1MODE = 0x00008000; // UART enabled, BRGH = 0
U1STA = 0x00009400; // TX interrupt on buffer empty, RX interrupt on buffer not empty
U1BRG = 19; // Set baud rate to 256000 @ 80MHz
IEC0SET = 0x0C000000; // Enable the RX and Error interrupts
INTEnableInterrupts();
TRISDbits.TRISD14 = 0;
PORTDbits.RD14 = 0;
}
int UART1_Write(char *string, int length) {
if (length > UART1_BUFFER_SIZE)
return 0;
if (uart_data_ptr->buffer_out_len != 0)
return 0;
// Put the data to send into the outbound buffer
uart_data_ptr->buffer_out_len = length;
uart_data_ptr->buffer_out_ind = 0;
int i;
for (i = 0; i < length; i++) {
uart_data_ptr->buffer_out[i] = string[i];
}
IEC0SET = 0x10000000; // Enable TX interrupt
return 1;
}
void __ISR(_UART_1_VECTOR, ipl2) __UART_1_Interrupt_Handler(void) {
PORTDbits.RD14 = 1;
// Process UART1 error flag
if (IFS0bits.U1EIF) {
if (U1STAbits.PERR) { // Process parity error
}
if (U1STAbits.FERR) { // Process frame error
}
if (U1STAbits.OERR) { // Process receive buffer overrun error
U1STAbits.OERR = 0; // Clear the overrun error if set
}
IFS0CLR = 0x04000000; // Clear the error flag
}
// Process UART1 recieve flag
if (IFS0bits.U1RXIF) {
// Read the data received from the last transfer
while (U1STAbits.URXDA) {
char c = U1RXREG;
// Call the RX callback function on each received data
if (uart_data_ptr->rx_callback != NULL) {
(*uart_data_ptr->rx_callback)(c);
}
}
IFS0CLR = 0x08000000; // Clear the recieve flag
}
// Process UART1 transmit flag
if (IFS0bits.U1TXIF) {
// Disable the transmit interrupt if all data has been sent
if (uart_data_ptr->buffer_out_ind == uart_data_ptr->buffer_out_len) {
IEC0CLR = 0x10000000;
uart_data_ptr->buffer_out_len = 0;
} else {
// Start filling the transmit buffer
while (!U1STAbits.UTXBF) {
U1TXREG = uart_data_ptr->buffer_out[uart_data_ptr->buffer_out_ind];
uart_data_ptr->buffer_out_ind++;
if (uart_data_ptr->buffer_out_ind == uart_data_ptr->buffer_out_len)
break;
}
}
IFS0CLR = 0x10000000; // Clear the transmit flag
}
PORTDbits.RD14 = 0;
}