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

📄 lin_low_level.c

📁 针对日本瑞莎单片机r8c/23 开发的LIN网络通讯程序包括主节点和从节点
💻 C
📖 第 1 页 / 共 5 页
字号:
         LIN_CONTROL_REG = 0x80;
      #endif
   #endif
   return;
}

/**********************************************************************
 *    Function Name: lin_set_ifc_status()
 *      Description: Updates the LIN interface status word.
 *       Parameters: ident - LIN message ID
 *                   status - new status value
 *          Returns: Nothing.
 *  Ext. References: LIN_ifc_status
 *      Preemptible: Yes.
 *        Reentrant: Yes.
 *********************************************************************/
void lin_set_ifc_status(unsigned char ident, unsigned char status)
{
   /* If "ident" is not 0xFF and the existing ident byte of the status
    * word has already been set, set the overrun status bit.  */
   if ((ident != LIN_ID_NOTSET) && (LIN_ifc_status[1] != 0))
   {
      LIN_ifc_status[0] |= LIN_IFC_OVERRUN;
   }
   /* If "ident" is not 0xFF, set the ident byte of the status word
    * to "ident".  */
   if (ident != LIN_ID_NOTSET)
   {
      LIN_ifc_status[1] = ident;
   }
   /* OR the new status with the existing status.  */
   LIN_ifc_status[0] |= status;
   return;
}

#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
#ifdef USE_POWER_CONTROL   /* Implemented only if power control is used.  */
/**********************************************************************
 *    Function Name: lin_goto_sleep()
 *      Description: Send the LIN sleep command from a LIN Master node.
 *       Parameters: None.
 *          Returns: Nothing.
 *  Ext. References: LIN_ident_PB, LIN_data[], LIN_DIAG_mode.
 *      Preemptible: Yes.
 *        Reentrant: No.
 *********************************************************************/
void lin_goto_sleep(void)
{
   unsigned char i;

   /* Generate a LIN message header byte using ID 0x60 (Master Diagnostic Request
    * Frame).  The ID byte is written into the global variable "LIN_ident_PB".  */
   LIN_ident = 0x3C;
   LIN_ident_PB = lin_make_protected_identifier(0x3C);
   /* Load the sync byte into LIN message byte 0.  */
   LIN_data[0] = 0x55;
   /* Load the header byte into LIN message byte 1.  */
   LIN_data[1] = LIN_ident_PB;
   /* Copy the LIN "go_to_sleep" data (including checksum) into the LIN message
    * bytes 2 through 10.  */
   for (i = 0; i < 9; i++)
   {
      LIN_data[(i + 2)] = LIN_sleep_cmd[i];
   }
   LIN_DIAG_mode = 1;
   /* Send the LIN break to start the message frame.  */
   lin_send_break();
}
#endif   /* USE_POWER_CONTROL.  */
#endif   /* Master node.  */

/**********************************************************************
 *    Function Name: lin_change_node_status()
 *      Description: Configures the LIN node to operate in the requested
 *                   state.
 *       Parameters: status - the desired node state.
 *          Returns: Nothing.
 *  Ext. References: LIN_node_status
 *      Preemptible: Yes.
 *        Reentrant: Yes.
 *********************************************************************/
void lin_change_node_status(unsigned char status)
{
   LIN_node_status = status;
   BRK_TMR_RUN = 0;                    /* Stop the break timer.  */
   BRK_TMR_INT_CTL = 0x00;             /* Disable the break timer interrupt.  */
   BRK_TMR_INT_CFG &= BRK_INT_NONE;    /* Clear all break timer interrupt source enables.  */
   BRK_TMR_FLAGS |= BRK_CLR_ALL_FLGS;  /* Clear all break timer interrupt flags.  */
   switch (status)
   {
      case DISCONNECT:
         LIN_FUNCTION_ENABLE = 0;            /* Disable the LIN function block.  */
         #if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
            #ifdef DEDICATED_SCHEDULE_TIMER
               SCH_TMR_RUN = 0;                 /* Stop the LIN schedule timer.  */
               SCH_TMR_INT_CFG = SCH_INT_DIS;   /* Disable the schedule timer interrupt.  */
            #endif
            LIN_schedule_stop_flag = 1;         /* Halt Master schedule action.  */
         #endif
         LIN_UART_OP_MODE = LIN_UART_OP_OFF; /* Disable the serial port.  */
         LIN_UART_RX_INT_CTL = 0x00;         /* Disable the UART interrupts.  */
         LIN_UART_TX_INT_CTL = 0x00;
         API_AWAKE_FLG = 0;                  /* Clear LIN_AWAKE_FLG.  */
         break;

      case CONNECT:
         #if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
            /* This is a LIN Master node.  */
            #ifdef DEDICATED_SCHEDULE_TIMER
               SCH_TMR_RUN = 1;                    /* Start the LIN schedule timer.  */
               SCH_TMR_INT_CFG = SCH_INT_EN;       /* Enable the schedule timer interrupt.  */
            #endif
            LIN_schedule_stop_flag = 0;            /* Start Master schedule action.  */
         #else
            /* This is a LIN Slave node.  */
            /* Reload the break timer count.  */
            BRK_TMR_PRECNT_REG = LIN_break_prescale;
            BRK_TMR_CNT_REG = LIN_break_count;
            /* Configure the LIN function mode and interrupt sources.  The Break interrupt
             * is always 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
            BRK_TMR_INT_CTL = BRK_TMR_INT_PRIO;    /* Enable the break timer interrupt.  */
            BRK_TMR_RUN  = 1;                      /* Start the break timer.  */
            BRK_TMR_ARMED = 1;                     /* Enable break pulse detection mode.  */
         #endif
         LIN_UART_OP_MODE = LIN_UART_OP_OFF; /* Disable the serial port.  */
         LIN_UART_RX_INT_CTL = 0x00;
         LIN_UART_TX_INT_CTL = 0x00;
         API_AWAKE_FLG = 1;                  /* Set LIN_AWAKE_FLG.  */
         break;

      #ifdef USE_POWER_CONTROL
         case SLEEP_STATE:
            #if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
               /* Reconfigure the break timer mode control bits to detect a wake-up pulse
                * according to the hardware being used.  */
               BRK_TMR_MODE_REG = BRK_TMR_SLV_MODE;
               BRK_TMR_IO_REG = BRK_TMR_SLV_IO;
            #endif
            /* Reload the break timer count to detect a wake-up pulse.  */
            BRK_TMR_PRECNT_REG = LIN_wake_up_period;
            BRK_TMR_CNT_REG = 14;
            lin_change_bus_status(QUIET_STATE);    /* Place the bus in the QUIET state.  */
            /* Configure the LIN function mode and interrupt sources.  Only the Break
             * interrupt is enabled.  */
            BRK_TMR_INT_CFG = 0xA2;
            BRK_TMR_INT_CTL = BRK_TMR_INT_PRIO;    /* Enable the break timer interrupt.  */
            BRK_TMR_RUN  = 1;                      /* Start the break timer.  */
            BRK_TMR_ARMED = 1;                     /* Enable break pulse detection mode.  */
            LIN_UART_OP_MODE = LIN_UART_OP_OFF;    /* Disable the serial port.  */
            LIN_UART_RX_INT_CTL = 0x00;
            LIN_UART_TX_INT_CTL = 0x00;
            API_AWAKE_FLG = 0;                     /* Clear LIN_AWAKE_FLG.  */
            /* Set the interface status to sleep mode.  */
            lin_set_ifc_status(LIN_ID_NOTSET, LIN_IFC_GOTOSLEEP) ;
            break;

         case WAKE_UP_STATE:
            #if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
               /* This is a Master node.  Disable the Break timer.  */
               /* Reconfigure the break timer mode control bits to Master mode.  */
               BRK_TMR_MODE_REG = BRK_TMR_MST_MODE;
               BRK_TMR_IO_REG = BRK_TMR_MST_IO;
               /* Reload the break timer count.  */
               BRK_TMR_PRECNT_REG = LIN_break_prescale;
               BRK_TMR_CNT_REG = LIN_break_count;
               #ifdef DEDICATED_SCHEDULE_TIMER
                  SCH_TMR_RUN = 1;                    /* Restart the LIN schedule timer.  */
               #endif
               LIN_schedule_stop_flag = 0;            /* Start Master schedule action.  */
            #else
               /* This is a Slave node.  */
               /* Clear "LIN_sleep_timer" to keep the node from going right back to sleep.  */
               LIN_sleep_timer = 0;
               /* Reload the break timer count.  */
               BRK_TMR_PRECNT_REG = LIN_break_prescale;
               BRK_TMR_CNT_REG = LIN_break_count;
               /* Configure the LIN function mode and interrupt sources.  The Break interrupt
                * is always 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
               BRK_TMR_INT_CTL = BRK_TMR_INT_PRIO;    /* Enable the break timer interrupt.  */
               BRK_TMR_RUN  = 1;                      /* Start the break timer.  */
               BRK_TMR_ARMED = 1;                     /* Enable break pulse detection mode.  */
            #endif
            lin_change_bus_status(QUIET_STATE);    /* Place the bus in the QUIET state.  */
            API_AWAKE_FLG = 1; /* Set LIN_AWAKE_FLG.  */
            break ;
      #endif   /* USE_POWER_CONTROL.  */
   }
   return;
}

/**********************************************************************
 *    Function Name: lin_change_bus_status()
 *      Description: Set the LIN bus status to the desired state and
 *                   configure the serial port accordingly.
 *       Parameters: status - desired bus state.
 *          Returns: Nothing.
 *  Ext. References: LIN_bus_state
 *      Preemptible: Yes.
 *        Reentrant: No.
 *********************************************************************/
void lin_change_bus_status(unsigned char status)
{
   /* Set "LIN_bus_status" to the new bus state.  */
   LIN_bus_status = status;

   #if ((LIN_MASTER_NODE != LIN_MY_NODE_NAME) && (defined USE_POWER_CONTROL))
      /* Clear "LIN_sleep_timer" on every bus state change, but do it here
       * most specifically so the timer is cleared even before the Break
       * timer ISR exits.  */
      LIN_sleep_timer = 0;
   #endif   /* Slave node and USE_POWER_CONTROL is defined.  */
   /* The original API code (written for the H8/Tiny family) cleared the serial
    * port flags here, which was possible to do since the serial port flags can
    * be cleared on the H8/Tiny without affecting UART operation.  For the M16C
    * and R8C families, two of the serial port flags used (receive complete and
    * framing error) are cleared by reading the receive data register.  The
    * overrun error flag is cleared only by clearing the receive enable bit
    * (clears framing error as well) or by de-allocating the UART (which clears
    * all three).  Any of these actions could potentially cause problems if
    * performed here unnecessarily.  Since the receive enable bit is cleared in
    * several of the bus states, the error flags will be forcefully cleared
    * when entering these states.  It has been decided not to perform any
    * other "special" operations at this point to clear serial port flags.  */
   /* The UART transmit function remains enabled literally continuously
    * to insure that the UART will begin transmitting immediately after
    * a byte is written to the UART transmit buffer.  Turning on the 'TE'
    * bit in the UART mode register only when needed was causing a 500us
    * to 700us "pause" between the end of the break period and the sync
    * byte (Master) and a similar "pause" between the ID byte and the first
    * data byte (Slave) on the H8/Tiny family of processors.  Leaving the
    * 'TE' bit always enabled eliminated these "pauses" and allowed the LIN
    * signal to be generated as specified.  This same practice (leaving the
    * 'TE' bit set under most circumstances) was followed for the M16C and
    * R8C families of processors, without really knowing if it is needed.  */
   switch (status) {
      case QUIET_STATE:
         LIN_TX_count = 0;
         LIN_RX_count = 0;
         /* Disable the bus collision interrupt and clear all flags.  */
         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 and the Sync interrupt is enabled in the SYNC_AUTO_MODE.  */
            #ifdef SYNC_AUTO_MODE
               BRK_TMR_INT_CFG = 0xB3;
            #else
               BRK_TMR_INT_CFG = 0x92;
            #endif
         #endif
         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 ;

      case SYNC_RECEIVE_STATE:
         #ifdef SYNC_AUTO_MODE
            /* Turn off the serial port while the sync byte width measurement is
             * being made.  */
            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.  */
         #else
            /* Enable the serial port to "read" the sync byte.  */
            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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -