📄 comm_lin.c
字号:
if(RCSTAbits.OERR == 1) // OVERRUN ERROR ?
COMM_LIN_OERR_FLAG = 1;
comm_data_2 = RCREG; // RETRIEVE DATA BYTE
#ifdef __DEBUG_LIN_AUX1
LIN_AUX1_PORT = 1;
#endif
//=======================================================
//--- BREAK ?!?
//=======================================================
Nop();
if((comm_data_2==0) && (COMM_LIN_FERR_FLAG))
{
COMM_LIN_FERR_FLAG = 0; // FERR EXPECTED ON BREAK
COMM_LIN_2_FLAG = 1; // FLAG INDICATES HARD ABAUD ERROR, ELSE, IGNORED
//--- POST EVENT MARKER
if(COMM_CB_LIN_EVENT_EN_BREAK_RX_FLAG)
comm_post_event(COMM_TAG_LIN_EVENT_BREAK_RX);
//--- SETUP OP FLAGS
COMM_LIN_SEQ_BRK_FLAG = 1;
COMM_LIN_SEQ_SYN_FLAG = 0;
COMM_LIN_SEQ_ID_FLAG = 0;
COMM_LIN_RX_SP_FLAG = 0;
COMM_LIN_TX_SP_FLAG = 0;
COMM_LIN_RX_SP_FLAG = 0;
//------------------------------------------
//--- AUTOBAUD ENABLED ?
//------------------------------------------
if((COMM_CB_LIN_AUTOBAUD_FLAG) && (COMM_LIN_ABAUD_DISABLE_FLAG==0))
{
//-----------------------------
//--- WAIT BREAK COMPLETE
// (ERR IF TIMEOUT)
//-----------------------------
timer3_set(COMM_LIN_WAIT_BREAK_T3);
COMM_LIN_ABERR_FLAG = 1; // PRESET ERROR FLAG
while(PIR2bits.TMR3IF == 0)
{
if(LIN_RX_PORT) // SYNC COMPLETE ?
{
COMM_LIN_ABERR_FLAG = 0; // SYNC COMPLETE, RESET ERROR FLAG !
break;
}
}
//---------------------------------------
//--- BREAK TERMINATED W/O TIMEOUT
// ENGAGE AUTOBAUD
//---------------------------------------
Nop();
if(COMM_LIN_ABERR_FLAG == 0)
{
//-----------------------------
//--- ENGAGE AUTOBAUD
//-----------------------------
BAUDCONbits.ABDEN = 1;
//-----------------------------
//--- WAIT ABAUD COMPLETE ...
// (ERR IF TIMEOUT)
//-----------------------------
COMM_LIN_COUNT = 0;
COMM_LIN_3_FLAG = 1;
COMM_LIN_ABERR_FLAG = 1;
timer3_set(COMM_LIN_WAIT_AB_T3);
while(PIR2bits.TMR3IF == 0)
{
if(COMM_LIN_3_FLAG == 0)
{
if(LIN_RX_PORT == 1)
{
if(COMM_LIN_COUNT == 5)
{
Nop();
BAUDCONbits.ABDEN = 0;
comm_data_2 = RCREG;
COMM_LIN_ABERR_FLAG = 0;
break;
}
COMM_LIN_3_FLAG = 1;
}
}
else
{
if(LIN_RX_PORT == 0)
{
COMM_LIN_3_FLAG = 0;
COMM_LIN_COUNT++;
}
}
}
//---
if(BAUDCONbits.ABDEN)
{
BAUDCONbits.ABDEN = 0; // SAFETY NET CLEAN UP ON TIMEOUT
COMM_LIN_2_FLAG = 1; // HARD ERROR
}
//-----------------------------
//--- AUTOBAUD OVERFLOW ?
//-----------------------------
if(BAUDCONbits.ABDOVF)
{
BAUDCONbits.ABDEN = 0;
BAUDCONbits.ABDOVF = 0;
COMM_LIN_ABERR_FLAG = 1;
}
//-----------------------------------------
//--- IF STATUS 'OK' SO FAR
// CHECK BAUD 'CHANGE' TO BE WITHIN LIMITS
// BAUD_CODE LIMITS: +/-12.5%
// CORRESPONDS TO BAUD: +14%/-11%
// OPTION:
// BAUD_CODE LIMITS: +/-25.0%
// CORRESPONDS TO BAUD: +33%/-20%
//-----------------------------------------
if(COMM_LIN_ABERR_FLAG == 0)
{
comm_macro_count_1_W.lo = SPBRG;
comm_macro_count_1_W.hi = SPBRGH;
comm_macro_count_2_W.lo = COMM_CB_LIN_BRG_LO_REG;
comm_macro_count_2_W.hi = COMM_CB_LIN_BRG_HI_REG;
if(comm_macro_count_1_W._w > comm_macro_count_2_W._w)
comm_macro_count_1_W._w = comm_macro_count_1_W._w - comm_macro_count_2_W._w;
else
comm_macro_count_1_W._w = comm_macro_count_2_W._w - comm_macro_count_1_W._w;
comm_macro_count_2_W._w >>= 3;
if(comm_macro_count_1_W._w > comm_macro_count_2_W._w)
COMM_LIN_ABERR_FLAG = 1;
COMM_LIN_2_FLAG = 0;
}
} //--- END: BREAK OK
//----------------------------------------------------
//--- IF AUTOBAUD ERROR, RE-LOAD DEFAULT BAUD
//----------------------------------------------------
if(COMM_LIN_ABERR_FLAG)
{
SPBRG = COMM_CB_LIN_BRG_LO_REG;
SPBRGH = COMM_CB_LIN_BRG_HI_REG;
if(COMM_LIN_2_FLAG == 0)
COMM_LIN_ABERR_FLAG = 0;
}
else
{
COMM_LIN_SEQ_SYN_FLAG = 1;
}
if(COMM_CB_LIN_EVENT_EN_AUTOBAUD_FLAG)
comm_post_event_2b(COMM_TAG_LIN_EVENT_AUTOBAUD, SPBRG, SPBRGH);
} //--- END AUTOBAUD
} //--- END BREAK DETECTION
//=======================================================
//--- DATA
//=======================================================
else
{
Nop();
COMM_LIN_ABAUD_DISABLE_FLAG = 0;
//---
COMM_LIN_DATA_FLAG = 1;
//--------------------------------
//--- EXPECTING 'SYNC' BYTE ?
//--------------------------------
if(not COMM_LIN_SEQ_SYN_FLAG)
{
//if(comm_data_2 == 0x55)
COMM_LIN_SEQ_SYN_FLAG = 1;
} //--- END 'SYNC' BYTE
//--------------------------------
//--- EXPECTING 'DATA' BYTE !
//--------------------------------
else
{
//------------------------------------------
//--- POST 'DATA RX' EVENT TAG(S)
//------------------------------------------
comm_post_event_1b(COMM_TAG_GEN_DATA, comm_data_2);
if(COMM_CB_LIN_EVENT_EN_DATA_RX_FLAG)
comm_post_event_1b(COMM_TAG_LIN_EVENT_BYTE_RX, comm_data_2);
//-----------------------------
//--- DATA: 'FRAME ID' ?
//-----------------------------
if(not COMM_LIN_SEQ_ID_FLAG)
{
COMM_LIN_SEQ_ID_FLAG = 1;
//--------------------------
//--- SLAVE MODE ?
//--------------------------
COMM_LIN_TX_SP_FLAG = 0;
COMM_LIN_RX_SP_FLAG = 0;
if(COMM_CB_LIN_SLAVE_FLAG)
{
if(comm_lin_parity(comm_data_2) != comm_data_2)
{
if(COMM_CB_LIN_EVENT_EN_IDPARITY_ERR_FLAG)
{
comm_post_event_1b(COMM_TAG_LIN_EVENT_IDPARITY_ERR, \
comm_data_2);
}
}
if(comm_lin_sp_iddef_search(comm_data_2))
{
//--- INIT CHECKSUM
COMM_LIN_SP_CHECKSUM = 0;
if((COMM_LIN_SP_IDDEF_ENHANCED_CS_FLAG) && (COMM_LIN_SP_ID<0x3C))
COMM_LIN_SP_CHECKSUM = comm_data_2;
if(COMM_LIN_SP_IDDEF_PUBLISH_FLAG)
{
COMM_LIN_TX_SP_FLAG = 1;
comm_lin_tx_isr();
}
else
{
COMM_LIN_RX_SP_FLAG = 1;
}
} //--- END: SEARCH SLAVE PROFILE FOR GIVEN ID
} //--- END: SLAVE MODE
} //--- END: EXPECTING FRAME ID
//--------------------------
//--- DATA:
//--------------------------
else
{
//--------------------------
//--- SLAVE MODE ?
//--------------------------
if(COMM_CB_LIN_SLAVE_FLAG)
{
if(COMM_LIN_RX_SP_FLAG)
{
if(COMM_LIN_SP_NBYTES)
{
COMM_LIN_SP_CHECKSUM += comm_data_2;
cbuf3_data[COMM_LIN_SP_INDEX_DATA] = comm_data_2;
COMM_LIN_SP_INDEX_DATA++;
COMM_LIN_SP_NBYTES--;
} //--- END: RX_SP ACTIVE, NBYTES!=0
else
{
if(not COMM_LIN_SP_IDDEF_CHKSUMDATA_FLAG)
{
//--- CHECKSUM GOOD
if(comm_data_2 == ~COMM_LIN_SP_CHECKSUM)
{
Nop();
}
//--- CHECKSUM BAD
else
{
if(COMM_CB_LIN_EVENT_EN_CHECKSUM_ERR_FLAG)
comm_post_event_1b(COMM_TAG_LIN_EVENT_CHECKSUM_ERR, COMM_LIN_SP_ID);
}
}
COMM_LIN_RX_SP_FLAG = 0;
} //--- END: RX_SP ACTIVE, NBYTES==0
} //--- END: RX_SP ACTIVE
} //--- END: RX DATA AFTER ID IN SLAVE MODE
} //--- END: RX DATA AFTER FRAME ID
} //--- END: RX DATA (NOT SYNC BYTE)
} //--- END: RX DATA (NOT AUTOBAUD or BREAK)
#ifdef __DEBUG_LIN_AUX1
LIN_AUX1_PORT = 0;
#endif
} //--- END: RX ISR (BREAK, AUTOBAUD or DATA
//==========================================================
//--- comm_lin_tx_isr()
//==========================================================
// USART TX interrupt service (in LIN mode)
// TX data has 2 sources (selected by bit flags)
// SLAVE & SCRIPT SERVICE ... SLAVE has priority
//==========================================================
void comm_lin_tx_isr(void)
{
TD_BYTE i;
//-----------------------------------
//--- SERVICE SCRIPT ?
//-----------------------------------
if (COMM_LIN_TX_SVC_FLAG)
{
comm_lin_svc();
}
//-----------------------------------
//--- SLAVE TX IN PROGRESS ?
//-----------------------------------
else if (COMM_LIN_TX_SP_FLAG)
{
if(COMM_LIN_SP_NBYTES)
{
i = cbuf3_data[COMM_LIN_SP_INDEX_DATA];
COMM_LIN_SP_CHECKSUM += i;
comm_lin_tx(i);
COMM_LIN_SP_INDEX_DATA++;
COMM_LIN_SP_NBYTES--;
}
else
{
if(not COMM_LIN_SP_IDDEF_CHKSUMDATA_FLAG)
comm_lin_tx(~COMM_LIN_SP_CHECKSUM);
COMM_LIN_TX_SP_FLAG = 0;
}
}
//-----------------------------------
//--- DONE !
//-----------------------------------
else
{
PIE1bits.TXIE = 0;
}
}
//==========================================================
//--- comm_lin_svc_tx()
//==========================================================
// transmit 'comm_data' byte
//==========================================================
void comm_lin_svc_tx(void)
{
COMM_LIN_TX_SVC_FLAG = 1;
comm_lin_tx(comm_data);
}
//==========================================================
//--- comm_lin_tx()
//==========================================================
// send/transmit data byte
// enable TX
// enable TX interrupt
//==========================================================
void comm_lin_tx(TD_BYTE data)
{
TXREG = data;
PIE1bits.TXIE = 1;
if(COMM_CB_LIN_EVENT_EN_DATA_TX_FLAG)
comm_post_event_1b(COMM_TAG_LIN_EVENT_BYTE_TX, comm_data);
}
//==========================================================
//--- comm_lin_parity()
//==========================================================
// computes 2 parity bits associated with LIN FRAME ID
// parity is computed on calling argument - 'data'
// the 'result' is returned as the function value
// where:
// result[7:7] = 1 ^ (data[5] ^ data[4] ^ data[3] ^ data[1])
// result[6:6] = 0 ^ (data[4] ^ data[2] ^ data[1] ^ data[0])
// result[5:0] = data[5:0]
//==========================================================
TD_BYTE comm_lin_parity(TD_BYTE data)
{
TD_BYTE mask;
data &= 0x3F;
mask = data & 0x17;
if((mask==0x01) || (mask==0x02) || (mask==0x04) || (mask==0x07) || \
(mask==0x10) || (mask==0x13) || (mask==0x15) || (mask==0x16))
data |= 0x40;
mask = data & 0x3A;
if((mask==0x00) || (mask==0x0A) || (mask==0x12) || (mask==0x18) || \
(mask==0x22) || (mask==0x28) || (mask==0x30) || (mask==0x3A))
data |= 0x80;
return(data);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -