323 lines
13 KiB
C
323 lines
13 KiB
C
/*!
|
|
* \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; n<recv; n++)
|
|
// {
|
|
// DEBUG("%x ", Recv_buffer[n]);
|
|
// }
|
|
// DEBUG("\r");
|
|
//
|
|
// Can_ext_recv_flag = false;
|
|
// }
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief CAN_Intr_Callback
|
|
* @details CAN interrupt callback function
|
|
* @param void *context
|
|
* @retval void
|
|
*/
|
|
__RAM_CODE void CAN_Intr_Callback(CAN_MsgTypeDef *can_msg) {
|
|
#if (CAN_RX_MODE == CAN_WORK_MODE)
|
|
Can_Rx_Msg.RxHeader.FrameFormat = can_msg->RxHeader.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
|
|
//}
|