📄 lin_low_level.c
字号:
/******************************************************************************/
/* Renesas Technology America, Inc. Legal Disclaimer */
/******************************************************************************/
/* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY */
/* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR */
/* PURPOSE. */
/* */
/* BY USING THE SOFTWARE HEREIN, YOU (AND YOUR COMPANY) AGREE TO BE BOUND BY */
/* THE TERMS AND CONDITIONS OF RENESAS TECHNOLOGY AMERICA, INC.'S SOURCE CODE */
/* LICENSE AGREEMENT. PLEASE READ THIS AGREEMENT CAREFULLY. IF YOU (OR YOUR */
/* COMPANY) DO NOT AGREE TO ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT, */
/* DO NOT INSTALL OR USE THIS SOFTWARE AND ASSOCIATED DOCUMENTATION. */
/* */
/* Copyright (c) 2003, 2004, 2005 and 2006 Renesas Technology America, Inc. */
/******************************************************************************/
/**********************************************************************
Title : lin_low_level.c
Module Description : This file contains the low level LIN function
routines.
MCU Family : R8C
Author : Bob Chamberlain
Version : LIN API 2.0 Version 1.1
*********************************************************************/
/**********************************************************************
* Include header files
*********************************************************************/
#include "lin_api.h"
/**********************************************************************
* File level pragmas
*********************************************************************/
/**********************************************************************
* Constant and Macro Definitions using #define
*********************************************************************/
/**********************************************************************
* Enumerations, Structures and Typedefs
*********************************************************************/
/**********************************************************************
* Global and Const Variable Defining Definitions / Initializations
*********************************************************************/
unsigned char LIN_node_status = DISCONNECT;
unsigned char LIN_bus_status = QUIET_STATE;
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
int LIN_slot_time = 0;
unsigned char LIN_now_schedule = 0;
unsigned char LIN_now_entry = 0;
unsigned char LIN_change_schedule = 0xFF;
unsigned char LIN_change_entry = 0;
unsigned char LIN_retry_count;
unsigned char LIN_schedule_stop_flag = 1;
#endif /* Master node. */
unsigned char LIN_frame_error_flag;
unsigned char LIN_TX_check_error;
unsigned char LIN_frame_type = 0;
unsigned char LIN_frame_name;
unsigned char LIN_ident;
unsigned char LIN_ident_PB;
unsigned char LIN_data[LIN_MAX_RESPONSE_LENGTH + 4];
unsigned char LIN_flags[4] = {0x00, 0x00, 0x00, 0x00};
const unsigned int LIN_bit_masks[17] = {
0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
};
unsigned char LIN_sum_code;
unsigned char LIN_RX_count = 0;
unsigned char LIN_TX_count = 0;
unsigned char LIN_tx_send_length;
unsigned char LIN_rx_receive_length;
unsigned char LIN_ifc_status[2] = {0, 0};
unsigned char LIN_DIAG_mode;
#ifdef EXTENDED_ERROR_STATS
unsigned char LIN_xmt_overrun_err = 0;
unsigned char LIN_xmt_framing_err = 0;
unsigned char LIN_xmt_checksum_err = 0;
unsigned char LIN_xmt_readback_err = 0;
unsigned char LIN_rcv_overrun_err = 0;
unsigned char LIN_rcv_framing_err = 0;
unsigned char LIN_rcv_checksum_err = 0;
#endif
/* This is the complete Go To Sleep command, to include the valid checksum as
* the final byte. */
#if ((LIN_MASTER_NODE == LIN_MY_NODE_NAME) && (defined USE_POWER_CONTROL))
const unsigned char LIN_sleep_cmd[9] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
#endif
/* The following variables are required to implement the basic Node Configuration
* commands. */
#if ((LIN_MASTER_NODE == LIN_MY_NODE_NAME) && (defined BASIC_NODE_CONFIG))
unsigned char LIN_diag_xfr_state = 0;
unsigned char LIN_diag_xfr_status = 0;
unsigned char LIN_diag_read_by_id = 0;
unsigned char *LIN_diag_return_ptr;
#endif
/**********************************************************************
* Static Variables With File Level Scope
*********************************************************************/
/**********************************************************************
* ROM Const Variables With File Level Scope
*********************************************************************/
/**********************************************************************
* Function Prototypes for Private Functions with File Level Scope
*********************************************************************/
/**********************************************************************
* Function Definitions
*********************************************************************/
/* The break timer is initialized only for Slave nodes. */
#if (LIN_MASTER_NODE != LIN_MY_NODE_NAME)
/**********************************************************************
* Function Name: lin_init_timer()
* Description: Set up the LIN break timer.
* Parameters: None.
* Returns: Nothing.
* Ext. References: LIN_MASTER_NODE, LIN_break_count, LIN_break_prescale.
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
void lin_init_timer(void)
{
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. */
/* Initialize the break timer mode control bits according to the hardware
* being used. */
BRK_TMR_MODE_REG = BRK_TMR_SLV_MODE;
BRK_TMR_IO_REG = BRK_TMR_SLV_IO;
/* If AUTO_CALCULATION is defined, calculate the LIN break period based on the
* system clock frequency and the LIN Baud rate. */
#ifdef AUTO_CALCULATION
/* The following math calculations should be done by the preprocessor, since all
* of the values are defined constants. This may result in a rounding error, but
* it will be insignificantly small. */
LIN_break_prescale = (unsigned char)((((1000000 * LIN_MY_FREQUENCY) + H_DIVISOR) / DIVISOR) - 1);
LIN_break_count = (unsigned char)((11 * BIT_FACTOR) - 1);
#endif /* AUTO_CALCULATION. */
/* Set the break timer period. */
BRK_TMR_PRECNT_REG = LIN_break_prescale;
BRK_TMR_CNT_REG = LIN_break_count;
return;
}
#endif /* Slave node. */
/* The schedule timer is used only for Master nodes. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
/**********************************************************************
* Function Name: lin_init_schedule_timer()
* Description: Set up the LIN Master schedule tick timer.
* Parameters: None.
* Returns: Nothing.
* Ext. References: None.
* Preemptible: Yes.
* Reentrant: Yes.
*********************************************************************/
void lin_init_schedule_timer(void)
{
#ifdef DEDICATED_SCHEDULE_TIMER
SCH_TMR_INT_CFG = SCH_INT_DIS; /* Disable the schedule timer interrupt. */
SCH_TMR_RUN = 0; /* Stop the LIN schedule timer. */
/* Initialize the schedule timer mode control bits. */
SCH_TMR_MODE_REG = SCH_TMR_MODE;
SCH_TMR_IO_REG = SCH_TMR_IO_MODE;
/* Set the timer prescaler count to the value needed to produce 100us ticks
* from the prescaler. Then set the timer count to the number of 100us
* ticks needed to produce "LIN_TIME_BASE" millisecond ticks. */
SCH_TMR_PRECNT_REG = SCH_TMR_INIT_PRECNT;
SCH_TMR_CNT_REG = SCH_TMR_INIT_CNT;
#endif
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. */
/* Initialize the break timer mode control bits according to the hardware
* being used. */
BRK_TMR_MODE_REG = BRK_TMR_MST_MODE;
BRK_TMR_IO_REG = BRK_TMR_MST_IO;
/* If AUTO_CALCULATION is defined, calculate the LIN break period (used by
* "lin_send_break()") based on the system clock frequency and the LIN Baud rate. */
#ifdef AUTO_CALCULATION
/* The following math calculations should be done by the preprocessor, since all
* of the values are defined constants. This may result in a rounding error, but
* it will be insignificantly small. */
LIN_break_prescale = (unsigned char)((((1000000 * LIN_MY_FREQUENCY) + H_DIVISOR) / DIVISOR) - 1);
LIN_break_count = (unsigned char)((13 * BIT_FACTOR) - 1);
#endif /* AUTO_CALCULATION. */
/* Set the break timer period. */
BRK_TMR_PRECNT_REG = LIN_break_prescale;
BRK_TMR_CNT_REG = LIN_break_count;
return;
}
#endif /* Master node. */
/**********************************************************************
* Function Name: lin_init_serial_if()
* Description: Set up the serial port.
* Parameters: None.
* Returns: Nothing.
* Ext. References: LIN_brr_value, LIN_smr_value.
* Preemptible: Yes.
* Reentrant: No.
*
* Note: This function really only sets up the Baud rate generator, sets
* the TxD pin function as a serial port output and clears the flags.
*********************************************************************/
void lin_init_serial_if(void)
{
#ifdef AUTO_CALCULATION
unsigned long brate;
unsigned int brr_value;
unsigned char i;
#endif
/* Clear the LIN configuration for a clean start. */
LIN_CONTROL_REG = 0x00;
BRK_TMR_FLAGS |= BRK_CLR_ALL_FLGS; /* Clear all break timer interrupt flags. */
/* Clear the serial port configuration. This will clear any error flags. */
LIN_UART_MODE_REG = 0x00;
LIN_UART_OP_MODE = LIN_UART_OP_OFF;
LIN_UART_RX_INT_CTL = 0x00;
LIN_UART_TX_INT_CTL = 0x00;
/* Set the serial port mode to assert TxD. */
LIN_UART_MODE_REG = LIN_UART_MODE;
LIN_UART_MODE_REG2 = LIN_UART_MODE2;
/* If AUTO_CALCULATION is defined, calculate the serial port Baud rate
* divider value instead of using precalculated value. */
#ifdef AUTO_CALCULATION
/* Try various prescaler values until the Baud rate divider is less than 256. */
for (i = 0; i <= 2; i++)
{
switch (i)
{
case 0: /* Prescale divide by 1. */
brate = (unsigned long)3125000000;
break;
case 1: /* Prescale divide by 8. */
brate = (unsigned long)390625000;
break;
case 2: /* Prescale divide by 32. */
brate = (unsigned long)97656250;
break;
}
/* Calculate the Baud rate generator divide value using integer
* math. This adds very little to the code size. */
brate += ((LIN_SPEED / 2) - 1); /* The right hand calculation should be done by the preprocessor. */
brate /= LIN_SPEED;
brate *= LIN_MY_FREQUENCY;
brate += 24999;
brate /= 50000;
brr_value = (unsigned int)(brate - 1);
if (brr_value <= 255)
{
break;
}
}
LIN_brr_value = (unsigned char)brr_value; /* Save the calculated divide value. */
LIN_smr_value = i; /* Save the prescaler index value. */
#endif /* AUTO_CALCULATION. */
/* Load the serial port control registers. */
LIN_UART_BRG_CKS |= LIN_smr_value; /* Set the BRG prescaler select bits. */
LIN_UART_BRG = LIN_brr_value; /* Set the BRG divide value. */
/* Set the basic LIN configuration. */
#if (LIN_MASTER_NODE == LIN_MY_NODE_NAME)
LIN_CONTROL_REG = 0xC0;
#else
#ifdef SYNC_AUTO_MODE
LIN_CONTROL_REG = 0xA0;
#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -