CAN配置初始化代码
/*
* HAL_GPIO.c
*
* Created on: 2023年2月13日
* Author: Administrator
*/
#include "HAL_CAN.h"
#include "device.h"
#include "F28004x_IapCfg.h"
#define MSG_DATA_LENGTH 8 //
void HAL_CANGPIO_Init(void);//CAN gpio配置
void HAL_CANReg_Init(void);//CAN寄存器配置
/**@
* 名称:
* 输入:
*/
void HAL_CAN_Init(void)
{
EALLOW;
CanaRegs.CAN_RAM_INIT.all = 0;
CanaRegs.CAN_CTL.all = 0;
CanaRegs.CAN_BTR.all = 0;
CanaRegs.CAN_IF1CMD.all = 0;
CanaRegs.CAN_IF1ARB.all = 0;
CanaRegs.CAN_IF1MSK.all = 0;
CanaRegs.CAN_IF1MCTL.all = 0;
CanaRegs.CAN_IF2CMD.all = 0;
CanaRegs.CAN_IF2ARB.all = 0;
CanaRegs.CAN_IF2MSK.all = 0;
CanaRegs.CAN_IF2MCTL.all = 0;
CpuSysRegs.PCLKCR10.bit.CAN_A = 0;
EDIS;
HAL_CANReg_Init();//CAN寄存器配置
}
/**@
* 名称:
* 输入:
*/
void HAL_CANReg_Init(void)
{
EALLOW;
CpuSysRegs.PCLKCR10.bit.CAN_A = 1U;
EDIS;
// 禁止所有邮箱
CAN_disableAllMessageObjects(CANA_BASE);
// 初始化CAN
CAN_initModule(CANA_BASE);
// CAN_enableAutoBusOn(CANA_BASE);
/*************** 波特率配置 *************
* CAN_BTR->BRP=31 : Baud Rate Prescaler
* CAN_BTR->SJW=3 :
* CAN_BTR->TSEG1 =15
* CAN_BTR->TSEG2 = 7
* CAN_BTR->BRPE = 0
* * 配置完成后会清除CCE位 CAN_CTL->CCE =0
* SYSclock(100M)
* Bit rate = --------------------------------------
* (BRP + 1) * ((TSEG1 + 1) + (TSEG2 + 1)+1)
* *
* 50k->BRP:15 BRPE= 1; 100K->BRP:39; 125K->31; 250K->15
*************************************/
CAN_setBitTiming(CANA_BASE, 31, 0, 15, 7, 3);//125k
// CAN_setBitRate(CANA_BASE,DEVICE_SYSCLK_FREQ,125000,25);
// 邮箱配置
/**与使用掩码的邮箱匹配的报文在邮箱有数据时不会往空闲的ID不滤波的邮箱放***/
/************请使用1-16作为接收邮箱使用**********/
// 为自动排序报文配置专用邮箱
CAN_setupMessageObject(CANA_BASE, 1,0x0FFFFFFF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFFF,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER|CAN_MSG_OBJ_FIFO),MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 2,0x0FFFFFFF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFFF,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER),MSG_DATA_LENGTH);
// 为0x18010000ID配置专用邮箱
CAN_setupMessageObject(CANA_BASE, 3,0x18010000 ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFF0000,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER|CAN_MSG_OBJ_FIFO),MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 4,0x18010000 ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFF0000,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER),MSG_DATA_LENGTH);
// 为0x18050000ID配置专用邮箱
CAN_setupMessageObject(CANA_BASE, 5,0x18050000 ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFF0000,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER|CAN_MSG_OBJ_FIFO),MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 6,0x18050000 ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFF0000,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER),MSG_DATA_LENGTH);
// 为CAN烧写配置专用邮箱
CAN_setupMessageObject(CANA_BASE, 7,IAP_CAN_RXID_DEF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFFF,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER|CAN_MSG_OBJ_FIFO),MSG_DATA_LENGTH);
CAN_setupMessageObject(CANA_BASE, 8,IAP_CAN_RXID_DEF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFFF,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER),MSG_DATA_LENGTH);
// 使用了邮箱9-12 配置FIFO
for(Uint16 u16Cnt=9;u16Cnt<16;u16Cnt++)
{
if(u16Cnt<15)
{
CAN_setupMessageObject(CANA_BASE, u16Cnt,0x1FFFFFFF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER |CAN_MSG_OBJ_USE_DIR_FILTER |CAN_MSG_OBJ_FIFO),MSG_DATA_LENGTH);
}
else
{
CAN_setupMessageObject(CANA_BASE, u16Cnt,0x1FFFFFFF ,CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_EXT_FILTER|CAN_MSG_OBJ_USE_DIR_FILTER),MSG_DATA_LENGTH);
}
}
//
// Start CAN module operations
// Clear Init and CCE bits
//
CAN_startModule(CANA_BASE);
}
Ecandrive
/*=============================================================================*
* Copyright(c) 2011-2020, Shijiazhuang TonHe Electronics Co., Ltd.
* ALL RIGHTS RESERVED
*
* Product: XXX
*
* File name: XXX.c
*
* Description: XXX模块程序文件
*
* Author:
*
* Data: 201X-XX-XX
*
*=============================================================================*/
#include "EcanDrive.h"
#include "string.h"
//本模块公有全局变量定义
Uint16 u16RxDataCounter = 0; // 接收数据写计数
Uint16 u16RxReadDataCnt = 0; // 接收数据读计数
Uint16 u16TxdataCounter = 0; // 发送数据写计数
Uint16 u16TxReadDataCnt = 0; // 发送数据读计数
Uint16 u16RxDataLen = 0; // 接收缓冲区存储数据长度
Uint16 u16TxDatalen = 0; // 发送缓冲区存储数据长度
//本模块私有变量定义
struct CANMBOXn_DATA stCanRxDataBuffer[MRXDATAMAX]; // 接收数据缓冲数组
struct CANMBOXn_DATA stCanTxDataBuffer[MTXDATAMAX]; // 发送数据缓冲数组
Uint16 stCanTxDataBufferMBOX[MTXDATAMAX]; // 发送数据缓冲数组对应的邮箱,与发送数据缓冲数组中的数据是一一对应的
// 比如两个数组中的第5个元素就分别是要发送的数据和对应的邮箱
/*==============================================================================
* Function name: void XXX(void)
*
* Description: the main function
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author:
*
* Data: 201X-0X-XX
*==============================================================================*/
void vEcanDrive_Init(void)
{
//初始化各个变量
u16RxDataCounter = 0;
u16TxdataCounter = 0;
memset(stCanRxDataBuffer,0,sizeof(stCanRxDataBuffer));
memset(stCanTxDataBuffer,0,sizeof(stCanTxDataBuffer));
//************************以下调用各个协议的初始化函数************************
vCom2Hmi_Init();
vCurrentEquanLize_Init();
CommAutoAdd_Init();
//************************以上调用各个协议的初始化函数************************
}
/*==============================================================================
* Function name: vEcanDrive_Push2TxDataBuffer
*
* Description: 将要发送的CAN数据放入发送缓冲区 连续使用次数不应超过MTXDATAMAX的长度超过的部分会丢掉
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
void vEcanDrive_Push2TxDataBuffer(struct CANMBOXn_DATA *stSendData, Uint16 u16MBOXn)
{
if(u16TxDatalen < MTXDATAMAX)
{
stCanTxDataBuffer[u16TxdataCounter] = *stSendData; // 数据
stCanTxDataBufferMBOX[u16TxdataCounter] = u16MBOXn; // 邮箱号
u16TxdataCounter++;
u16TxDatalen++;
if(u16TxdataCounter >= MTXDATAMAX)
{
u16TxdataCounter = 0;
}
}
}
/*==============================================================================
* Function name: void vEcanDrive_TxDataBufferProcess(void)
*
* Description: 发送CAN缓冲区中的数据
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author:wgs
*
* Data: 2025-10-23
*==============================================================================*/
void vEcanDrive_TxDataBufferProcess(void)
{
static Uint16 u16FirstCnt = 0;
Uint32 u32MailStatus;
Uint32 u32temp = 1;
if(u16TxDatalen > 0)
{
//(HWREGH(CANA_BASE + CAN_O_ES) & CAN_ES_TXOK) == CAN_ES_TXOK
//u32MailStatus = CAN_getTxRequeTxsts(CANA_BASE);
//u32MailStatus != (u32temp <<(stCanTxDataBufferMBOX[u16TxReadDataCnt] - 1)) &&
if ((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) != CAN_IF1CMD_BUSY)
{
u16FirstCnt = 1;
HAL_CANASEND1(&stCanTxDataBuffer[u16TxReadDataCnt],stCanTxDataBufferMBOX[u16TxReadDataCnt]);
u16TxReadDataCnt++;
u16TxDatalen--;
if(u16TxReadDataCnt >= MTXDATAMAX)
{
u16TxReadDataCnt = 0;
}
}
}
}
/*==============================================================================
* Function name: EcanDrive_RxCheck
*
* Description: 查询各个邮箱状态,将收到的数据存入接收缓存数组
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
void EcanDrive_RxCheck(void)
{
Uint16 u16RxMailFlag = 0;
u16RxMailFlag = (HWREG_BP(CANA_BASE + CAN_O_NDAT_21)) & 0xFFFF; // 取出邮箱1-16的标志位
if(u16RxMailFlag != 0) // 邮箱有新数据且缓冲区数据未存满
{
for(Uint16 i=0;i<16;i++) // 遍历邮箱1-16
{
if((u16RxMailFlag>>i) & 0x01 == 1)
{
if(u16RxDataLen < MRXDATAMAX)
{
HAL_CANRECV(&stCanRxDataBuffer[u16RxDataCounter++],i+1); // 读取邮箱数据存入接收缓冲区
u16RxDataLen++;
if(u16RxDataCounter >= MRXDATAMAX)
{
u16RxDataCounter = 0;
}
}
}
}
}
}
/*==============================================================================
* Function name: vEcanDrive_RxDataProcess
*
* Description: 接收数据处理
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author:
*
* Data: 201X-0X-XX
*==============================================================================*/
void vEcanDrive_RxDataProcess(void)
{
struct CANMBOXn_DATA stCanRxDataTemp;
Uint16 u32CANtime=20000;
EcanDrive_RxCheck();
if(u16RxDataLen>0)
{
stCanRxDataTemp = stCanRxDataBuffer[u16RxReadDataCnt++];
u16RxDataLen--;
if(u16RxReadDataCnt >= MRXDATAMAX)
{
u16RxReadDataCnt = 0;
}
//************************以下调用各个协议的接收数据处理函数************************
//上位机通信协议,接收数据处理
if((stCanRxDataTemp.u32MID.all & 0x1FFFFFFF) == IAP_CAN_RXID_DEF)
{
IAP_Process(&stCanRxDataTemp);
}
StarStarCAN_request(stCanRxDataTemp);
//************************以上调用各个协议的接收数据处理函数************************
vCom2Hmi_Rx(stCanRxDataTemp);
vCurrentEquanLize(stCanRxDataTemp);
vCommAutoAdd_RX(stCanRxDataTemp);
}
if(u8Com2Hmi_ChooseFlag==1 || u8Com2Hmi_ChooseFlag==5)
{//1国网协议、5复兴协议
u32CANtime=u16Ecan_Count;
}
else if(u8Com2Hmi_ChooseFlag == 7)
{//7英可瑞协议
u32CANtime=M_120s;
}
else// if(u8Com2Hmi_ChooseFlag==2)
{//2通合协议//6华商三零
u32CANtime=M_20s;
}
mSW_TMRSet(SW_TMR_COM2HMI_OVERTIME,u32CANtime);
if(mSW_TMR_IFSts(SW_TMR_COM2HMI_OVERTIME))
{
if(u8RunMode==0)
{
u16Ecan_Fault = 1; //置位通信故障标志
if((u8Com2Hmi_ChooseFlag==1||u8Com2Hmi_ChooseFlag==5) && (g_u8GroupMode==1))//国网协议、复兴协议:动态分组,通信超时,清空组号
{
g_u16Group = 0;
}
}
else
{
u16Ecan_Fault = 0; //手动模式下,要复位通信故障标志
}
mSW_TMRReload(SW_TMR_COM2HMI_OVERTIME,u32CANtime);//重载通信超时计数器
}
}
/*==============================================================================
* Function name: HAL_CANASEND1
*
* Description:
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
Uint16 HAL_CANASEND1(struct CANMBOXn_DATA *buf,Uint16 box)
{
Uint16 txMsgData[8];
// if ((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) != CAN_IF1CMD_BUSY && HWREGH(CANA_BASE + CAN_O_TXRQ_21) == 0) //
if ((HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) != CAN_IF1CMD_BUSY)
{
CAN_setupMessageObject(CANA_BASE, box, buf->u32MID.all,
CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
CAN_MSG_OBJ_NO_FLAGS, buf->Dlc);
txMsgData[0] = buf->Data_L.bit.Data_0;
txMsgData[1] = buf->Data_L.bit.Data_1;
txMsgData[2] = buf->Data_L.bit.Data_2;
txMsgData[3] = buf->Data_L.bit.Data_3;
txMsgData[4] = buf->Data_H.bit.Data_4;
txMsgData[5] = buf->Data_H.bit.Data_5;
txMsgData[6] = buf->Data_H.bit.Data_6;
txMsgData[7] = buf->Data_H.bit.Data_7;
CAN_sendMessage(CANA_BASE, box, buf->Dlc, txMsgData);
// CAN_sendMessage_updateDLC(CANA_BASE, box, len, txMsgData);
return 0; // 正常
} else {
return 1; // 错误
}
}
/*==============================================================================
* Function name: HAL_CANASEND
*
* Description:
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
void HAL_CANASEND(struct CANMBOXn_DATA *buf,Uint16 box)
{
// struct CAN_REGS CanaShadow;
// volatile struct CANMBOXn_DATA *txMessage;
// Uint32 txState = 0;
// Uint16 txMsgData[8];
//
//// if (buf == RT_NULL) {
//// return 0;
//// }
////
//// if (box >= RT_CANREG_MAX) {
//// return 0;
//// }
//
// txMessage = (volatile struct MBOX *)buf;
//
// txState = (HWREGH(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);//CAN_IF1CMD->Busy
//
// if (txState != CAN_IF1CMD_BUSY)
// {
// // Initialize the receive message object used for receiving CAN messages.
// // Possible flags: CAN_MSG_OBJ_NO_FLAGS, CAN_MSG_OBJ_USE_EXT_FILTER,
// // CAN_MSG_OBJ_USE_DIR_FILTER
// // Message Object Parameters:
// // CAN Module: A
// // Message Object ID Number: 1 (MBOX)
// // Message Identifier: txMessage->MSGID.all
// // Message Frame: Extended
// // Message Type: CAN_MSG_OBJ_TYPE_TX
// // Message ID Mask: 0
// // Message Object Flags: UMask, MXtd, MDir
// // Message Object flag CAN_MSG_OBJ_USE_ID_FILTER enables usage
// // of msgIDMask parameter for Message Identifier based filtering
// // Message Data Length: "Don't care" for a Receive mailbox 0x1F000000
// CAN_setupMessageObject(CANA_BASE, box, txMessage->u32MID.all,
// CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
// CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH);
//
// txMsgData[0] = txMessage->Data_L.bit.Data_0;
//
// txMsgData[1] = txMessage->Data_L.bit.Data_1;
// txMsgData[2] = txMessage->Data_L.bit.Data_2;
// txMsgData[3] = txMessage->Data_L.bit.Data_3;
//
// txMsgData[4] = txMessage->Data_H.bit.Data_4;
// txMsgData[5] = txMessage->Data_H.bit.Data_5;
// txMsgData[6] = txMessage->Data_H.bit.Data_6;
// txMsgData[7] = txMessage->Data_H.bit.Data_7;
//
//
// //
// CAN_sendMessage(CANA_BASE, box, MSG_DATA_LENGTH, txMsgData);
//
//// return MSG_DATA_LENGTH;
//
// } else {
//// return 0;
// }
}
/*==============================================================================
* Function name: HAL_CANRECV
*
* Description: 查询各个邮箱状态,将收到的数据存入接收缓存数组
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
Uint16 HAL_CANRECV(struct CANMBOXn_DATA *buf,Uint16 box)
{
volatile struct CANMBOXn_DATA *rxMessage;
struct CAN_REGS CanaShadow;
Uint16 rxMsgData[8]; // rx Buffer
Uint32 rxMsgID;//message ID
CAN_MsgFrameType frameType;//message ID frame
rxMessage = (struct CANMBOXn_DATA *)buf;
if (CAN_readMessageWithID(CANA_BASE, box, &frameType, &rxMsgID, rxMsgData))
{
rxMessage->u32MID.bit.ID = rxMsgID;
rxMessage->u32MID.bit.Xtd = frameType;
rxMessage->Dlc = (HWREGH(CANA_BASE + CAN_O_IF2MCTL) & CAN_IF2MCTL_DLC_M);
rxMessage->Data_L.bit.Data_0 = rxMsgData[0];
rxMessage->Data_L.bit.Data_1 = rxMsgData[1];
rxMessage->Data_L.bit.Data_2 = rxMsgData[2];
rxMessage->Data_L.bit.Data_3 = rxMsgData[3];
rxMessage->Data_H.bit.Data_4 = rxMsgData[4];
rxMessage->Data_H.bit.Data_5 = rxMsgData[5];
rxMessage->Data_H.bit.Data_6 = rxMsgData[6];
rxMessage->Data_H.bit.Data_7 = rxMsgData[7];
return 8;
}
else
{
return 0;
}
}
/*==============================================================================
* Function name: HAL_CANdatacopy
*
* Description: 查询各个邮箱状态,将收到的数据存入接收缓存数组
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
void HAL_CANdatacopy(struct CANMBOXn_DATA *CanMBOXn_Data, Uint16 *DataBuffer)
{
(*CanMBOXn_Data).Data_L.bit.Data_0 = DataBuffer[0];
(*CanMBOXn_Data).Data_L.bit.Data_1 = DataBuffer[1];
(*CanMBOXn_Data).Data_L.bit.Data_2 = DataBuffer[2];
(*CanMBOXn_Data).Data_L.bit.Data_3 = DataBuffer[3];
(*CanMBOXn_Data).Data_H.bit.Data_4 = DataBuffer[4];
(*CanMBOXn_Data).Data_H.bit.Data_5 = DataBuffer[5];
(*CanMBOXn_Data).Data_H.bit.Data_6 = DataBuffer[6];
(*CanMBOXn_Data).Data_H.bit.Data_7 = DataBuffer[7];
}
/*==============================================================================
* Function name: u16CanDataByteOperate_Read
*
* Description:
*
* Input:
*
* Output:
*
* Call:
*
* Called by:
*
* Author: wgs
*
* Data: 2025-10-23
*==============================================================================*/
Uint16 u16CanDataByteOperate_Read(struct CANMBOXn_DATA CanMBOXn_Data, Uint16 n)
{
Uint16 rxBuf[8]={0};
rxBuf[0] = CanMBOXn_Data.Data_L.bit.Data_0;
rxBuf[1] = CanMBOXn_Data.Data_L.bit.Data_1;
rxBuf[2] = CanMBOXn_Data.Data_L.bit.Data_2;
rxBuf[3] = CanMBOXn_Data.Data_L.bit.Data_3;
rxBuf[4] = CanMBOXn_Data.Data_H.bit.Data_4;
rxBuf[5] = CanMBOXn_Data.Data_H.bit.Data_5;
rxBuf[6] = CanMBOXn_Data.Data_H.bit.Data_6;
rxBuf[7] = CanMBOXn_Data.Data_H.bit.Data_7;
return (rxBuf[n]);
}
vEcanDrive_TxDataBufferProcess在mainLoop调用
发送时先试用vEcanDrive_Push2TxDataBuffer将数据放入缓冲区