📄 lin_low_level.c
字号:
* Transmit enabled. */
#endif
break ;
case IDENTIFY_RECEIVE_STATE:
LIN_DIAG_mode = 0; /* Insure the diagnostic mode is off. */
/* Reload the break timer count. */
BRK_TMR_PRECNT_REG = LIN_break_prescale;
BRK_TMR_CNT_REG = LIN_break_count;
LIN_UART_OP_MODE = LIN_UART_OP_RCV; /* Configure the serial port. */
LIN_UART_RX_INT_CTL = LIN_UART_RX_INT_PRIO;
LIN_UART_TX_INT_CTL = 0x00;
/* Receive interrupt enabled
* Receive enabled
* Transmit end interrupt disabled
* Transmit enabled. */
break ;
case DATA_RECEIVE_STATE:
LIN_RX_count = 0; /* Initialize the receive byte counter. */
/* Disable the bus collision interrupt and clear the flag. */
BRK_TMR_FLAGS |= BRK_CLR_ALL_FLGS;
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
BRK_TMR_INT_CFG = 0xC0; /* Break detect not enabled for Master node. */
#else
/* Configure the LIN function mode and interrupt sources. The Break interrupt
* is always enabled, the Bus Collision interrupt is never enabled and the Sync
* interrupt is enabled in the SYNC_AUTO_MODE. */
#ifdef SYNC_AUTO_MODE
BRK_TMR_INT_CFG = 0xA3;
#else
BRK_TMR_INT_CFG = 0x82;
#endif
#endif
LIN_UART_OP_MODE = LIN_UART_OP_RCV; /* Configure the serial port. */
LIN_UART_RX_INT_CTL = LIN_UART_RX_INT_PRIO;
LIN_UART_TX_INT_CTL = 0x00;
/* Receive interrupt enabled
* Receive enabled
* Transmit end interrupt disabled
* Transmit enabled. */
break ;
case DATA_SEND_STATE:
LIN_TX_count = 0; /* Initialize the transmit byte counter. */
/* Clear all break flags and enable the bus collision interrupt. */
BRK_TMR_FLAGS |= BRK_CLR_ALL_FLGS;
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
BRK_TMR_INT_CFG = 0xC4; /* Break detect not enabled for Master node. */
#else
/* Configure the LIN function mode and interrupt sources. The Break interrupt
* is always enabled, the Bus Collision interrupt is always enabled and the Sync
* interrupt is enabled in the SYNC_AUTO_MODE. */
#ifdef SYNC_AUTO_MODE
BRK_TMR_INT_CFG = 0xA7;
#else
BRK_TMR_INT_CFG = 0x86;
#endif
#endif
/* Initialize the transmit check error flag. */
LIN_TX_check_error = 0;
LIN_UART_OP_MODE = LIN_UART_OP_XMT; /* Configure the serial port. */
LIN_UART_RX_INT_CTL = 0x00;
LIN_UART_TX_INT_CTL = LIN_UART_TX_INT_PRIO;
/* Receive interrupt disabled
* Receive enabled
* Transmit end interrupt enabled
* Transmit enabled. */
break ;
#ifdef USE_POWER_CONTROL
case WAKEUP_SEND_STATE:
LIN_UART_OP_MODE = LIN_UART_OP_IDLE; /* Configure the serial port. */
LIN_UART_RX_INT_CTL = 0x00;
LIN_UART_TX_INT_CTL = 0x00;
/* Receive interrupt disabled
* Receive disabled
* Transmit end interrupt disabled
* Transmit enabled. */
break;
#endif /* USE_POWER_CONTROL. */
}
return;
}
/**********************************************************************
* Function Name: lin_init_checksum()
* Description: Initializes checksum value to 0 for a "classic"
* checksum or to the LIN message ident byte for an
* enhanced checksum.
* Parameters: check_sum_type - 0 = classic; 1 = enhanced.
* Returns: Nothing.
* Ext. References: LIN_ident_PB, LIN_sum_code
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
void lin_init_check_sum(unsigned char check_sum_type)
{
/* If "check_sum_type" is LIN_ENHANCED (1), initialize "LIN_sum_code"
* to the current value of "LIN_ident_PB". */
if (check_sum_type == LIN_ENHANCED)
{
LIN_sum_code = LIN_ident_PB;
}
else
/* Otherwise (0 assumed), clear "LIN_sum_code". */
{
LIN_sum_code = 0;
}
return;
}
/**********************************************************************
* Function Name: lin_make_check_sum()
* Description: Adds one data byte to the 1's compliment checksum.
* Parameters: data - data byte.
* Returns: Nothing.
* Ext. References: LIN_sum_code
* Preemptible: Yes.
* Reentrant: No.
*********************************************************************/
void lin_make_check_sum(unsigned char data)
{
int i;
union {
unsigned int d_int ;
unsigned char d_byte[2];
} buf;
buf.d_int = 0; /* Initialize the buffer. */
buf.d_byte[0] = LIN_sum_code; /* Load the current checksum. */
buf.d_int += (unsigned int)data; /* Add in the data byte. */
/* If an 8-bit overflow occurs, subtract 255. This is the equivalent of
* adding 1 to the 8-bit sum, which is an 8-bit 1's compliment add. */
if (buf.d_int >= 256)
{
buf.d_int -= 255;
}
LIN_sum_code = buf.d_byte[0]; /* Save the new checksum. */
return;
}
/**********************************************************************
* Function Name: lin_make_protected_identifier()
* Description: Create a LIN Protected ID by setting the two parity
* bits as appropriate for the frame ID.
* Parameters: id_data - the LIN message frame ID.
* Returns: The Protected ID.
* Ext. References: None.
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
unsigned char lin_make_protected_identifier(unsigned char id_data)
{
union {
unsigned char BYTE;
struct {
unsigned char D0:1;
unsigned char D1:1;
unsigned char D2:1;
unsigned char D3:1;
unsigned char D4:1;
unsigned char D5:1;
unsigned char P0:1;
unsigned char P1:1;
} BIT;
} BUF;
/* Load the desired message frame ID into the LSBits of the buffer. */
BUF.BYTE = id_data & (unsigned char)0x3F;
/* Set the two parity bits. */
BUF.BIT.P1 = ~(BUF.BIT.D1 ^ BUF.BIT.D3 ^ BUF.BIT.D4 ^ BUF.BIT.D5);
BUF.BIT.P0 = BUF.BIT.D0 ^ BUF.BIT.D1 ^ BUF.BIT.D2 ^ BUF.BIT.D4;
return (BUF.BYTE);
}
/**********************************************************************
* Function Name: lin_reset_signal_update_flg()
* Description: Clear all signal status flags associated with a frame
* ID to indicate that the signals have not been updated.
* Parameters: frame_name - index number of the frame ID.
* Returns: Nothing.
* Ext. References: LIN_signal_table (indirectly).
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
void lin_reset_signal_update_flg(unsigned char frame_name)
{
int i;
unsigned char signal_name;
/* Loop through all signals associated with a frame ID number and clear
* the signal state flag for all signals. */
for (i = 0; i < LIN_id_table[frame_name].num_sigs; i++)
{
/* Determine the index number of the signal. */
signal_name = *(LIN_id_table[frame_name].data_address + (i * 2));
/* Clear the status flag for this signal to indicate that it has not
* been updated. */
*LIN_signal_table[signal_name].signal_address = 0x00;
}
return;
}
/* The following function is included only for Master nodes. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
/**********************************************************************
* Function Name: lin_send_break()
* Description: Sends the LIN Break pulse.
* Parameters: break_period - the length of the break in bits.
* Returns: Nothing.
* Ext. References: None.
* Preemptible: Yes.
* Reentrant: No.
*********************************************************************/
void lin_send_break(void)
{
/* Initialize the break timer for the Master break mode. */
BRK_TMR_FLAGS |= BRK_CLR_ALL_FLGS;
BRK_TMR_MODE_REG = BRK_TMR_MST_MODE;
BRK_TMR_PRECNT_REG = LIN_break_prescale;
BRK_TMR_CNT_REG = LIN_break_count;
BRK_INT_BREAK = 1; /* Configure the break detect interrupt. */
BRK_TMR_INT_CTL = BRK_TMR_INT_PRIO; /* Enable the break timer interrupt. */
BRK_TMR_RUN = 1; /* Start the LIN break timer. */
return;
}
#endif /* Master node. */
/**********************************************************************
* Function Name: lin_send_response()
* Description: Outputs the data byte from the "LIN_data[]" that is
* indicated by the current value of "LIN_TX_count".
* Parameters: None.
* Returns: Nothing.
* Ext. References: LIN_TX_count - index to the next byte to be sent.
* Preemptible: Yes.
* Reentrant: No.
*********************************************************************/
void lin_send_response(void)
{
/* Make sure the transmit data register is empty. */
while (LIN_UART_TBUFE_FLG == 0);
LIN_UART_TDAT = LIN_data[LIN_TX_count]; /* Output the data byte. */
LIN_TX_count++; /* Pre-increment to next byte to be sent. */
return;
}
/**********************************************************************
* Function Name: lin_first_send_data()
* Description: This function prepares the "LIN_data[]" structure
* for a transmit operation and causes the first byte
* to be sent.
* Parameters: None.
* Returns: Nothing.
* Ext. References: LIN_data[], LIN_ident, LIN_ident_PB, LIN_sum_code.
* Preemptible: Yes.
* Reentrant: No.
*********************************************************************/
void lin_first_send_data()
{
signed char i;
unsigned int temp_sum;
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
/* Master node processing. "LIN_DIAG_mode" is only set to 1 for Master devices
* when the command Go To Sleep is being sent. Otherwise (even for "normal"
* diagnostic frames), "LIN_DIAG_mode" is set to 0 and the frames are sent with
* "LIN_frame_type" set to UNCONDITIONAL or EVENT_TRIG. */
if (LIN_DIAG_mode == 1)
{
/* This is the Go To Sleep command. The command is already fully loaded into
* "LIN_data[]", so there is nothing to do but send it. */
LIN_tx_send_length = 11;
}
else
{
/* By the time this code executes, "LIN_frame_type" is set to
* Unconditional even if the original frame type was Sporadic.
* If the original frame type was Event Triggered, that remains, but
* the Master node never publishes Event Triggered data. */
if (LIN_frame_type == UNCONDITION_FRAME)
{
/* This is an Unconditional frame, which may have been a Sporadic
* frame originally. The Master node will always publish the data
* for a Sporadic frame but might not publish the data for an
* Unconditional frame. Check to see if the Master node is supposed
* to publish the data for the current frame. */
if (LIN_id_table[LIN_frame_name].node_name == LIN_MY_NODE_NAME)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -