Files
hpw421/component/xc6xx_drivers/Drivers/test_case/CAN/can.c
T
2026-06-06 16:49:48 +08:00

323 lines
12 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
//}