Page MenuHomec4science

uart.c
No OneTemporary

File Metadata

Created
Sat, Aug 24, 20:28
#include "uart.h"
#include "p33FJ128MC804.h"
#include "config.h"
#include "pindefs.h"
#include "sbcp.h"
#include "timer.h"
/*************************************************************************
*
* DEFINES
*
*************************************************************************/
#define BAUDRATE_ERROR_MARGIN 30 // in 10 times percent (40 = 4 percent)
// Automatic calculation of baudrate settings for bus communication
// STEP1: Calculate different baudrate options and corresponding errors
// Option 1: low speed mode; rounding down
#define BRGVAL_BUS_LD ((FCY_FOR_BAUDRATE/BAUDRATE_BUS)/16)-1
#if BRGVAL_BUS_LD >= 0 // check if register value is a positive number
#define BAUDRATE_BUS_LD (FCY_FOR_BAUDRATE/(16*(BRGVAL_BUS_LD+1)))
#define BAUDRATE_ERROR_BUS_LD_T ((1000*BAUDRATE_BUS_LD - 1000*BAUDRATE_BUS)/BAUDRATE_BUS)
// calculate absolute error
#if BAUDRATE_ERROR_BUS_LD_T < 0
#define BAUDRATE_ERROR_BUS_LD -BAUDRATE_ERROR_BUS_LD_T
#else
#define BAUDRATE_ERROR_BUS_LD BAUDRATE_ERROR_BUS_LD_T
#endif
#else
// make sure that for negative register values the error can never be below the error margin
#define BAUDRATE_ERROR_BUS_LD 2*BAUDRATE_ERROR_MARGIN
#endif
// Option 2: low speed mode; rounding up
#define BRGVAL_BUS_LU ((FCY_FOR_BAUDRATE/BAUDRATE_BUS)/16)
#if BRGVAL_BUS_LU >= 0 // check if register value is a positive number
#define BAUDRATE_BUS_LU (FCY_FOR_BAUDRATE/(16*(BRGVAL_BUS_LU+1)))
#define BAUDRATE_ERROR_BUS_LU_T ((1000*BAUDRATE_BUS_LU - 1000*BAUDRATE_BUS)/BAUDRATE_BUS)
#if BAUDRATE_ERROR_BUS_LU_T < 0 // calculate absolute error
#define BAUDRATE_ERROR_BUS_LU -BAUDRATE_ERROR_BUS_LU_T
#else
#define BAUDRATE_ERROR_BUS_LU BAUDRATE_ERROR_BUS_LU_T
#endif
#else
// make sure that for negative register values the error can never be below the error margin
#define BAUDRATE_ERROR_BUS_LU 2*BAUDRATE_ERROR_MARGIN
#endif
// Option 3: high speed mode; rounding down
#define BRGVAL_BUS_HD ((FCY_FOR_BAUDRATE/BAUDRATE_BUS)/4)-1
#if BRGVAL_BUS_HD >= 0 // check if register value is a positive number
#define BAUDRATE_BUS_HD (FCY_FOR_BAUDRATE/(4*(BRGVAL_BUS_HD+1)))
#define BAUDRATE_ERROR_BUS_HD_T ((1000*BAUDRATE_BUS_HD - 1000*BAUDRATE_BUS)/BAUDRATE_BUS)
#if BAUDRATE_ERROR_BUS_HD_T < 0 // calculate absolute error
#define BAUDRATE_ERROR_BUS_HD -BAUDRATE_ERROR_BUS_HD_T
#else
#define BAUDRATE_ERROR_BUS_HD BAUDRATE_ERROR_BUS_HD_T
#endif
#else
// make sure that for negative register values the error can never be below the error margin
#define BAUDRATE_ERROR_BUS_HD 2*BAUDRATE_ERROR_MARGIN
#endif
// Option 4: high speed mode; rounding up
#define BRGVAL_BUS_HU ((FCY_FOR_BAUDRATE/BAUDRATE_BUS)/4)
#if BRGVAL_BUS_HU >= 0 // check if register value is a positive number
#define BAUDRATE_BUS_HU (FCY_FOR_BAUDRATE/(4*(BRGVAL_BUS_HU+1)))
#define BAUDRATE_ERROR_BUS_HU_T ((1000*BAUDRATE_BUS_HU - 1000*BAUDRATE_BUS)/BAUDRATE_BUS)
#if BAUDRATE_ERROR_BUS_HU_T < 0 // calculate absolute error
#define BAUDRATE_ERROR_BUS_HU -BAUDRATE_ERROR_BUS_HU_T
#else
#define BAUDRATE_ERROR_BUS_HU BAUDRATE_ERROR_BUS_HU_T
#endif
#else
// make sure that for negative register values the error can never be below the error margin
#define BAUDRATE_ERROR_BUS_HU 2*BAUDRATE_ERROR_MARGIN
#endif
// STEP2: Check error values and decide for register values / uart option
// Try low speed mode first
#if BAUDRATE_ERROR_BUS_LD > BAUDRATE_ERROR_BUS_LU
#if (BAUDRATE_ERROR_BUS_LU < BAUDRATE_ERROR_MARGIN)
#warning "UART BUS: Picked UART low speed mode and rounding up"
#define BRGHVAL_BUS 0 // low speed mode
#define BRGVAL_BUS BRGVAL_BUS_LU
#endif
#else
#if (BAUDRATE_ERROR_BUS_LD < BAUDRATE_ERROR_MARGIN)
#warning "UART BUS: Picked UART low speed mode and rounding down"
#define BRGHVAL_BUS 0 // low speed mode
#define BRGVAL_BUS BRGVAL_BUS_LD
#endif
#endif
// If low speed mode is not working -> try high speed mode
#ifndef BRGVAL_BUS
#if BAUDRATE_ERROR_BUS_HD > BAUDRATE_ERROR_BUS_HU
#if (BAUDRATE_ERROR_BUS_HU < BAUDRATE_ERROR_MARGIN)
#warning "UART BUS: Picked UART high speed mode and rounding up"
#define BRGHVAL_BUS 1 // high speed mode
#define BRGVAL_BUS BRGVAL_BUS_HU
#endif
#else
#if (BAUDRATE_ERROR_BUS_HD < BAUDRATE_ERROR_MARGIN)
#warning "UART BUS: Picked UART high speed mode and rounding down"
#define BRGHVAL_BUS 1 // high speed mode
#define BRGVAL_BUS BRGVAL_BUS_HD
#endif
#endif
#endif
// If both high and low speed mode are not working - > stop compilation and print error message
#ifndef BRGVAL_BUS
#error "BAUDRATE_ERROR_BUS is above BAUDRATE_ERROR_MARGIN. Could not solve that problem automatically. Consider setting BRGVAL_BUS by hand, using a different baudrate or system frequency."
#endif
/*
void __attribute__((__interrupt__ , no_auto_psv)) _U1ErrInterrupt(void) {
IFS4bits.U1EIF = 0;
*((unsigned char *) (((void*)DMA0STA) + ((unsigned int)&_DMA_BASE)) + 1 ) = 0x00;
if(dma_sbcp.bus_uart_error_enable_flags ) { //Any flag is enabled
dma_sbcp.bus_rx_error |= SBCP_ERROR_CODE_BUS_FRAME_ERROR;
}
}
*/
void uart_init()
{
//------------- UART1 --------------------------
U1MODEbits.STSEL = 0; // 1-stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-data bits
U1MODEbits.ABAUD = 0; // Auto-Baud Disabled
U1MODEbits.BRGH = BRGHVAL_BUS; // Low Speed mode
U1BRG = BRGVAL_BUS; // BAUD Rate Setting
// If UTXISEL<1:0> = 01, the UxTXIF is set when the last character is shifted out of the
// UxTSR register. This implies that all the transmit operations are completed.
//here we interrupt for each char
U1STAbits.UTXISEL0 = 0;
U1STAbits.UTXISEL1 = 0;
U1STAbits.URXISEL0 = 0; // Interrupt after one RX character is received;
U1STAbits.URXISEL1 = 0;
IEC0bits.U1TXIE = 0; // Disable UART Tx interrupt
IEC0bits.U1RXIE = 0; // Disable UART Rx interrupt
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART Tx
//------------- UART2 --------------------------
/*U2MODEbits.STSEL = 0; // 1-stop bit
U2MODEbits.PDSEL = 0; // No Parity, 8-data bits
U2MODEbits.ABAUD = 0; // Auto-Baud Disabled
U2MODEbits.BRGH = 0; // Low Speed mode
U2BRG = BRGVAL; // BAUD Rate Setting
U2STAbits.UTXISEL0 = 0; // Interrupt after one Tx character is transmitted
U2STAbits.UTXISEL1 = 0;
U2STAbits.URXISEL0 = 0; // Interrupt after one RX character is received;
U2STAbits.URXISEL1 = 0;
IEC1bits.U2TXIE = 0; // Enable UART Tx interrupt
IEC1bits.U2RXIE = 1; // Enable UART Rx interrupt
U2MODEbits.UARTEN = 1; // Enable UART
U2STAbits.UTXEN = 1; // Enable UART Tx
*/
}

Event Timeline