📄 lin_api.c
字号:
/* This is a request for an API flag. Return the present setting of the flag. */
flg -= 252;
ret_val = LIN_flags[flg];
}
else
{
/* This is a request for a signal flag. */
ret_val = 0x00; /* Initialize the return value to 0. */
/* Return 1 if the signal status byte is greater than 0x00. */
if (*LIN_signal_table[flg].signal_address > 0x00)
{
ret_val = 0x01;
}
}
return (ret_val);
}
/**********************************************************************
* Function Name: l_flg_clr()
* Description: Clears a system flag or signal status byte.
* Parameters: flg - possible values:
* any valid signal name defined in "lin_dev.h"
* LIN_TX_END_FLG (252)
* LIN_RX_END_FLG (253)
* LIN_AWAKE_FLG (254)
* LIN_DIAG_RESP_FLG (255).
* Returns: Nothing.
* Ext. References: System flag referenced by "flg".
* Preemptible: Yes.
* Reentrant: Yes.
*
* Note: this function does not perform any limit checking to verify
* the signal name values in "flg". The user application programmer
* should take precautions to insure that invalid parameters cannot be
* passed. The best method to use is to reference all flags by name.
* In the case of signals, these are the names defined in "lin_dev.h".
* It is virtually guaranteed that these name definitions correspond
* directly with the values defined in "LIN_signal_table[]".
*********************************************************************/
void l_flg_clr(l_flag_handle flg)
{
/* If "flg" has the value 252, 253, 254 or 255, this request is to clear one of
* the API flags LIN TX_END_FLG, LIN_END_FLG, LIN_AWAKE_FLG or LIN_DIAG_RESP_FLG.
* Otherwise, the request is to clear one of the user signals defined in
* "LIN_signal_table[]". */
if (flg > 251)
{
/* This is a request for an API flag. Clear the flag. */
flg -= 252;
LIN_flags[flg] = 0;
}
else
{
/* This is a request for a signal flag. Clear the signal ststus byte. */
*LIN_signal_table[flg].signal_address = 0x00;
}
return;
}
/**********************************************************************
* Function Name: l_ifc_read_status()
* Description: Reads the LIN interface status word.
* Parameters: ifc_name - index number of the LIN interface - only
* 0 is allowed.
* Returns: Returns the status value.
* Ext. References: LIN_ifc_status[].
* Preemptible: No.
* Reentrant: No.
*
* Note: This routine assumes that each node implements a single LIN
* interface, defined as interface 0 in "lin_dev.h" (the value of "LIN"
* is set to 0 by default). The API software should be modified to
* allow multiple LIN interfaces to be implemented.
*********************************************************************/
l_u16 l_ifc_read_status(l_ifc_handle ifc_name)
{
unsigned char flag_state;
union {
unsigned int d_int;
unsigned char d_byte[2];
} buf;
/* Clear the return value for the case that "ifc_name" is not LIN. */
buf.d_int = 0x0000;
/* Do nothing if the specified interface is not interface 0. */
if (ifc_name == LIN)
{
flag_state = l_sys_irq_disable(); /* Disable the global interrupt. */
/* Read the current value of "LIN_ifc_status" into the buffer. */
buf.d_byte[0] = LIN_ifc_status[0];
buf.d_byte[1] = LIN_ifc_status[1];
/* Clear "LIN_ifc_status". */
LIN_ifc_status[0] = 0;
LIN_ifc_status[1] = 0;
l_sys_irq_restore(flag_state); /* Restore the global interrupt. */
}
return (buf.d_int); /* Return the state of "LIN_ifc_status" prior to being cleared. */
}
/* This function is implemented only for LIN Master nodes. LIN Slave nodes
* are commanded into the sleep mode when this command is received and they
* are supposed to go to sleep automatically after 4 seconds of bus silence. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
#ifdef USE_POWER_CONTROL /* Implemented only if power control is used. */
/**********************************************************************
* Function Name: l_ifc_goto_sleep()
* Description: Send the LIN sleep command from a LIN Master node
* and then put the Master node in the SLEEP state.
* Parameters: ifc_name - index number of the LIN interface - only
* 0 is allowed.
* Returns: Nothing.
* Ext. References: LIN_schedule_stop_flag.
* Preemptible: Yes.
* Reentrant: No.
*
* Note: This routine assumes that each node implements a single LIN
* interface, defined as interface 0 in "lin_dev.h" (the value of "LIN"
* is set to 0 by default). The API software should be modified to
* allow multiple LIN interfaces to be implemented.
*********************************************************************/
void l_ifc_goto_sleep(l_ifc_handle ifc_name)
{
/* Do nothing if the specified interface is not interface 0. */
if (ifc_name == LIN)
{
/* Set the "LIN_schedule_stop_flag" to 2. When the current frame slot
* has expired, the LIN Go-To-Sleep message will be sent and then the
* Master schedule actions will be stopped. */
LIN_schedule_stop_flag = 2;
#ifdef DEDICATED_SCHEDULE_TIMER
/* If the LIN device is using a dedicated schedule timer, and this call
* to the "l_ifc_goto_sleep()" function is being made because a previous
* attempt failed, it will be necessary to restart the schedule timer to
* allow the Go-To-Sleep message to repeat. If the timer is already
* running, the following command won't change anything anyway. */
SCH_TMR_RUN = 1; /* Restart the LIN schedule timer. */
#endif
}
}
#endif /* USE_POWER_CONTROL. */
#endif /* Master node. */
#ifdef USE_POWER_CONTROL /* Implemented only if power control is used. */
/**********************************************************************
* Function Name: l_ifc_wake_up()
* Description: Sends the wakeup signal on the LIN bus (logic 0 for
* 250us) and then takes the node out of the SLEEP state.
* Parameters: ifc_name - index number of the LIN interface - only
* 0 is allowed.
* Returns: Nothing.
* Ext. References: No direct external references.
* Preemptible: No.
* Reentrant: No.
*
* Note: This routine assumes that each node implements a single LIN
* interface, defined as interface 0 in "lin_dev.h" (the value of "LIN"
* is set to 0 by default). The API software should be modified to
* allow multiple LIN interfaces to be implemented.
*********************************************************************/
void l_ifc_wake_up(l_ifc_handle ifc_name)
{
unsigned char flag_state;
/* Do nothing if the specified interface is not interface 0. */
if (ifc_name == LIN)
{
if (LIN_bus_status == QUIET_STATE)
{
flag_state = l_sys_irq_disable(); /* Disable the global interrupt. */
lin_change_bus_status(WAKEUP_SEND_STATE); /* Prepare the LIN bus to transmit. */
/* Wait until the transmit data register is empty. */
while (LIN_UART_TBUFE_FLG == 0);
LIN_UART_TDAT = 0xF0; /* Output 0xF0, which forces the bus low for 5 bit periods. */
/* Wait until the byte has been sent. */
while (LIN_UART_TXEND_FLG == 0);
/* If the LIN interface is in the "sleep" state, bring it back up. */
if (LIN_node_status == SLEEP_STATE)
{
lin_change_node_status(WAKE_UP_STATE); /* Set the LIN interface into the "wakeup state". */
}
else
{
lin_change_bus_status(QUIET_STATE); /* Set the LIN bus to the inactive state. */
}
l_sys_irq_restore(flag_state); /* Restore the global interrupt. */
}
}
}
#endif /* USE_POWER_CONTROL. */
/* This function is implemented only for LIN Master nodes. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
/**********************************************************************
* Function Name: l_sch_set()
* Description: Configures the Master node to use a different
* schedule table.
* Parameters: ifc_name - index number of the LIN interface - only
* 0 is allowed.
* schedule - index number of the schedule table to use.
* entry - first entry in the new schedule table that
* should be used.
* Returns: Nothing.
* Ext. References: LIN_change_schedule, LIN_change_entry.
* Preemptible: Yes.
* Reentrant: No.
*
* Note: This routine assumes that each node implements a single LIN
* interface, defined as interface 0 in "lin_dev.h" (the value of "LIN"
* is set to 0 by default). The API software should be modified to
* allow multiple LIN interfaces to be implemented.
*********************************************************************/
void l_sch_set(l_ifc_handle ifc_name, l_schedule_handle schedule, l_u8 entry)
{
/* Do nothing if the specified interface is not interface 0. */
if (ifc_name == LIN)
{
/* An "entry" value of both 0 and 1 means "start at the beginning". Modify
* "entry" such that 1 is the minimum value actually used. */
if (entry == 0)
{
entry = 1;
}
/* Load the requested values into "LIN_change_schedule" and "LIN_change_entry"
* so they can be activated at the next opportunity. */
LIN_change_entry = entry;
LIN_change_schedule = schedule;
}
}
#endif /* Master node. */
/* This function is implemented only for LIN Master nodes. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
/**********************************************************************
* Function Name: l_sch_tick()
* Description: Sends the next message frame on the current schedule
* table. This function is called only from the ISR
* for the scheduler timer.
* Parameters: ifc_name - index number of the LIN interface - only
* 0 is allowed.
* Returns: Index number of entry just sent or 0 on error.
* Ext. References:
* Preemptible: No.
* Reentrant: No.
*
* Note: This routine assumes that each node implements a single LIN
* interface, defined as interface 0 in "lin_dev.h" (the value of "LIN"
* is set to 0 by default). The API software should be modified to
* allow multiple LIN interfaces to be implemented.
*********************************************************************/
l_u8 l_sch_tick(l_ifc_handle ifc_name)
{
unsigned char ret;
unsigned char relational_frame_name;
unsigned char signal_name;
unsigned char LIN_master_request_frame;
unsigned char *p;
unsigned char i;
unsigned char j;
/* If "LIN_CORE_TIME_ENABLE" is defined, LIN core time measurements are being made.
* Turn on the "LIN_CORE_TIME" output pin. */
#ifdef LIN_CORE_TIME_ENABLE
LIN_CORE_TIME = 1;
#endif
ret = 0; /* Initialize the return value in case the NULL schedule table is active. */
/* Do nothing if the specified interface is not interface 0. */
if (ifc_name == LIN)
{
#ifdef DEDICATED_SCHEDULE_TIMER
SCH_TMR_FLAG_REG &= SCH_CLR_FLG; /* Clear the schedule timer flag. */
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -