/*! * \file can.c * * \brief Target xc60xx can implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "can.h" #include "xc6xxx_hal_can.h" /*------------------------------------------------------------------------------------ Macros -------------------------------------------------------------------------------------*/ #define CAN_TX_MODE 0U #define CAN_RX_MODE 1U #define CAN_WORK_MODE CAN_TX_MODE #define CAN_ID_MODE CAN_ID_STD // CAN_ID_STD or CAN_ID_EXT #define CAN_FILTER_MODE \ CAN_FILTER_SINGLE // CAN_FILTER_SINGLE or CAN_FILTER_DUAL /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ #if (CAN_RX_MODE == CAN_WORK_MODE) uint8_t Can_recv_flag = false; CAN_MsgTypeDef Can_Rx_Msg; #endif /*------------------------------------------------------------------------------------ Func Prototype -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ /** * @brief can_demo * @details * @param void * @retval void * * ##### How to use this driver ##### * ====================================== * 125kbs config: * tclk = 1/(16 Mhz), Prescaler = 4 * TQ = tclk * 2 * Prescaler = 1/(16 Mhz) * 8 = 1 / (2 Mhz) * T(syncseg) = 1 * TQ * T(tseg1) = CAN_BUS_TIME_TSEG1_8TQ; * T(tseg2) = CAN_BUS_TIME_TSEG2_7TQ; * T(bit) = T(syncseg) + T(tseg1) + T(tseg2) = 16 TQ = 16 * 1/ (4 Mhz) = 4 / (1 * Mhz) * * 1Mbs config: * tclk = 1/(16 Mhz), Prescaler = 1 * TQ = tclk * 2 * Prescaler = 1/(16 Mhz) * 2 = 1 / (8 Mhz) * T(syncseg) = 1 * TQ * T(tseg1) = CAN_BUS_TIME_TSEG1_4TQ; * T(tseg2) = CAN_BUS_TIME_TSEG2_3TQ; * T(bit) = T(syncseg) + T(tseg1) + T(tseg2) = 8 TQ = 8 * 1/ (8 Mhz) = 1 / (1 * Mhz) * ====================================== */ void can_demo(void) { DEBUG("__CAN_DEMO__\r"); // uint8_t FilterID = CAN_ID_MODE;//CAN_ID_EXT; // uint8_t FilterMode = CAN_FILTER_MODE;//CAN_FILTER_DUAL; CAN_InitTypeDef CAN_InitStruct; CAN_FilterTypeDef CAN_FilterCfg; CAN_InitStruct.Prescaler = 1; CAN_InitStruct.SyncJumpWidth = CAN_BUS_TIME_SJW_1TQ; CAN_InitStruct.TimeSeg1 = CAN_BUS_TIME_TSEG1_4TQ; CAN_InitStruct.TimeSeg2 = CAN_BUS_TIME_TSEG2_3TQ; CAN_InitStruct.SleepMode = CAN_MODE_SLEEP_NOT_SLEEP; CAN_Init(XC_CAN, &CAN_InitStruct); CAN_FilterCfg.Id_Mode = CAN_ID_MODE; CAN_FilterCfg.Mode = CAN_FILTER_MODE; if (CAN_FilterCfg.Id_Mode == CAN_ID_STD) { if (CAN_FilterCfg.Mode == CAN_FILTER_SINGLE) { // mask, 0 means that the corresponding bit is not filtered. CAN_FilterCfg.Std_Single.Std_Id = 0x0706; CAN_FilterCfg.Std_Single.Std_Id_Mask = 0x0000; CAN_FilterCfg.Std_Single.RTR = 0x00; CAN_FilterCfg.Std_Single.RTR_Mask = 0x00; CAN_FilterCfg.Std_Single.Data_Filter.Data[0] = 0x08; CAN_FilterCfg.Std_Single.Data_Filter.Data[1] = 0x00; CAN_FilterCfg.Std_Single.Data_Filter.Data_Mask[0] = 0x00; CAN_FilterCfg.Std_Single.Data_Filter.Data_Mask[1] = 0x00; } else if (CAN_FilterCfg.Mode == CAN_FILTER_DUAL) { // mask, 0 means that the corresponding bit is not filtered. CAN_FilterCfg.Std_Dual.Filter1.Std_Id = 0x0706; CAN_FilterCfg.Std_Dual.Filter1.Std_Id_Mask = 0x0000; CAN_FilterCfg.Std_Dual.Filter1.RTR = 0x00; CAN_FilterCfg.Std_Dual.Filter1.RTR_Mask = 0x00; CAN_FilterCfg.Std_Dual.Filter1.Data_Filter.Data[0] = 0x0; CAN_FilterCfg.Std_Dual.Filter1.Data_Filter.Data[1] = 0x0; CAN_FilterCfg.Std_Dual.Filter1.Data_Filter.Data_Mask[0] = 0x0; CAN_FilterCfg.Std_Dual.Filter1.Data_Filter.Data_Mask[1] = 0x0; CAN_FilterCfg.Std_Dual.Filter2.Std_Id = 0x0706; CAN_FilterCfg.Std_Dual.Filter2.Std_Id_Mask = 0x0000; CAN_FilterCfg.Std_Dual.Filter2.RTR = 0x00; CAN_FilterCfg.Std_Dual.Filter2.RTR_Mask = 0x00; } } else if (CAN_FilterCfg.Id_Mode == CAN_ID_EXT) { if (CAN_FilterCfg.Mode == CAN_FILTER_SINGLE) { // mask, 0 means that the corresponding bit is not filtered. CAN_FilterCfg.Ext_Single.Ext_Id = 0x12345678; CAN_FilterCfg.Ext_Single.Ext_Id_Mask = 0x00000000; CAN_FilterCfg.Ext_Single.RTR = 0x00; CAN_FilterCfg.Ext_Single.RTR_Mask = 0x00; } else if (CAN_FilterCfg.Mode == CAN_FILTER_DUAL) { // mask, 0 means that the corresponding bit is not filtered. CAN_FilterCfg.Ext_Dual.Filter1.Ext_Id = 0x12345678; CAN_FilterCfg.Ext_Dual.Filter1.Ext_Id_Mask = 0x00000000; CAN_FilterCfg.Ext_Dual.Filter2.Ext_Id = 0x12345678; CAN_FilterCfg.Ext_Dual.Filter2.Ext_Id_Mask = 0x00000000; } } CAN_Filter_Config(XC_CAN, &CAN_FilterCfg); CAN_Enable_IT(XC_CAN, CAN_INTERRUPT_RECEIVE_ENABLE); NVIC_EnableIRQ(CAN_IRQn); #if 0 if(FilterID == CAN_ID_STD) { if(FilterMode == CAN_FILTER_SINGLE) { //mask, 0 means that the corresponding bit is not filtered. CAN_FilterConfig.FilterIdHigh16bit = 0x0000; CAN_FilterConfig.FilterIdLow16bit = 0x0070; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_FilterConfig.StandardFrameFilter.Data[0]= 0x08; CAN_FilterConfig.StandardFrameFilter.Data[1]= 0x00; CAN_FilterConfig.StandardFrameFilter.MaskData[0]= 0x00; CAN_FilterConfig.StandardFrameFilter.MaskData[1]= 0x00; CAN_StandardFrameConfigSingleFilter(XC_CAN, &CAN_FilterConfig); } else if(FilterMode == CAN_FILTER_DUAL) { //mask, 0 means that the corresponding bit is not filtered. //DualFilter1 Only filter one byte of data CAN_FilterConfig.FilterIdHigh16bit = 0x0070; CAN_FilterConfig.FilterIdLow16bit = 0x0070; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_StandardFrameConfigDualFilter1(XC_CAN, &CAN_FilterConfig); //DualFilter2 do not filter data, only filter ID and RTR CAN_FilterConfig.FilterIdHigh16bit = 0x0000; CAN_FilterConfig.FilterIdLow16bit = 0x000F; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_StandardFrameConfigDualFilter2(XC_CAN, &CAN_FilterConfig); } } else if(FilterID == CAN_ID_EXT) { if(FilterMode == CAN_FILTER_SINGLE) { //mask, 0 means that the corresponding bit is not filtered. CAN_FilterConfig.FilterIdHigh16bit = 0x0070; CAN_FilterConfig.FilterIdLow16bit = 0x0070; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_ExtendedFrameConfigSingleFilter(XC_CAN, &CAN_FilterConfig); } else if(FilterMode == CAN_FILTER_DUAL) { //mask, 1 means that the corresponding bit is not filtered. CAN_FilterConfig.FilterIdHigh16bit = 0x0070; CAN_FilterConfig.FilterIdLow16bit = 0x0070; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_ExtendedFrameConfigDualFilter1(XC_CAN, &CAN_FilterConfig); CAN_FilterConfig.FilterIdHigh16bit = 0x0080; CAN_FilterConfig.FilterIdLow16bit = 0x0080; CAN_FilterConfig.FilterMaskIdHigh16bit = 0x0000; CAN_FilterConfig.FilterMaskIdLow16bit = 0x0000; CAN_FilterConfig.FilterRTR = 0x0000; CAN_FilterConfig.FilterMaskRTR = 0x0000; CAN_ExtendedFrameConfigDualFilter2(XC_CAN, &CAN_FilterConfig); } } #endif #if (CAN_TX_MODE == CAN_WORK_MODE) DEBUG("__CAN_TX_MODE__\r"); CAN_MsgTypeDef CAN_Msg; CAN_Msg.TxHeader.StdId = 0x706; // 11 bits CAN_Msg.TxHeader.ExtId = 0x12345678; // 29 bits CAN_Msg.TxHeader.FrameFormat = CAN_ID_MODE; // CAN_ID_STD or CAN_ID_EXT CAN_Msg.TxHeader.RTR = CAN_RTR_DATA; CAN_Msg.TxHeader.DLC = 8; // 0~8 bytes for (uint8_t i = 0; i < CAN_Msg.TxHeader.DLC; i++) { CAN_Msg.Tx_Msg[i] = i; } CAN_Transmit(XC_CAN, &CAN_Msg); #else DEBUG("__CAN_RX_MODE__\r"); #endif while (1) { #if (CAN_TX_MODE == CAN_WORK_MODE) Delay_Ms(1000); #else if (Can_recv_flag == true) { if (Can_Rx_Msg.RxHeader.FrameFormat == CAN_ID_STD) DEBUG("CAN STD ID: 0x%04x\n", Can_Rx_Msg.RxHeader.StdId); else if (Can_Rx_Msg.RxHeader.FrameFormat == CAN_ID_EXT) DEBUG("CAN EXT ID: 0x%08x\n", Can_Rx_Msg.RxHeader.ExtId); else DEBUG("CAN ID Mode Error!!!\n"); DEBUG("CAN DLC: %d\n", Can_Rx_Msg.RxHeader.DLC); for (uint8_t n = 0; n < Can_Rx_Msg.RxHeader.DLC; n++) { PRINT("%x-", Can_Rx_Msg.Rx_Msg[n]); } PRINT("\r"); Can_recv_flag = false; } // if(Can_ext_recv_flag == true) // { // DEBUG("CAN Recv %d\n", recv); // for(uint8_t n=0; nRxHeader.FrameFormat; Can_Rx_Msg.RxHeader.StdId = can_msg->RxHeader.StdId; Can_Rx_Msg.RxHeader.ExtId = can_msg->RxHeader.ExtId; Can_Rx_Msg.RxHeader.DLC = can_msg->RxHeader.DLC; memcpy(Can_Rx_Msg.Rx_Msg, can_msg->Rx_Msg, Can_Rx_Msg.RxHeader.DLC); // DEBUG("CB_FrameFormat=0x%x, RTR=0x%x, SID=0x%x, EID=0x%x, len=0x%x\n", // Can_Rx_Msg.RxHeader.FrameFormat, // Can_Rx_Msg.RxHeader.RTR , Can_Rx_Msg.RxHeader.StdId, // Can_Rx_Msg.RxHeader.ExtId, Can_Rx_Msg.RxHeader.DLC); Can_recv_flag = true; #endif } ///** // * @brief CAN_Ext_ID_Intr_Callback // * @details CAN extended id interrupt callback function // * @param void *context // * @retval void // */ //__RAM_CODE void CAN_Ext_ID_Intr_Callback(CAN_EFF_TypeDef can_eff, uint8_t //can_dlc) //{ //#if (CAN_RX_MODE == CAN_WORK_MODE) // memcpy(Recv_buffer, can_eff.DATA, can_dlc); // Can_ext_recv_flag = false; //#endif //}