📄 lin.c
字号:
/////////////////////////////////////////////////////////////////////////////////////////
//
// LIN Sample for Freescale EVB9S08DZ60
// LIN communication data from master to slave
//
// --------------------------------------------------------------------------------------
//
// Copyright (c) 2006 SofTec Microsystems
// http://www.softecmicro.com/
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// NOTES:
//
// - LIN bus communication is set to work about at 20Kb/s.
// - Only standard checksum is used.
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "derivative.h"
#include "lin.h"
/////////////////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////////////////
struct frame rx;
/////////////////////////////////////////////////////////////////////////////////////////
// LINInit
// --------------------------------------------------------------------------------------
// SCI Peripheral Initialization
/////////////////////////////////////////////////////////////////////////////////////////
void LINInit(void)
{
int sbr,i;
// Calculates SCI baud rate value
sbr=(SCI_CLOCK/SCI_BAUDRATE/16);
SCI1BDH =(unsigned char)(sbr>>8);
SCI1BDL =(unsigned char)sbr;
//Enable SCI0 and receiver interrupt
SCI1C2 =0x2C;
// Break character is 13 or 14 bit long
SCI1S2=0x04;
// Initializes LIN receive frames
rx.protected_id=0;
rx.state=IDLE;
rx.error=0;
rx.check=0;
for (i=0;i<MAX_DATA;i++)
rx.data[i]=0;
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINCalcParity
// --------------------------------------------------------------------------------------
// LIN Parity Calculation Routine
/////////////////////////////////////////////////////////////////////////////////////////
unsigned char LINCalcParity(unsigned char id)
{
unsigned char parity, p0,p1;
parity=id;
p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6;
p1=(~(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7;
parity|=(p0|p1);
return parity;
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINCalcChecksum
// --------------------------------------------------------------------------------------
// LIN Checksum Calculation Routine
/////////////////////////////////////////////////////////////////////////////////////////
unsigned char LINCalcChecksum(unsigned char *data)
{
unsigned int sum = 0;
unsigned char i;
for(i = 0; i < MAX_DATA; i++)
{
sum += data[i];
if(sum&0xFF00)
// Adds carry
sum = (sum&0x00FF) + 1;
}
sum ^= 0x00FF;
return (unsigned char)sum;
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINGetChar
// --------------------------------------------------------------------------------------
// SCI data receive routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINGetChar(void)
{
unsigned volatile char ch;
// State of the LIN receive channel
switch(rx.state++)
{
case IDLE:
if(!(SCI1S1&0x22))
return(FALSE);
if(SCI1D)
return(FALSE);
break;
case _BREAK:
if(!(SCI1S1&0x20))
return(FALSE);
if(SCI1D != 0x55)
return(FALSE);
break;
case SYNCH:
if(!(SCI1S1&0x20))
return(FALSE);
ch = SCI1D;
rx.protected_id = ch;
break;
case PROTECTED_IDENTIFIER:
case DATA_0:
case DATA_1:
case DATA_2:
case DATA_3:
case DATA_4:
case DATA_5:
case DATA_6:
if(!(SCI1S1&0x20))
return(FALSE);
ch = SCI1D;
rx.data[rx.state-DATA_0] = ch;
if((rx.state-DATA_0+1) == MAX_DATA)
rx.state = DATA_7;
break;
case DATA_7:
if(!(SCI1S1&0x20))
return(FALSE);
ch = SCI1D;
rx.check = ch;
break;
case CHECKSUM:
return(FALSE);
}
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINGetMsg
// --------------------------------------------------------------------------------------
// LIN Message Receive Routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINGetMsg(Bool get_data, struct message *msg)
{
unsigned char i;
if(rx.state < PROTECTED_IDENTIFIER)
return FALSE;
msg->identifier = (rx.protected_id&0x3F);
if (get_data)
{
if(rx.state == CHECKSUM)
{
for(i = 0; i < MAX_DATA; i++)
msg->data_field[i] = rx.data[i];
rx.state = IDLE;
}
else
for(i = 0; i < MAX_DATA; i++)
msg->data_field[i] = 0;
}
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINCheckSend
// --------------------------------------------------------------------------------------
// Sent byte field check routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINCheckSend(enum lin_state status, unsigned char val)
{
// While until sci data has been received
while(rx.state < status)
if(rx.error)
return(FALSE);
switch(status)
{
case _BREAK:
case SYNCH:
break;
case PROTECTED_IDENTIFIER:
if(rx.protected_id != val)
return(FALSE);
break;
case DATA_0:
case DATA_1:
case DATA_2:
case DATA_3:
case DATA_4:
case DATA_5:
case DATA_6:
case DATA_7:
if(rx.data[status-DATA_0] != val)
return(FALSE);
break;
case CHECKSUM:
if(rx.check != val)
return(FALSE);
break;
}
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINSendChar
// --------------------------------------------------------------------------------------
// SCI byte fields sending routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINSendChar(Bool brk, unsigned char ch)
{
// Waits until transmit data registry is empty (TDRE=1)
while(!(SCI1S1&0x80))
;
// If break field, transmits one break character (13-14 bits of dominant value)
if(brk)
{
SCI1C2 |= 0x01;
SCI1C2 &= ~0x01;
}
else
SCI1D = ch;
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINSendMsg
// --------------------------------------------------------------------------------------
// LIN Message Sending Routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINSendMsg(Bool master, Bool send_data, struct message msg)
{
unsigned char check_sum, parity_id, i;
rx.error = 0;
if(master)
{
// Sends break feald
if(!LINSendChar(TRUE, 0x00))
return(FALSE);
// Check break sending
if(!LINCheckSend(_BREAK, 0x00))
return(FALSE);
// Sends synch feald
if(!LINSendChar(FALSE, 0x55))
return(FALSE);
// Checks synch sending
if(!LINCheckSend(SYNCH, 0x55))
return(FALSE);
parity_id=LINCalcParity(msg.identifier);
// Sends protected identifier feald
if(!LINSendChar(FALSE, parity_id))
return(FALSE);
// Checks protected identifier sending
if(!LINCheckSend(PROTECTED_IDENTIFIER, parity_id))
return(FALSE);
}
if(send_data)
{
for(i=0; i < MAX_DATA; i++)
{
// Sends data field
if(!LINSendChar(FALSE, msg.data_field[i]))
return(FALSE);
// Checks data sending
if(!LINCheckSend(DATA_0+i, msg.data_field[i]))
return(FALSE);
}
check_sum = LINCalcChecksum(msg.data_field);
// Sends checksum field
if(!LINSendChar(FALSE, check_sum))
return(FALSE);
// Checks checksum sending
if(!LINCheckSend(CHECKSUM, check_sum))
return(FALSE);
rx.state = IDLE;
}
return(TRUE);
}
/////////////////////////////////////////////////////////////////////////////////////////
// LINCheckMsg
// --------------------------------------------------------------------------------------
// LIN State Check Routine
/////////////////////////////////////////////////////////////////////////////////////////
enum lin_state LINCheckState(void)
{
return rx.state;
}
/////////////////////////////////////////////////////////////////////////////////////////
// SCI1_RX
// --------------------------------------------------------------------------------------
// SCI1 receive interrupt service routine
/////////////////////////////////////////////////////////////////////////////////////////
interrupt void SCI1_RX(void)
{
if(!LINGetChar())
{
rx.error = 1;
rx.state = IDLE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -