📄 lin_low_level.c
字号:
{
/* Determine the number of bytes to be sent. */
LIN_tx_send_length = LIN_id_table[LIN_frame_name].data_length + (unsigned char)3;
/* Load the signal data for this frame into the "LIN_data[]" array. */
lin_make_frame_data(LIN_frame_name);
/* Make the checksum for this data. */
temp_sum = LIN_sum_code;
for (i = (LIN_tx_send_length - (unsigned char)4); i >= 0; i--)
{
temp_sum += LIN_data[i];
}
/* Add in the carry bits. */
temp_sum = (unsigned int)((unsigned char)(temp_sum >> 8) + (unsigned char)(temp_sum & 0x00FF));
/* And once more, in case the first add of carry bits produced a carry. */
temp_sum += (temp_sum >> 8);
/* Load the (inverted) checksum into the last (used) byte of the "LIN_data[]" array. */
LIN_data[LIN_tx_send_length - 3] = ~(unsigned char)(temp_sum);
/* Shift the data out by two bytes to make room for the sync byte and the
* frame ID byte. */
for (i = (LIN_tx_send_length - (unsigned char)3); i >= 0; i--)
{
LIN_data[(i + 2)] = LIN_data[i];
}
}
else
{
/* The Master node will not publish the data for this frame. Set
* "LIN_tx_send_length" to 2: sync byte and the ID byte. */
LIN_tx_send_length = 2;
}
}
else
{
/* This is an Event Triggered frame and the Master node never publishes the
* data for an Event Triggered frame. Set "LIN_tx_send_length" to 2: sync
* byte and the ID byte. */
LIN_tx_send_length = 2;
}
/* For all frames, regardless of type, set byte 0 of the "LIN_data[]" array
* to 0x55 (sync byte) and byte 1 to the frame ID byte. Then fall through
* to "lin_send_response()" to send the byte. */
LIN_data[0] = 0x55;
LIN_data[1] = LIN_ident_PB;
}
#else
/* Slave node processing. Load the signal data for this frame into the
* "LIN_data[]" array. */
lin_make_frame_data(LIN_frame_name);
/* Make the checksum for this data. */
temp_sum = LIN_sum_code;
for (i = (LIN_tx_send_length - (unsigned char)2); i >= 0; i--)
{
temp_sum += LIN_data[i];
}
/* Add in the carry bits. */
temp_sum = (unsigned int)((unsigned char)(temp_sum >> 8) + (unsigned char)(temp_sum & 0x00FF));
/* And once more, in case the first add of carry bits produced a carry. */
temp_sum += (temp_sum >> 8);
/* Load the (inverted) checksum into the last (used) byte of the "LIN_data[]" array. */
LIN_data[LIN_tx_send_length - 1] = ~(unsigned char)(temp_sum);
#endif /* Master node. */
/* Set the bus state to the DATA_SEND state and send the first byte. */
lin_change_bus_status(DATA_SEND_STATE);
lin_send_response();
return;
}
/**********************************************************************
* Function Name: lin_read_serial_data()
* Description: Reads one byte of data from the LIN serial port.
* Parameters: *p - pointer to the location to store the read byte.
* Returns: 0 on success; -1 on failure.
* Ext. References: None.
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
unsigned char lin_read_serial_data(unsigned char *p)
{
unsigned char ret_status;
unsigned int read_word;
unsigned char error_bits;
unsigned char wait_cnt;
ret_status = 1; /* Set failure return status. */
wait_cnt = LIN_READBACK_FAIL_SAFE;
/* Wait (possibly needed only for readback of transmit data) until the receive
* data ready flag is set or for 50us, whichever is less. The "fail safe" timeout
* is needed only for the case that something has gone wrong on the LIN bus to
* cause the readback reception of a transmitted byte not to complete. For true
* receive data, this function is only called after the receive data ready flag
* has already been set. */
while (LIN_UART_RBUFF_FLG == 0 && wait_cnt > 0)
{
wait_cnt--;
}
/* Read the received data word and store the error bits in the high byte. */
read_word = LIN_UART_RDAT;
error_bits = (unsigned char)(read_word >> 8);
/* If an overrun error or framing error has occurred, clear all error
* flags and return failure. */
if ((LIN_UART_RCV_ERR_FLGS & LIN_RCV_ERRS) != 0x00)
{
/* If the LIN bus is in the DATA_RECEIVE state and an overrun error
* occurs, increment "LIN_RX_count" to make up for the "lost" byte, but
* not if "LIN_RX_count" is 0. If "LIN_RX_count" is 0, the first receive
* byte has not yet been processed and skipping over this "count" will
* cause "LIN_rx_receive_length" not to be set properly, which will
* create an even worse mess than being one count short at the end of a
* message frame. */
if ((LIN_bus_status == DATA_RECEIVE_STATE) && ((LIN_UART_RCV_ERR_FLGS & LIN_OVERRUN_ERR) != 0x00))
{
if (LIN_RX_count > 0)
{
LIN_RX_count++;
}
}
/* Maintain the detailed error counters if EXTENDED_ERROR_STATS is defined. */
#ifdef EXTENDED_ERROR_STATS
if (LIN_bus_status == DATA_SEND_STATE)
{
if ((LIN_UART_RCV_ERR_FLGS & LIN_OVERRUN_ERR) != 0x00)
{
LIN_xmt_overrun_err++;
}
if ((LIN_UART_RCV_ERR_FLGS & LIN_FRAME_ERR) != 0x00)
{
LIN_xmt_framing_err++;
}
}
else
{
/* This block of code picks up serial errors for all received data bytes,
* sync bytes and protected ID bytes. */
if ((LIN_UART_RCV_ERR_FLGS & LIN_OVERRUN_ERR) != 0x00)
{
LIN_rcv_overrun_err++;
}
if ((LIN_UART_RCV_ERR_FLGS & LIN_FRAME_ERR) != 0x00)
{
LIN_rcv_framing_err++;
}
}
#endif
/* If needed, clear the overrun error flag here by momentarily clearing
* the receive enable bit. The framing error flag (if set) was cleared
* by reading the receive data register. */
if ((LIN_UART_RCV_ERR_FLGS & LIN_OVERRUN_ERR) != 0x00)
{
LIN_UART_RCV_EN = 0;
_asm("NOP");
_asm("NOP");
LIN_UART_RCV_EN = 1;
}
}
else
{
*p = (unsigned char)read_word; /* Store the read data byte. */
ret_status = 0; /* Return success. */
}
return (ret_status);
}
/**********************************************************************
* Function Name: lin_make_frame_data()
* Description: Loads signal data into "LIN_data[]" to prepare a
* for publishing LIN data.
* Parameters: frame_name - LIN message frame ID number.
* Returns: Nothing.
* Ext. References: LIN_data[] - the LIN data byte array.
* Preemptible: Yes.
* Reentrant: No.
*********************************************************************/
void lin_make_frame_data(unsigned char frame_name)
{
int i, j;
unsigned char *p, *fstp, *dptr;
unsigned char max_sig;
union {
unsigned int d_int;
unsigned char d_byte[2];
} buf;
unsigned char set_byte, set_bit, signal_name, offset, signal_byte, signal_bit;
unsigned char start_byte;
#ifdef ENABLE_ODD_SIGNAL_WIDTHS /* Odd length signals allowed (signal size not evenly divisable by 8). */
/* Zero out "LIN_data[]" array before starting if odd length signals are allowed.
* "Loading" of the odd length signal data requires logical OR'ing, which in turn
* requires that "LIN_data[]" be zeroed out before starting. */
for (i = (LIN_MAX_RESPONSE_LENGTH + 1); i >= 0; i--)
{
LIN_data[i] = 0x00;
}
#endif
start_byte = 0;
#ifndef ENABLE_ODD_SIGNAL_WIDTHS /* Limits scalar signal data size to 8 or 16 bits. */
/* Save the number of signals in the frame. */
max_sig = LIN_id_table[frame_name].num_sigs;
/* Set the pointer to point to the first signal in the frame table. */
fstp = LIN_id_table[frame_name].data_address;
/* Loop through all of the signals associated with a LIN message frame ID. */
for (i = 0; i < max_sig; i++)
{
/* Get the index number of a signal. */
signal_name = *fstp++;
/* Determine the bit offset of the signal data in the LIN data buffer. */
offset = *fstp++;
/* Get the number of bytes in the signal value. */
signal_byte = LIN_signal_table[signal_name].signal_byte;
set_byte = offset / (unsigned char)8;
/* Set a pointer to the first data byte of the signal value. */
p = LIN_signal_table[signal_name].signal_address + 1;
/* Set a pointer to the (initial) destination byte in "LIN_data[]". */
dptr = (unsigned char *)&LIN_data[set_byte + start_byte];
/* Load the signal value into the LIN data buffer at the appropriate
* location. */
for (j = 0; j < signal_byte; j++)
{
*dptr++ = *p++;
}
}
#else /* Odd length signals allowed (signal size not evenly divisable by 8). */
/* Save the number of signals in the frame. */
max_sig = LIN_id_table[frame_name].num_sigs;
/* Set the pointer to point to the first signal in the frame table. */
fstp = LIN_id_table[frame_name].data_address;
/* Loop through all of the signals associated with a LIN message frame ID. */
for (i = 0; i < max_sig; i++)
{
/* Get the index number of a signal. */
signal_name = *fstp++;
/* Determine the bit offset of the signal data in the LIN data buffer. */
offset = *fstp++;
/* Get the number of bytes in the signal value - 1 or 2. */
signal_byte = LIN_signal_table[signal_name].signal_byte;
/* Get the number of bits in the signal value - 0 through 15. */
signal_bit = LIN_signal_table[signal_name].signal_bit;
/* "offset" is the number of bits (0 through 63) that lie "below" the
* LSB of this signal in the "LIN_data[]" array. "offset" must be
* divided up to produce "set_byte" number of bytes completely offset (0
* through 7) and "set_bit" number of bits offset in the last byte (also
* 0 through 7). */
set_byte = offset >> 3;
set_bit = offset & (unsigned char)0x07;
/* Set a pointer to the first data byte of the signal value. */
p = LIN_signal_table[signal_name].signal_address + 1;
/* Set a pointer to the (initial) destination byte in "LIN_data[]". */
dptr = (unsigned char *)&LIN_data[set_byte + start_byte];
/* If "signal_byte" is 1 or 2, the signal may be a scalar signal with a
* length of between 1 and 16 bits. A scalar signal may be packed into
* the "LIN_data[]" array starting at any given bit (0 to 63) within the
* array, but a scalar value may cross only a single byte boundary within
* the array. If "signal_byte" is 1 or 2, the signal may also be a byte
* array. However, a byte array may be stored only in byte locations
* within the "LIN_data[]" array, meaning that the starting bit must
* always be bit 0 of some byte. If "signal_byte" is 3 or greater (max
* of 8), the signal is a byte array. */
if (signal_byte < 3)
{
/* Load the signal data into "buf.d_int" to allow it to be bit shifted as
* a complete value. */
if (signal_bit <= 8)
{
buf.d_int = 0;
}
else
{
buf.d_byte[1] = *(p + 1);
}
buf.d_byte[0] = *p;
/* Shift the signal value toward the MSbit by "set_bit" number of positions.
* A LIN scalar value may be 1 to 16 bits in length, but the value may
* cross only a single byte boundary. This means the the 16-bit "buf.d_int"
* will always be able to hold any (valid) combination of signal length and
* bit shifts without losing any bits. */
buf.d_int <<= set_bit;
/* Load the signal value into the LIN data buffer at the appropriate
* location. Both bytes are always OR'd into "LIN_data[]" since even a signal
* with fewer than 8 bits may now have some of those bits in the MSByte. It
* is faster just to write the MSByte in every case rather than to figure out
* if it really must be written or not. Since the bits are OR'd, writing a
* '0x00' byte doesn't change anything anyway. */
*dptr++ |= buf.d_byte[0];
*dptr |= buf.d_byte[1];
}
else
{
/* This is a byte array. Load the signal value into the LIN data buffer at
* the appropriate locations. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -