⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lin_low_level.c

📁 针对日本瑞莎单片机r8c/23 开发的LIN网络通讯程序包括主节点和从节点
💻 C
📖 第 1 页 / 共 5 页
字号:
            {
               /* 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 + -