/* ********************************************************************* * Includes ********************************************************************* */ #include "kwp2000_interface.h" #include "kwp2000_tp.h" /* ********************************************************************* * defines ********************************************************************* */ /* Possible initialization formats */ #define KWP2000_FORMAT_NOADDRESS 0u /* 00 */ #define KWP2000_FORMAT_CARB 1u /* 01 Exception mode */ #define KWP2000_FORMAT_PHYSICALADDRESSING 2u /* 10 */ #define KWP2000_FORMAT_FUNCTIONALADDRESSING 3u /* 11 */ #define KWP2000_WUP_TI_IDLE_DU 5ul /* idle time of RX pins [us] */ #define KWP2000_WUP_TI_MIN_DU 24ul /* duration of WUP, min value (low time/hi time) [ms] */ #define KWP2000_WUP_TI_MAX_DU 26ul /* duration of WUP, max value (low time/hi time) [ms] */ /* ********************************************************************* * structure ********************************************************************* */ typedef enum { KWP2000_WUP_WAIT4IDLE_E = 0x00, KWP2000_WUP_WAIT4SCANLO_E = 0x10, KWP2000_WUP_SCANLO_E, KWP2000_WUP_WAIT4SCANHI_E = 0x20, KWP2000_WUP_SCANHI_E, KWP2000_WUP_SCANASC_E = 0x30, KWP2000_WUP_DETECTED_E = 0x80, } Kwp2000_ScanStates_t; typedef struct { unsigned long xPortIn_pu32; unsigned long xPortInMsk_u32; unsigned long tiStartSample_u32; Kwp2000_ScanStates_t xScanState_u32; unsigned char xBusType_u32; unsigned long tiCom_u32; } Kwp2000_ScanWup_t; /* ********************************************************************* * variable ********************************************************************* */ /* Carb address and format */ unsigned char kwp2000_CARB_Address; unsigned char kwp2000_CARB_TgtRequest; unsigned char kwp2000_CARB_TgtResponse; unsigned char kwp2000_CARB_Fmt; unsigned long Kwp2000_TimeCounter; unsigned long Kwp2000_P2_TimeCounter; unsigned long Kwp2000_ComMode; Kwp2000_ScanWup_t Kwp2000_ScanWup; Kwp2000_Modify_t Kwp2000_Modify; Kwp2000_ComState_t Kwp2000_ComState; /* ********************************************************************* * function ********************************************************************* */ void Kwp2000_ProtocolInit(void); /*------------------------------------------------------------------------- * Function Name : Kwp2000_Init * Description : Kwp2000初始化 * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_Init(void) { Kwp2000_AscInit(); Kwp2000_ProtocolInit(); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_ProtocolInit * Description : KWP2000协议初始化 * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_ProtocolInit(void) { /* Initial time base */ Kwp2000_TimeCounter = 0; Kwp2000_P2_TimeCounter = 0; /* Prepare Wup scan */ Kwp2000_ComMode = COM_INIT; Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_WAIT4IDLE_E; Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; //Uart_DisableReceiveIsrReq(); /*----20220309----*/ /*Set RX as GPIO-IN*/ Uart_SetRxGpio(); Kwp2000_Modify.typeOfModif = KWP2000_MODIFY_NULL; Kwp2000_ComState.Rx_len = 0; Kwp2000_SetAddress(); Kwp2000_SetTiming(); kwp2000_CARB_TgtRequest = 0x6A; kwp2000_CARB_TgtResponse = 0x6B; Kwp2000_ComState.ResponsePending = 0; } /*------------------------------------------------------------------------- * Function Name : Kwp2000_Timeout * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_Timeout(void) { unsigned long tiSample_u32; if ((Kwp2000_ComMode & PROTOCOL) == KWP2000) { tiSample_u32 = Kwp2000_TimeCounter; /**/ if (Kwp2000_ComMode == KWP2000_FAST_INIT) { if ((tiSample_u32 - Kwp2000_ComState.tiCom_u32) >= 20u) { Kwp2000_ProtocolInit(); } } else { if ((tiSample_u32 - Kwp2000_ComState.tiCom_u32) >= kwp2000_P3_MAX_LIMIT) { Kwp2000_ProtocolInit(); } } /* tiSample_u32 = Kwp2000_TimeCounter; if((tiSample_u32 - Kwp2000_ComState.tiCom_u32) >= kwp2000_P3_MAX_LIMIT) { Kwp2000_ProtocolInit(); } */ } } /*------------------------------------------------------------------------- * Function Name : Kwp2000_CommuniationDown * Description : 通讯底层与协议层初始化 * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_CommuniationDown(void) { Kwp2000_AscInit(); Kwp2000_ProtocolInit(); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_VerifyChecksum * Description : Verify the message checksum * Input : * Output : None * Return : TRUE or FALSE * onther : --------------------------------------------------------------------------*/ unsigned char Kwp2000_VerifyChecksum(void) { unsigned char answer; unsigned char CS; /* Calculates the message Checksum */ CS = Kwp2000_ChecksumCalculate((unsigned char *) & (Kwp2000_ComState.RxBuffer[0]), (unsigned short)(Kwp2000_ComState.headerSize + Kwp2000_ComState.kwp2000_Len)); /* Verifies it with the one that was in the message */ if (CS == Kwp2000_ComState.kwp2000_Checksum) { /* it is ok */ answer = 1; } else { /* it is not the same */ answer = 0; } return (answer); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_ChecksumCalculate * Description : calculates the checksum * Input : dataBuffer, numberOfBytes * Output : None * Return : sum * onther : --------------------------------------------------------------------------*/ unsigned char Kwp2000_ChecksumCalculate(unsigned char *dataBuffer, unsigned short numberOfBytes) { unsigned char sum; unsigned short i; /* Resets the sum */ sum = 0; for (i = 0; i < numberOfBytes; i++) { /* add each byte to the sum */ sum += dataBuffer[i]; } return (sum); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_PrepareHeader * Description : constructs the message header * Input : headerSize * Output : dataSize * Return : sum * onther : --------------------------------------------------------------------------*/ unsigned char Kwp2000_PrepareHeader(unsigned char dataSize) { unsigned char headerSize; unsigned char fmt; /* Resets the header size */ headerSize = 1; /* Tests the data size */ if (dataSize > 63) { /* Too big to be written in the format byte, needs additional length byte */ fmt = Kwp2000_ComState.Format << 6; Kwp2000_ComState.TxBuffer[4 - (headerSize++)] = dataSize; } else { /* Format and size in the same byte */ fmt = (Kwp2000_ComState.Format << 6) | dataSize; } /* Test the format used */ switch (Kwp2000_ComState.Format) { case KWP2000_FORMAT_NOADDRESS: /* if no address then nothing to be added to the header */ break; case KWP2000_FORMAT_CARB: // /* CARB mode */ // fmt = kwp2000_CARB_Fmt; // asc0_CommunicationBuf.b[4-(headerSize++)]= kwp2000_CARB_Address; // asc0_CommunicationBuf.b[4-(headerSize++)]= kwp2000_CARB_TgtResponse; break; case KWP2000_FORMAT_FUNCTIONALADDRESSING: case KWP2000_FORMAT_PHYSICALADDRESSING: /* Physical addressing */ Kwp2000_ComState.TxBuffer[4 - (headerSize++)] = kwp2000_PhysicalAddress; Kwp2000_ComState.TxBuffer[4 - (headerSize++)] = Kwp2000_ComState.SrcAddr; // kwp2000_ServerAddress; break; } Kwp2000_ComState.TxBuffer[4 - headerSize] = fmt; Kwp2000_ComState.Response_Datas = (unsigned char *)&Kwp2000_ComState.TxBuffer[4 - headerSize]; return (headerSize); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_FormatAnalyse * Description : Copies the datas from the buffer to the variables related to the header information * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_HeaderAnalyse(void) { /* Tests the header size */ switch (Kwp2000_ComState.headerSize) { case 1: /* 1 byte -> FMT */ break; case 2: /* 2 bytes -> FMT LEN */ Kwp2000_ComState.kwp2000_Len = Kwp2000_ComState.RxBuffer[1]; break; case 3: /* 3 bytes -> FMT TGT SRC */ Kwp2000_ComState.TgtAddr = Kwp2000_ComState.RxBuffer[1]; Kwp2000_ComState.SrcAddr = Kwp2000_ComState.RxBuffer[2]; break; case 4: /* 4 bytes -> FMT TGT SRC LEN */ Kwp2000_ComState.TgtAddr = Kwp2000_ComState.RxBuffer[1]; Kwp2000_ComState.SrcAddr = Kwp2000_ComState.RxBuffer[2]; Kwp2000_ComState.kwp2000_Len = Kwp2000_ComState.RxBuffer[3]; break; } } /*------------------------------------------------------------------------- * Function Name : Kwp2000_FormatAnalyse * Description : ����֡���� * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ unsigned char Kwp2000_FormatAnalyse(void) { unsigned char headerSize; /* Extracts the format information */ Kwp2000_ComState.Format = (Kwp2000_ComState.RxBuffer[0] & 0xC0) >> 6; /* Extracts the message length */ Kwp2000_ComState.kwp2000_Len = Kwp2000_ComState.RxBuffer[0] & 0x3F; /* Resets the headerSize */ headerSize = 1; /* Tests the format */ switch (Kwp2000_ComState.Format) { case KWP2000_FORMAT_NOADDRESS: /* There is no address */ break; case KWP2000_FORMAT_CARB: /* There are source and target addresses */ Kwp2000_ComState.kwp2000_Len = 0; case KWP2000_FORMAT_PHYSICALADDRESSING: case KWP2000_FORMAT_FUNCTIONALADDRESSING: /* There are source and target addresses */ headerSize += 2; break; } /* Tests the message length */ if (Kwp2000_ComState.kwp2000_Len == 0) { /* it was 0 so there is an additional length byte */ headerSize++; } else { } /* Sets the pointer at the beginning of the datas */ Kwp2000_ComState.Request_Datas = (unsigned char *) & (Kwp2000_ComState.RxBuffer[headerSize]); return (headerSize); } /*------------------------------------------------------------------------- * Function Name : kwp2000_AddressTest * Description : verifies the target address to know if this ECU is the target * Input : * Output : None * Return : TRUE or FALSE * onther : --------------------------------------------------------------------------*/ unsigned char kwp2000_AddressTest(void) { unsigned char answer = 0; /* Tests the format */ if (Kwp2000_ComState.Format == KWP2000_FORMAT_NOADDRESS) { /* No addressing bytes */ /* The message is for this ECU */ answer = 1; } else { switch (Kwp2000_ComState.Format) { case KWP2000_FORMAT_CARB: /* CARB addressing mode */ if (Kwp2000_ComState.TgtAddr == kwp2000_CARB_TgtRequest) { /* it is the correct address */ answer = 1; } else { /* it is the false address */ answer = 0; } break; case KWP2000_FORMAT_PHYSICALADDRESSING: /* Physical addressing mode */ if (Kwp2000_ComState.TgtAddr == kwp2000_PhysicalAddress) { /* it is the correct address */ answer = 1; } else { /* it is the false address */ answer = 0; } break; case KWP2000_FORMAT_FUNCTIONALADDRESSING: /* Functional addressing mode */ if ((Kwp2000_ComState.TgtAddr == kwp2000_FunctionalAddress) || (Kwp2000_ComState.TgtAddr == kwp2000_PhysicalAddress)) { /* it is the correct address */ answer = 1; } else { /* it is the false address */ answer = 0; } break; default: break; } } return (answer); } /*------------------------------------------------------------------------- * Function Name : Kwp2000_ComInit_Handle * Description : 测量Twup * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_ComInit_Handle(void) { unsigned char RxPortState; /* scan all RX-pins, which are configured, for WUP */ RxPortState = Uart_GetRxLevel(); /* scan WUP (100ms) for each ASC available */ /* wait Tidle */ if (Kwp2000_ScanWup.xScanState_u32 == KWP2000_WUP_WAIT4IDLE_E) { if (RxPortState != 0) { if ((Kwp2000_TimeCounter - Kwp2000_ScanWup.tiStartSample_u32) >= KWP2000_WUP_TI_IDLE_DU) { Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_WAIT4SCANLO_E; } } else { Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; } } /* wait for low level on RX-pin and start time measurement */ if (Kwp2000_ScanWup.xScanState_u32 == KWP2000_WUP_WAIT4SCANLO_E) { if (RxPortState == 0) { Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_SCANLO_E; Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; } } // measure low level time on RX-pin, if level changes to high during the first 25ms // abort measurement if (Kwp2000_ScanWup.xScanState_u32 == KWP2000_WUP_SCANLO_E) { if (RxPortState != 0) { if (((Kwp2000_TimeCounter - Kwp2000_ScanWup.tiStartSample_u32) >= KWP2000_WUP_TI_MIN_DU) && ((Kwp2000_TimeCounter - Kwp2000_ScanWup.tiStartSample_u32) <= KWP2000_WUP_TI_MAX_DU)) { Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_WAIT4SCANHI_E; } else { Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_WAIT4IDLE_E; } } } // After 25ms - 4%, wait until RX-pin level goes hi // If level stays low, abort measurement if (Kwp2000_ScanWup.xScanState_u32 == KWP2000_WUP_WAIT4SCANHI_E) { if (RxPortState != 0) { if ((Kwp2000_TimeCounter - Kwp2000_ScanWup.tiStartSample_u32) >= KWP2000_WUP_TI_MIN_DU) { Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_DETECTED_E; Uart_SetRxGpio(); // RX Kwp2000_AscEnableRx(); /* reset variables, which are used by the receive interrupt function */ Kwp2000_ComState.Rx_len = 0; /* enable irq */ Uart_EnableReceiveIsrReq(); Kwp2000_ComMode = KWP2000_FAST_INIT; Kwp2000_ComState.tiCom_u32 = Kwp2000_TimeCounter; } } else { if (RxPortState == 0) { Kwp2000_ScanWup.tiStartSample_u32 = Kwp2000_TimeCounter; Kwp2000_ScanWup.xScanState_u32 = KWP2000_WUP_WAIT4IDLE_E; } } } Kwp2000_TimeCounter += 1; Kwp2000_P2_TimeCounter += 1; } /*------------------------------------------------------------------------- * Function Name : Kwp2000_AscRxInterrupt * Description : 串口接收中断 * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Kwp2000_AscRxInterrupt(void) { unsigned short rxUartData; Uart_ClearRxFullFlag(); /* clear service request flags */ if ((Kwp2000_ComMode & PROTOCOL) == KWP2000) { if (Kwp2000_ComMode < KWP2000_BUILD_RESPONSE) { /* if receve on going */ if (Kwp2000_ComMode == KWP2000_FAST_INIT) { Kwp2000_ComMode = KWP2000_WAIT_RECEPTION; } if (Kwp2000_ComState.Rx_len < KWP2000_RX_BUFFER_SIZE) { rxUartData = Uart_GetData(); /*读取串口数据 ----20220303----*/ Kwp2000_ComState.RxBuffer[Kwp2000_ComState.Rx_len] = (unsigned char)rxUartData; Kwp2000_ComState.tiCom_u32 = Kwp2000_TimeCounter; Kwp2000_ComState.Rx_len++; } } else { /* if transmit on going, do nothing */ rxUartData = Uart_GetData(); /* 读取串口数据----20220303----*/ if (Kwp2000_ComState.Tx_len) { Kwp2000_ComState.Tx_len--; } if (Kwp2000_ComState.Tx_len > 0) { if (rxUartData == (*Kwp2000_ComState.Response_Datas)) { Kwp2000_P2_TimeCounter = 0; Kwp2000_ComState.Response_Datas++; Kwp2000_AscTx(Kwp2000_ComState.Response_Datas); /* 数据发送----20220303----*/ } else { Kwp2000_ComState.Tx_len = 0; Kwp2000_ComMode = KWP2000_WAIT_RECEPTION; } } else { if (Kwp2000_ComState.ResponsePending) { Kwp2000_ComMode = KWP2000_BUILD_RESPONSE; /* Start a new timeout counter */ Kwp2000_ComState.tiCom_u32 = Kwp2000_TimeCounter; } else { Kwp2000_ComMode = KWP2000_MODIFY_CONFIG; } } } } }