?? uartintc.c
字號:
/*******************************************************************************
sioapi.c
********************************************************************************
Written by: Shaheen Mahomed
nSoft Developement.
********************************************************************************
Version
0.00aA 17 Jun 04 SSM Began using pic18 uart code from MPLab Maestro
0.00aB 14 Aug 04 BDW Patching in data handeling
0.00aD 15 Sep 04 BDW Making build compatible with new Protocessors
0.00aI 11 Oct 04 BDW Increasing SIO buffer sizes
*******************************************************************************/
#if defined ( P18F6720 )
#include <p18f6720.h>
#elif defined (P18F6520)
#include <p18f6520.h>
#else
#error must defined P18F6X20 compiler option
#endif
#include <fst.h>
#include <sioapi.h>
#include "UARTIntC.h"
#include <led.h>
#include <delays.h>
#define TMR2_PERIOD_REGISTER 156 // timer2 period register
UINT32 mseconds = 0;
/*Interrupt service routine*/
VOID high_isr(VOID);
// serial interrupt taken as low priority interrupt
#pragma code uart_int_service = 0x08
VOID uart_int_service(VOID)
{
_asm
goto high_isr
_endasm
}
#pragma code
#pragma interrupt high_isr save=section(".tmpdata")
VOID high_isr(VOID)
{
if ( PIR1bits.TMR2IF )
{
mseconds++;
PIR1bits.TMR2IF = 0;
}
UARTIntISR();
}
// status flags of receive and transmit buffers
#pragma udata sio_0 = 0xa00
tx_status tx_vUARTIntStatus1;
#pragma udata sio_1 = 0xb00
rx_status rx_vUARTIntStatus1;
#pragma udata sio_2 = 0xc00
tx_status tx_vUARTIntStatus2;
#pragma udata sio_3 = 0xd00
rx_status rx_vUARTIntStatus2;
/*********************************************************************
* Function: VOID UARTIntInit(VOID)
* PreCondition: None
* Input: None
* Output: None
* Side Effects: None
* Stack Requirements: 1 level deep
* Overview: This function initialises UART peripheral.This
* function need to be called before using
* UARTIntPutChar and UARTIntGetChar functions to
* send and receive the characters.
********************************************************************/
VOID UARTIntInit ( UINT iport)
{
tx_status *tx_vUARTIntStatus ;
rx_status *rx_vUARTIntStatus ;
mCheckPortHandle(iport);
if (iport==(UINT)P6720SER1)
{
tx_vUARTIntStatus = &tx_vUARTIntStatus1 ;
rx_vUARTIntStatus = &rx_vUARTIntStatus1 ;
}
else
{
tx_vUARTIntStatus = &tx_vUARTIntStatus2 ;
rx_vUARTIntStatus = &rx_vUARTIntStatus2 ;
}
// Intialising the status variables and circular buffer
// variables .
tx_vUARTIntStatus->UARTIntTxBufferFull = 0;
tx_vUARTIntStatus->UARTIntTxBufferEmpty = 1;
tx_vUARTIntStatus->vUARTIntTxBufDataCnt = 0;
tx_vUARTIntStatus->vUARTIntTxBufWrPtr = 0;
tx_vUARTIntStatus->vUARTIntTxBufRdPtr = 0;
rx_vUARTIntStatus->UARTIntRxBufferFull = 0;
rx_vUARTIntStatus->UARTIntRxBufferEmpty = 1;
rx_vUARTIntStatus->UARTIntRxError = 0;
rx_vUARTIntStatus->UARTIntRxOverFlow = 0;
rx_vUARTIntStatus->vUARTIntRxBufDataCnt = 0;
rx_vUARTIntStatus->vUARTIntRxBufWrPtr = 0;
rx_vUARTIntStatus->vUARTIntRxBufRdPtr = 0;
if ( iport == (UINT)P6720SER1 )
{
/* Initialising BaudRate value */
TXSTAbits.BRGH = BRGH_VAL;
mSetUARTPort ( iport, DEFAULT_UART_BAUDRATE, 0) ;
/* Setting priority */
IPR1bits.TXIP = 1;
IPR1bits.RCIP = 1;
/* Enabling Transmitter or Receiver */
TXSTAbits.TXEN = 1;
RCSTAbits.CREN = 1;
/* Enabling Serial Port */
RCSTAbits.SPEN = 1;
/* Enable the TX and RX. Interrupt */
PIE1bits.RCIE = 1;
/* Initialising TX/RX port pins */
DDRCbits.RC6 = 0;
DDRCbits.RC7 = 1;
/*Setting RTS pin as output, and low */
PORTCbits.RC5 = 0 ;
DDRCbits.RC5 = 0;
}
else
{
/* Initialising BaudRate value */
TXSTA2bits.BRGH = BRGH_VAL;
mSetUARTPort ( iport, DEFAULT_UART_BAUDRATE, 0) ;
/* Setting priority */
IPR3bits.TX2IP = 1;
IPR3bits.RC2IP = 1;
/* Enabling Transmitter or Receiver */
TXSTA2bits.TXEN = 1;
RCSTA2bits.CREN = 1;
/* Enabling Serial Port */
RCSTA2bits.SPEN = 1;
/* Enable the TX and RX. Interrupt */
PIE3bits.RC2IE = 1;
/* Initialising TX/RX port pins */
DDRGbits.RG1 = 0;
DDRGbits.RG2 = 1;
/*Setting RTS pin as output, and low */
PORTGbits.RG3 = 0 ;
DDRGbits.RG3 = 0;
}
/*Enable priority interrupts*/
RCONbits.IPEN = 1;
/* Setting Global interrupt pins */
INTCONbits.GIEH = 1;
INTCONbits.GIEL = 1;
}
/*********************************************************************
* Function: BYTE UARTIntPutString(BYTE*)
* PreCondition: UARTIntInit()function should have been called.
* Input: BYTE pointer
* Output: BYTE
* 1 - string is successfully
* added to transmit buffer.
* 0 - transmit buffer is full and the
* character could not be added to
* transmit buffer.
*
* Side Effects: None
* Stack Requirements: 1 level deep
* Overview: This function puts the data in to transmit
* buffer. Internal implementation wise ,
* it places the argument data in transmit buffer
* and updates the data count and write pointer
* variables.
*
********************************************************************/
BYTE UARTIntPutString(UINT iport, BYTE *stCharData, UINT length)
{
tx_status *tx_vUARTIntStatus ;
UINT i;
BYTE bytetosend;
mCheckPortHandle(iport);
if (iport==(UINT)P6720SER1)
{
tx_vUARTIntStatus = &tx_vUARTIntStatus1 ;
}
else
{
tx_vUARTIntStatus = &tx_vUARTIntStatus2 ;
}
// Check if TX_BUFFER already full
if ( tx_vUARTIntStatus->UARTIntTxBufferFull )
{
//todo : Flag an error,
return CD_ERROR ;
}
//critical code , disable interrupts
if ( iport == (UINT)P6720SER1 )
{
PIE1bits.TXIE = 0;
#if ( ENABLE_SER1_RS485 == 'Y' )
Delay1KTCYx (1) ; // at 10 Mhz, 1000 instruction cycles delay for 0.4 ms.
mSetRS485_RTSHigh ( P6720SER1 ) ;
#endif
}
else if ( iport == (UINT)P6720SER2 )
{
PIE3bits.TX2IE = 0;
#if ( ENABLE_SER2_RS485 == 'Y' )
Delay1KTCYx (1) ; // at 10 Mhz, 1000 instruction cycles delay for 0.4 ms.
mSetRS485_RTSHigh ( P6720SER2 ) ;
#endif
}
// Put data in TX_BUFFER
for ( i=0; i < length; i++ )
{
tx_vUARTIntStatus->vUARTIntTxBuffer[tx_vUARTIntStatus->vUARTIntTxBufWrPtr] = stCharData[i];
tx_vUARTIntStatus->UARTIntTxBufferEmpty = 0;
tx_vUARTIntStatus->vUARTIntTxBufDataCnt ++;
if ( tx_vUARTIntStatus->vUARTIntTxBufDataCnt == (BYTE)TX_BUFFER_SIZE )
{
tx_vUARTIntStatus->UARTIntTxBufferFull = 1;
break; // Else we will overrun our buffers
}
tx_vUARTIntStatus->vUARTIntTxBufWrPtr++;
if ( tx_vUARTIntStatus->vUARTIntTxBufWrPtr == (BYTE)TX_BUFFER_SIZE )
{
tx_vUARTIntStatus->vUARTIntTxBufWrPtr = 0;
}
}
if ( iport == (UINT)P6720SER1 )
{
PIE1bits.TXIE = 1;
}
else if ( iport == (UINT)P6720SER2 )
{
PIE3bits.TX2IE = 1;
}
return 1;
}
/*********************************************************************
* Function: BYTE UARTIntGetTxBufferEmptySpace(VOID)
* PreCondition: UARTIntInit()function should have been called.
* Input: None
* Output: BYTE
* 0 - There is no empty space in
* transmit buffer.
* number - the number of bytes of empty
* space in transmit buffer.
*
*
* Side Effects: None
* Stack Requirements: 1 level deep
* Overview: This function returns the number of bytes
* of free space left out in transmit buffer at
* the calling time of this function. It helps
* the user to further write data in to transmit
* buffer at once, rather than checking transmit
* buffer is full or not with every addition of
* data in to the transmit buffer.
********************************************************************/
BYTE UARTIntGetTxBufferDataSize(UINT iport)
{
mCheckPortHandle(iport);
if (iport==(UINT)P6720SER1)
{
return tx_vUARTIntStatus1.vUARTIntTxBufDataCnt ;
}
else
{
return tx_vUARTIntStatus2.vUARTIntTxBufDataCnt ;
}
}
/*********************************************************************
* Function: BYTE UARTIntGetChar(BYTE*)
* PreCondition: UARTIntInit()function should have been called.
* Input: BYTE*
* Output: BYTE
* 0 - receive buffer is empty and the
* character could not be read from
* the receive buffer.
* 1 - single character is successfully
* read from receive buffer.
* Side Effects: None
* Stack Requirements: 1 level deep
* Overview: This function reads the data from the receive
* buffer. It places the data in to argument and
* updates the data count and read pointer
* variables of receive buffer.
*
********************************************************************/
BYTE UARTIntGetChar(UINT iport)
{
rx_status *rx_vUARTIntStatus ;
BYTE rxchar;
mCheckPortHandle(iport);
if (iport==(UINT)P6720SER1)
{
rx_vUARTIntStatus = &rx_vUARTIntStatus1 ;
}
else
{
rx_vUARTIntStatus = &rx_vUARTIntStatus2 ;
}
if ( rx_vUARTIntStatus->UARTIntRxBufferEmpty )
return 0;
//critical code, disabling interrupts here keeps the
//access pointer values proper.
if ( iport == (UINT)P6720SER1 )
{
PIE1bits.RCIE = 0;
}
else if ( iport == (UINT)P6720SER2 )
{
PIE3bits.RC2IE = 0;
}
rx_vUARTIntStatus->UARTIntRxBufferFull = 0;
rxchar = rx_vUARTIntStatus->vUARTIntRxBuffer[rx_vUARTIntStatus->vUARTIntRxBufRdPtr];
rx_vUARTIntStatus->vUARTIntRxBufDataCnt--;
if ( rx_vUARTIntStatus->vUARTIntRxBufDataCnt == (UINT)0 )
{
rx_vUARTIntStatus->UARTIntRxBufferEmpty = (UINT)1;
}
rx_vUARTIntStatus->vUARTIntRxBufRdPtr++;
if ( rx_vUARTIntStatus->vUARTIntRxBufRdPtr == (BYTE)RX_BUFFER_SIZE )
{
rx_vUARTIntStatus->vUARTIntRxBufRdPtr = 0;
}
if ( iport == (UINT)P6720SER1 )
{
PIE1bits.RCIE = 1;
}
else if ( iport == (UINT)P6720SER2 )
{
PIE3bits.RC2IE = 1;
}
return rxchar;
}
/*********************************************************************
* Function: BYTE UARTIntGetRxBufferDataSize(VOID)
* PreCondition: UARTIntInit()function should have been called.
* Input: None
* Output: BYTE
* number - the number of bytes
* of data in receive buffer.
* Side Effects: None
* Stack Requirements: 1 level deep
* Overview: This function returns the number of bytes
* of data available in receive buffer at
* the calling time of this function. It helps
* the user to read data from receive buffer
* at once, rather than checking receive buffer
* is empty or not with every read of data from
* receive buffer.
********************************************************************/
BYTE UARTIntGetRxBufferDataSize(UINT iport)
{
mCheckPortHandle(iport);
if (iport==(UINT)P6720SER1)
{
return rx_vUARTIntStatus1.vUARTIntRxBufDataCnt ;
}
else
{
return rx_vUARTIntStatus2.vUARTIntRxBufDataCnt ;
}
}
/*********************************************************************
* Function: VOID UARTIntISR(VOID)
* PreCondition: UARTIntInit() function should have been called.
* Input: None
* Output: None
* Side Effects: None
* Stack Requirements: 2 level deep
* Overview: This is the Interrupt service routine which is
* called in the user application's ISR portion.
* This function actually sends the data from
* transmit buffer to USART and updates the data
* count and read pointer variables of transmit
* buffer. For the receive portion, it reads the
* data from USART and places the data in to
* receive buffer (if no errors occured) and
* updates data count and write pointer variables
* of receive buffer. If the receive buffer is
* full and it receives more data error flag is
* set.If frame errors(FERR) occur it sets the
* error flag. If over flow errors(OERR) occurs,
* it clears and sets the CREN bit, so that
* USART can receive further data.
********************************************************************/
VOID UARTIntISR(VOID)
{
BYTE chTemp;
tx_status *tx_vUARTIntStatus = &tx_vUARTIntStatus1 ;
rx_status *rx_vUARTIntStatus = &rx_vUARTIntStatus1 ;
//------------------------------------------------------------
//
// TX Interrupts
//
if ( PIR1bits.TXIF & PIE1bits.TXIE )
{
if ( !tx_vUARTIntStatus->UARTIntTxBufferEmpty )
{
TXREG = tx_vUARTIntStatus->vUARTIntTxBuffer[tx_vUARTIntStatus->vUARTIntTxBufRdPtr];
//if ( parity )
// {
// addParityBit(0, vUARTIntStatus->vUARTIntTxBuffer[vUARTIntStatus->vUARTIntTxBufRdPtr]);
// }
tx_vUARTIntStatus->UARTIntTxBufferFull = 0;
tx_vUARTIntStatus->vUARTIntTxBufDataCnt--;
if ( tx_vUARTIntStatus->vUARTIntTxBufDataCnt == (UINT)0 )
{
tx_vUARTIntStatus->UARTIntTxBufferEmpty = 1;
}
tx_vUARTIntStatus->vUARTIntTxBufRdPtr++;
if ( tx_vUARTIntStatus->vUARTIntTxBufRdPtr >= (BYTE)TX_BUFFER_SIZE )
{
tx_vUARTIntStatus->vUARTIntTxBufRdPtr = 0;
}
}
else
{
PIE1bits.TXIE = 0;
#if ( ENABLE_SER1_RS485 == 'Y' )
while ( TXSTAbits.TRMT == (BYTE)0 );
Delay1KTCYx (1) ; // at 10 Mhz, 1000 instruction cycles delay for 0.4 ms.
mSetRS485_RTSLow ( P6720SER1 );
#endif
}
}
//------------------------------------------------------------
//
// RX Interrupts
//
if ( PIR1bits.RCIF & PIE1bits.RCIE )
{
if ( RCSTAbits.FERR )
{ /* FERR error condition */
chTemp = RCREG;
rx_vUARTIntStatus->UARTIntRxError = 1;
}
else if ( RCSTAbits.OERR )
{ /* OERR error condition */
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
chTemp = RCREG;
rx_vUARTIntStatus->UARTIntRxError = 1;
}
else if ( rx_vUARTIntStatus->UARTIntRxBufferFull )
{
chTemp = RCREG;
rx_vUARTIntStatus->UARTIntRxOverFlow = 1;
}
else if ( !rx_vUARTIntStatus->UARTIntRxBufferFull )
{
rx_vUARTIntStatus->UARTIntRxOverFlow = 0;
rx_vUARTIntStatus->UARTIntRxBufferEmpty = 0;
rx_vUARTIntStatus->vUARTIntRxBuffer[rx_vUARTIntStatus->vUARTIntRxBufWrPtr] = RCREG;
rx_vUARTIntStatus->vUARTIntRxBufDataCnt ++;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -