V1.0
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
/*!
|
||||
* \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
|
||||
//}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* \file can.h
|
||||
*
|
||||
* \brief The head file of can.c
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* _ __ _ ________ _
|
||||
* | |/ /(_)___ / ____/ /_ (_)___
|
||||
* | // / __ \/ / / __ \/ / __ \
|
||||
* / |/ / / / / /___/ / / / / /_/ /
|
||||
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
|
||||
* /_/
|
||||
* (C) 2022-2025 XinChip
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \author ( XinChip ) Alex-J
|
||||
*
|
||||
* \author ( XinChip )
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __CAN_H__
|
||||
#define __CAN_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------------------
|
||||
INCLUDE HEADE FILES
|
||||
------------------------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
Macros
|
||||
-------------------------------------------------------------------------------------*/
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
TypeDef
|
||||
-------------------------------------------------------------------------------------*/
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
Global Variables
|
||||
-------------------------------------------------------------------------------------*/
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
Exported Functions
|
||||
-------------------------------------------------------------------------------------*/
|
||||
void can_demo(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CAN_H__ */
|
||||
Reference in New Issue
Block a user