📄 elinmint.c
字号:
/*********************************************************************
*
* LIN-Master Software
*
*********************************************************************
* FileName: ELINMInt.c
* Dependencies: ELINMInt.h
* Processor: 18Fxxxx
* Compilers: Microchip C Compiler -> mcc C18 v2.20 or better
* Assembler: MPASMWIN 02.70.02 or higher
* Linker: MPLINK 2.33.00 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the "Company") is intended and supplied to you, the Company抯
* customer, for use solely and exclusively with products manufactured
* by the Company.
*
* The software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*
* This FW provides the necessary functions to create a Master LIN
* node driver using an EUSART enabled 18F part.
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* CG 09/4/03 Initial Release (Maestro 1.0)
*
********************************************************************/
#define _LINM18ESOURCE
#include "ELINMInt.h"
BYTE _ELINMIntMessageTag; // message tag -> identifies one specific message
ELINMINT_CRC _ELINMIntRXCRC; // reception CRC buffer
ELINMINT_STATUS _ELINMIntStatus; // main status byte
ELINMINT_STATUS1 _ELINMIntStatus1; // second status byte
ELINMINT_MESSAGE_SIZE _ELINMIntMessageSize; // message size
ELINMINT_MESSAGE_SIZE _ELINMIntRXMessageSize; // reception message size
BYTE _ELINMIntMessageBuffer[ELINMINT_MAX_MESSAGE_SIZE+3]; // message buffer
BYTE _ELINMIntReadBack; // saves the last transmitted byte to be compared with feedback
BYTE _ELINMIntMessageBufferPointer; // TX byte position pointer
char _ELINMIntSpace; // interbyte and interframe space
unsigned int _ELINMIntTFrameMin; // timing control variables
unsigned int _ELINMIntTFrameMax;
unsigned int _ELINMIntTHeaderMin;
unsigned int _ELINMIntTHeaderMax;
unsigned long _ELINMIntSleepTimeout; // sleep time-out count variable
/*********************************************************************
* Function: BYTE _ELINMIntInitialize(void)
*
* PreCondition:
*
* Input:
* Output: 0=NO Error
* !0=ERROR CODE
*
* Side Effects:
*
* Stack Requirements:
*
* Overview: This procedure Initializes:
* The Baud Rate
* Reception Interrupt (enabled)
* Protocol Status bytes - > put protocol in IDLE
* Interbyte timing
*
********************************************************************/
BYTE _ELINMIntInitialize(void)
{
SPBRG =ELINMINT_SPBRG; // set Baud Rate (16 bits)
SPBRGH =ELINMINT_SPBRGH;
TXSTA =ELINMINT_TXSTA_INIT; // initiates transmission and reception
RCSTA =ELINMINT_RCSTA_INIT;
BAUDCON=ELINMINT_BAUDCON_INIT;
PIE1 |=ELINMINT_PIE1_INIT; //
_ELINMIntSleepTimeout=ELINMINT_SLEEP_TIMEOUT; // init bus idle-to-sleep timing
_ELINMIntSpace=ELINMINT_INTERBYTE_SPACE; // start interbyte space
_ELINMIntStatus.ELINMIntStatusByte=0; // clear status
_ELINMIntStatus1.ELINMIntStatusByte=0; // clear status1
_ELINMIntStatus.ELINMINTSTS.IDLE=1; // return to idle state
return(0); // return 0 - OK
}
/*********************************************************************
* Function: void _ELINMIntResetProtocol(BYTE code)
*
* PreCondition:
*
* Input: BYTE code - any eventual error code
*
* Output:
*
* Side Effects:
*
* Stack Requirements:
*
* Overview: This procedure resets the protocol and if necessary
* sets the error flags
*
********************************************************************/
void _ELINMIntResetProtocol(BYTE code)
{
_ELINMIntReadBack=RCREG; // read the receive register to clear RCIF flag
_ELINMIntStatus1.ELINMIntStatusByte=0; // reset all aux. status conditions including
// sleep timeout
_ELINMIntRXCRC.CRC=0; // reset CRC
_ELINMIntStatus.ELINMIntStatusByte=code; // status code set.
_ELINMIntSleepTimeout=ELINMINT_SLEEP_TIMEOUT; // init bus idle-to-sleep timing
}
/*********************************************************************
* Function: void interrupt ELINMIntHandler(void)
*
* PreCondition:
*
* Input:
* Output:
*
* Side Effects:
*
* Stack Requirements:
*
* Overview: Interrupt Handler for EUSART based Master node LIN
* To be called by a timer based interrupt routine
*
********************************************************************/
void ELINMIntHandler(void)
{
if(TXSTA_SENDB==0) // check if it is not sending break
{
if(PIR1_RCIF) // also checks if received something
{
if(_ELINMIntStatus.ELINMINTSTS.IDLE) // check if in IDLE state
{
if((RCSTA&0x06)==0) // if received without error
{
if(RCREG==ELINMINT_WAKEUP_BYTE) // then check if it was an wake-up request
{
_ELINMIntSleepTimeout=ELINMINT_SLEEP_TIMEOUT; // reinit bus-idle-to sleep timing
_ELINMIntReadBack=RCREG; // read the receive register to clear RCIF flag
if(_ELINMIntStatus1.ELINMINTSTS.WAKEUP_SENT) // if an wake-up signal was sent from the master to the slave
_ELINMIntStatus1.ELINMINTSTS.WAKEUP_SENT=0; // clear the flag
else // if wake-up signal
_ELINMIntStatus1.ELINMINTSTS.WAKEUP=1; // set the wake-up flag
} // else if(RCREG==ELINMINT_WAKEUP_BYTE)
} // if((RCSTA&0x06)==0)
} // if(_ELINMIntStatus.ELINMINTSTS.IDLE)
else if(_ELINMIntStatus.ELINMINTSTS.TX) // check if transmitting
{
if((RCSTA&0x06)&&_ELINMIntMessageBufferPointer) // if error and it's not in the BREAK byte (pointer==0)
_ELINMIntResetProtocol(ELINMINT_IDLEBIT+ELINMINT_ERRORBIT+ELINMINT_FRAMING_ERROR); // signal the error
else // if no error detected or error detected in BREAK (expected)
{
if(_ELINMIntMessageBufferPointer==2) // then check if it just sent the HEADER
_ELINMIntStatus1.ELINMINTSTS.HEADER=0; // if so turn-off the header transmission flag (it will trigger the check of header max. time)
if(_ELINMIntSpace) // if interbyte space not zero decrement and go away
_ELINMIntSpace--;
else if(_ELINMIntReadBack!=RCREG) // otherwise check if the byte read is the same as the sent one
_ELINMIntResetProtocol(ELINMINT_IDLEBIT+ELINMINT_ERRORBIT+ELINMINT_DATA_ERROR); // if not signals the error
else // if byte read is the same as the sent one
{
if(_ELINMIntMessageSize.SIZE) // and if there is still message to be sent
{
_ELINMIntReadBack=RCREG; // read the receive register to clear RCIF flag
_ELINMIntReadBack=_ELINMIntMessageBuffer[_ELINMIntMessageBufferPointer]; // load next byte to be sent
TXREG=_ELINMIntReadBack; // also load the read-back check byte
_ELINMIntMessageSize.SIZE--; // decrement the counter
_ELINMIntMessageBufferPointer++; // increment the pointer
_ELINMIntSpace+=ELINMINT_INTERBYTE_SPACE; // start interbyte space counter
}
else // if all message already transmitted
{
if(_ELINMIntStatus.ELINMINTSTS.RX) // and if it's set to receive
{
_ELINMIntStatus.ELINMINTSTS.TX=0; // then clear the transmission flag
_ELINMIntMessageBufferPointer=0; // and reset the pointer
}
else // however, if it's not going to receive
{
_ELINMIntStatus1.ELINMINTSTS.FRAME=0; // then clear frame check flag (force the max. frame time to be checked)
_ELINMIntResetProtocol(ELINMINT_IDLEBIT); // reset the protocol without error
} // else
} // else
} // else
} // else of "if((RCSTA&0x06)&&ELINMIntMessageBufferPointer)"
} // else if(_ELINMIntStatus.ELINMINTSTS.TX)
else if(_ELINMIntStatus.ELINMINTSTS.RX) // if receiving
{
if(RCSTA&0x06) // and if an error was detected
_ELINMIntResetProtocol(ELINMINT_IDLEBIT+ELINMINT_ERRORBIT+ELINMINT_FRAMING_ERROR); // reset protocol with error
else
{
if(_ELINMIntRXMessageSize.SIZE) // if no error detected and if there is still message to be received
{
_ELINMIntMessageBuffer[_ELINMIntMessageBufferPointer]=RCREG; // load message data byte in the buffer
_ELINMIntRXMessageSize.SIZE--; // decrement the counter
_ELINMIntRXCRC.CRC+=RCREG; // add to CRC
if(_ELINMIntRXCRC.CRCbits.CRC8) // if a carry bit from the lower byte
_ELINMIntRXCRC.CRCL++; // add the carry bit
_ELINMIntMessageBufferPointer++; // increment pointer
} // if(ELINMIntRXMessageSize.SIZE)
else // if all data bytes already received
{
_ELINMIntStatus1.ELINMINTSTS.FRAME==0;
_ELINMIntRXCRC.CRCL += RCREG+1; // check CRC(checksum) by XORing received CRC
if(_ELINMIntRXCRC.CRCL)
_ELINMIntResetProtocol(ELINMINT_IDLEBIT+ELINMINT_ERRORBIT+ELINMINT_CHECKSUM_ERROR); // if error reset protocol and signal error // if result != 0 error!
else
_ELINMIntResetProtocol(ELINMINT_IDLEBIT); // otherwise just reset protocol without error
} // else
} // else
} // else if(_ELINMIntStatus.ELINMINTSTS.RX)
} // if(PIR1_RCIF)
} // if(SENDB==0)
if(_ELINMIntStatus.ELINMINTSTS.IDLE==0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -