一、概述
在嵌入式系统中,CAN(控制器局域网络)是一种常用的通信协议。然而,为了保证数据的稳定传输和处理效率,我们需要设计一种高效的CAN驱动程序。本文将介绍一种基于DSP28335的带缓存CAN驱动程序设计,该设计主要分为三层:CHAL层、BSP层和应用层。
- CHAL层:
CHAL层是CAN驱动的底层实现,主要负责CAN的读写操作。这一层直接与硬件交互,实现对CAN控制器的配置和数据的发送接收。通过精细的硬件控制,确保数据的准确传输。
- BSP层:
BSP层位于CHAL层之上,主要负责CAN数据的发送和接收处理。在这一层,我们设计了两个CAN数据帧缓存,分别用于存储待发送和已接收的数据。
BSP层包含一个周期调用函数,每隔200us调用一次。这个函数的主要任务是将发送缓存中的数据装入CAN控制器进行发送,并从CAN控制器读取接收到的数据放入接收缓存。值得注意的是,我们的设计中,CAN本身并不产生中断,而是通过周期调用函数来处理数据的发送和接收。
为了提高数据的发送和接收效率,我们在BSP层采用了2到3个缓冲箱来进行数据的发送和接收。这样可以在一定程度上并行处理数据,提高系统的吞吐量。
- 应用层:
应用层是最高层,主要负责处理接收缓存中的数据和将待发送的数据加入发送缓存。只要缓存大小设置得当,且数据的处理及时,就可以保证CAN数据不会丢帧,同时也不需要频繁进入中断,从而保持CPU运行的节拍稳定。
二、关键代码
以下是一个简易的canopen master 帧过滤的程序 ,工程采用面向对象思想,模仿C++的类编写程序,关键初始化程序,应用程序通过回调调用 gCanFunc.TxData, gCanFunc.RxData这两个收发接口处理数据,原工程是一个控制伺服驱动的demo程序,伺服驱动器是标准的canopen协议。后续可将工程绑定在资源。
gBSP.Create();
gBSP.cpu->Init(150000000);
gCanFunc.Init(500);
200us 中断及时处理can数据,应用层可以1ms或者几ms调用一次,根据实际工程情况和需求。
interrupt void cpu_timer2_isr(void)
{
gCanFunc.Period();
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
CHAL层驱动代码:
#include "CHAL.h" // DSP2833x Examples Include File
#include "TMS320F28335/DSP2833x_Device.h" // DSP2833x Headerfile Include File
void InitECana(uint32_t baudRate)
{
//
// Create a shadow register structure for the CAN control registers. This
// is needed, since only 32-bit access is allowed to these registers.
// 16-bit access to these registers could potentially corrupt the register
// contents or return false data. This is especially true while writing
// to/reading from a bit (or group of bits) among bits 16 - 31
//
struct ECAN_REGS ECanaShadow;
EALLOW; // EALLOW enables access to protected bits
SysCtrlRegs.PCLKCR0.bit.ECANAENCLK = 1; // eCAN-A
//
// Configure eCAN RX and TX pins for CAN operation using eCAN regs
//
ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
ECanaShadow.CANOPC.all = ECanaRegs.CANOPC.all;
ECanaShadow.CANTIOC.bit.TXFUNC = 1;
ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;
ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
ECanaShadow.CANRIOC.bit.RXFUNC = 1;
ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
//
// Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31)
// HECC mode also enables time-stamping feature
//
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.SCB = 1;
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
//
// Initialize all bits of 'Master Control Field' to zero
// Some bits of MSGCTRL register come up in an unknown state. For proper
// operation, all bits (including reserved bits) of MSGCTRL must be
// initialized to zero
//
ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;
//
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
// as a matter of precaution.
//
ECanaRegs.CANTA.all = 0xFFFFFFFF; // Clear all TAn bits
ECanaRegs.CANRMP.all = 0xFFFFFFFF; // Clear all RMPn bits
ECanaRegs.CANGIF0.all = 0xFFFFFFFF; // Clear all interrupt flag bits
ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
//
// Configure bit timing parameters for eCANA
//
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 1; // Set CCR = 1
ECanaShadow.CANMC.bit.DBO = 1; // DATA order
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while (ECanaShadow.CANES.bit.CCE != 1); // Wait for CCE bit to be set
ECanaShadow.CANBTC.all = 0;
//
// CPU_FRQ_150MHz is defined in DSP2833x_Examples.h
//
//
// The following block for all 150 MHz SYSCLKOUT
// (75 MHz CAN clock) - default. Bit rate = 1 Mbps See Note at End of File
//
ECanaShadow.CANBTC.bit.BRPREG = (SYS_MAIN_FREQ / (30 * baudRate)) - 1;
ECanaShadow.CANBTC.bit.TSEG2REG = 2;
ECanaShadow.CANBTC.bit.TSEG1REG = 10;
ECanaShadow.CANBTC.bit.SAM = 1;
ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 0; // Set CCR = 0
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while (ECanaShadow.CANES.bit.CCE != 0); // Wait for CCE bit to be cleared
//
// Disable all Mailboxes
//
ECanaRegs.CANME.all = 0; // Required before writing the MSGIDs
/* 设置接收寄存器 0,1,2 接收*/
// struct ECAN_REGS ECanaShadow;
ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
ECanaShadow.CANME.all = ECanaRegs.CANME.all;
ECanaShadow.CANOPC.bit.OPC0 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanaShadow.CANOPC.bit.OPC1 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanaShadow.CANOPC.bit.OPC2 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanaShadow.CANME.bit.ME0 = 0; /* Enable Mailbox under test */
ECanaMboxes.MBOX0.MSGID.all = 0; // Set ID
ECanaMboxes.MBOX0.MSGID.bit.AME = 1; // Set ID
ECanaShadow.CANMD.bit.MD0 = 1; /* Configure Mailbox Rx */
ECanaShadow.CANME.bit.ME0 = 1; /* Enable Mailbox under test */
ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanaMboxes.MBOX0.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanaMboxes.MBOX0.MDH.all = 0x55555555;
ECanaLAMRegs.LAM0.bit.LAMI = 1;
ECanaLAMRegs.LAM0.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanaLAMRegs.LAM0.bit.LAM_L = 0x0;
ECanaShadow.CANME.bit.ME1 = 0; /* Enable Mailbox under test */
ECanaMboxes.MBOX1.MSGID.all = 0; // Set ID
ECanaMboxes.MBOX1.MSGID.bit.AME = 1; // Set ID
ECanaShadow.CANMD.bit.MD1 = 1; /* Configure Mailbox Rx */
ECanaShadow.CANME.bit.ME1 = 1; /* Enable Mailbox under test */
ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanaMboxes.MBOX1.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanaMboxes.MBOX1.MDH.all = 0x55555555;
ECanaLAMRegs.LAM1.bit.LAMI = 1;
ECanaLAMRegs.LAM1.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanaLAMRegs.LAM1.bit.LAM_L = 0x0;
ECanaShadow.CANME.bit.ME2 = 0; /* Enable Mailbox under test */
ECanaMboxes.MBOX2.MSGID.all = 0; // Set ID
ECanaMboxes.MBOX2.MSGID.bit.AME = 1; // Set ID
ECanaShadow.CANMD.bit.MD2 = 1; /* Configure Mailbox Rx */
ECanaShadow.CANME.bit.ME2 = 1; /* Enable Mailbox under test */
ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanaMboxes.MBOX2.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanaMboxes.MBOX2.MDH.all = 0x55555555;
ECanaLAMRegs.LAM2.bit.LAMI = 1;
ECanaLAMRegs.LAM2.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanaLAMRegs.LAM2.bit.LAM_L = 0x0;
ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;
ECanaRegs.CANME.all = ECanaShadow.CANME.all;
ECanaRegs.CANOPC.all = ECanaShadow.CANOPC.all;
EDIS;
}
void InitECanb(uint32_t baudRate)
{
//
// Create a shadow register structure for the CAN control registers. This
// is needed, since only 32-bit access is allowed to these registers.
// 16-bit access to these registers could potentially corrupt the register
// contents or return false data. This is especially true while writing
// to/reading from a bit (or group of bits) among bits 16 - 31
//
struct ECAN_REGS ECanbShadow;
EALLOW; // EALLOW enables access to protected bits
SysCtrlRegs.PCLKCR0.bit.ECANBENCLK = 1; // eCAN-B
//
// Configure eCAN RX and TX pins for CAN operation using eCAN regs
//
ECanbShadow.CANTIOC.all = ECanbRegs.CANTIOC.all;
ECanbShadow.CANTIOC.bit.TXFUNC = 1;
ECanbRegs.CANTIOC.all = ECanbShadow.CANTIOC.all;
ECanbShadow.CANRIOC.all = ECanbRegs.CANRIOC.all;
ECanbShadow.CANRIOC.bit.RXFUNC = 1;
ECanbRegs.CANRIOC.all = ECanbShadow.CANRIOC.all;
//
// Configure eCAN for HECC mode - (read to access mailboxes 16 thru 31)
//
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.SCB = 1;
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
//
// Initialize all bits of 'Master Control Field' to zero
// Some bits of MSGCTRL register come up in an unknown state. For proper
// operation, all bits (including reserved bits) of MSGCTRL must be
// initialized to zero
//
ECanbMboxes.MBOX0.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX1.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX2.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX3.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX4.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX5.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX6.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX7.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX8.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX9.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX10.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX11.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX12.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX13.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX14.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX15.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX16.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX17.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX18.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX19.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX20.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX21.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX22.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX23.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX24.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX25.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX26.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX27.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX28.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX29.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX30.MSGCTRL.all = 0x00000000;
ECanbMboxes.MBOX31.MSGCTRL.all = 0x00000000;
//
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
// as a matter of precaution.
//
ECanbRegs.CANTA.all = 0xFFFFFFFF; // Clear all TAn bits
ECanbRegs.CANRMP.all = 0xFFFFFFFF; // Clear all RMPn bits
ECanbRegs.CANGIF0.all = 0xFFFFFFFF; // Clear all interrupt flag bits
ECanbRegs.CANGIF1.all = 0xFFFFFFFF;
//
// Configure bit timing parameters for eCANB
//
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.CCR = 1; // Set CCR = 1
ECanbShadow.CANMC.bit.DBO = 1; // DATA order
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
ECanbShadow.CANES.all = ECanbRegs.CANES.all;
do
{
ECanbShadow.CANES.all = ECanbRegs.CANES.all;
} while (ECanbShadow.CANES.bit.CCE != 1); // Wait for CCE bit to be cleared
ECanbShadow.CANBTC.all = 0;
//
// CPU_FRQ_150MHz is defined in DSP2833x_Examples.h
//
//
// The following block for all 150 MHz SYSCLKOUT
// (75 MHz CAN clock) - default. Bit rate = 1 Mbps See Note at end of file
//
ECanbShadow.CANBTC.bit.BRPREG = (SYS_MAIN_FREQ / (30 * baudRate)) - 1;
ECanbShadow.CANBTC.bit.TSEG2REG = 2;
ECanbShadow.CANBTC.bit.TSEG1REG = 10;
ECanbShadow.CANBTC.bit.SAM = 1;
ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.CCR = 0; // Set CCR = 0
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
ECanbShadow.CANES.all = ECanbRegs.CANES.all;
do
{
ECanbShadow.CANES.all = ECanbRegs.CANES.all;
} while (ECanbShadow.CANES.bit.CCE != 0); // Wait for CCE bit to be cleared
//
// Disable all Mailboxes
//
ECanbRegs.CANME.all = 0; // Required before writing the MSGIDs
/* 设置接收寄存器 0,1,2 接收*/
// struct ECAN_REGS ECanbShadow;
ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
ECanbShadow.CANME.all = ECanbRegs.CANME.all;
ECanbShadow.CANOPC.bit.OPC0 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanbShadow.CANOPC.bit.OPC1 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanbShadow.CANOPC.bit.OPC2 = 1; // 读前原数据不可被覆盖 需要被读出后再接收新的数据
ECanbShadow.CANME.bit.ME0 = 0; /* Enable Mailbox under test */
ECanbMboxes.MBOX0.MSGID.all = 0; // Set ID
ECanbMboxes.MBOX0.MSGID.bit.AME = 1; // Set ID
ECanbShadow.CANMD.bit.MD0 = 1; /* Configure Mailbox Rx */
ECanbShadow.CANME.bit.ME0 = 1; /* Enable Mailbox under test */
ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanbMboxes.MBOX0.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanbMboxes.MBOX0.MDH.all = 0x55555555;
ECanbLAMRegs.LAM0.bit.LAMI = 1;
ECanbLAMRegs.LAM0.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanbLAMRegs.LAM0.bit.LAM_L = 0x0;
ECanbShadow.CANME.bit.ME1 = 0; /* Enable Mailbox under test */
ECanbMboxes.MBOX1.MSGID.all = 0; // Set ID
ECanbMboxes.MBOX1.MSGID.bit.AME = 1; // Set ID
ECanbShadow.CANMD.bit.MD1 = 1; /* Configure Mailbox Rx */
ECanbShadow.CANME.bit.ME1 = 1; /* Enable Mailbox under test */
ECanbMboxes.MBOX1.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanbMboxes.MBOX1.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanbMboxes.MBOX1.MDH.all = 0x55555555;
ECanbLAMRegs.LAM1.bit.LAMI = 1;
ECanbLAMRegs.LAM1.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanbLAMRegs.LAM1.bit.LAM_L = 0x0;
ECanbShadow.CANME.bit.ME2 = 0; /* Enable Mailbox under test */
ECanbMboxes.MBOX2.MSGID.all = 0; // Set ID
ECanbMboxes.MBOX2.MSGID.bit.AME = 1; // Set ID
ECanbShadow.CANMD.bit.MD2 = 1; /* Configure Mailbox Rx */
ECanbShadow.CANME.bit.ME2 = 1; /* Enable Mailbox under test */
ECanbMboxes.MBOX2.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanbMboxes.MBOX2.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanbMboxes.MBOX2.MDH.all = 0x55555555;
ECanbLAMRegs.LAM2.bit.LAMI = 1;
ECanbLAMRegs.LAM2.bit.LAM_H = 0x1fff; //屏蔽位 接收所有标准帧
ECanbLAMRegs.LAM2.bit.LAM_L = 0x0;
ECanbShadow.CANME.bit.ME16 = 0; /* Enable Mailbox under test */
ECanbMboxes.MBOX16.MSGID.all = 0; // Set ID
ECanbShadow.CANMD.bit.MD16 = 0; /* Configure Mailbox Rx */
ECanbShadow.CANME.bit.ME16 = 1;
ECanbMboxes.MBOX16.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanbMboxes.MBOX16.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanbMboxes.MBOX16.MDH.all = 0x55555555;
ECanbShadow.CANME.bit.ME17 = 0; /* Enable Mailbox under test */
ECanbMboxes.MBOX17.MSGID.all = 0; // Set ID
ECanbShadow.CANMD.bit.MD17 = 0; /* Configure Mailbox Rx */
ECanbShadow.CANME.bit.ME17 = 1;
ECanbMboxes.MBOX17.MSGCTRL.bit.DLC = 8; /* Write to DLC field in Master Control reg */
ECanbMboxes.MBOX17.MDL.all = 0x55555555; /* Write to the mailbox RAM field */
ECanbMboxes.MBOX17.MDH.all = 0x55555555;
ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
ECanbRegs.CANOPC.all = ECanbShadow.CANOPC.all;
EDIS;
}
uint8_t CHAL_Can0Rx(stc_can_rx_frame_t *canMsg)
{
uint8_t ret = 0;
static uint32_t times = 0;
uint32_t redata[2];
struct ECAN_REGS ECanaShadow;
ECanaShadow.CANRMP.all = ECanaRegs.CANRMP.all;
ECanaShadow.CANRML.all = ECanaRegs.CANRML.all;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
if (ECanaShadow.CANMC.bit.CCR == 1) //瑙e喅ecan busoff 闂
{
times++;
if (times > 7000) // /7 绾�1s
{
times = 0;
EALLOW;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 0; // Set CCR = 0
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
EDIS;
}
}
if (ECanaShadow.CANRMP.bit.RMP2)
{
canMsg->au32Data[0] = ECanaMboxes.MBOX2.MDL.all;
canMsg->au32Data[1] = ECanaMboxes.MBOX2.MDH.all;
canMsg->u32Ctrl = ECanaMboxes.MBOX2.MSGCTRL.all;
canMsg->u32ID = (ECanaMboxes.MBOX2.MSGID.all >> 18) & 0x7ff;
ECanaShadow.CANRMP.all = 0;
ECanaShadow.CANRMP.bit.RMP2 = 1; // clear the flag
ret = 1;
}
else if (ECanaShadow.CANRMP.bit.RMP1)
{
canMsg->au32Data[0] = ECanaMboxes.MBOX1.MDL.all;
canMsg->au32Data[1] = ECanaMboxes.MBOX1.MDH.all;
canMsg->u32Ctrl = ECanaMboxes.MBOX1.MSGCTRL.all;
canMsg->u32ID = (ECanaMboxes.MBOX1.MSGID.all >> 18) & 0x7ff;
ECanaShadow.CANRMP.all = 0;
ECanaShadow.CANRMP.bit.RMP1 = 1; // clear the flag
ret = 1;
}
else if (ECanaShadow.CANRMP.bit.RMP0)
{
canMsg->au32Data[0] = ECanaMboxes.MBOX0.MDL.all;
canMsg->au32Data[1] = ECanaMboxes.MBOX0.MDH.all;
canMsg->u32Ctrl = ECanaMboxes.MBOX0.MSGCTRL.all;
canMsg->u32ID = (ECanaMboxes.MBOX0.MSGID.all >> 18) & 0x7ff;
ECanaShadow.CANRMP.all = 0;
ECanaShadow.CANRMP.bit.RMP0 = 1; // clear the flag
ret = 1;
}
if (ret)
{
ECanaRegs.CANRMP.all = ECanaShadow.CANRMP.all;
}
return ret;
}
/* ret 0: 发送失败 1: 发送成功 */
uint8_t CHAL_Can0Tx(stc_can_tx_frame_t *canMsg)
{
uint8_t ret = 0;
struct ECAN_REGS ECanaShadow;
ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
ECanaShadow.CANTRS.all = ECanaRegs.CANTRS.all;
ECanaShadow.CANME.all = ECanaRegs.CANME.all;
ECanaShadow.CANTA.all = 0;
if (ECanaShadow.CANTRS.bit.TRS16 == 0)
{
ECanaShadow.CANME.bit.ME16 = 0; /* Enable Mailbox under test */
ECanaRegs.CANME.all = ECanaShadow.CANME.all;
ECanaMboxes.MBOX16.MSGID.all = canMsg->u32ID << 18;
ECanaMboxes.MBOX16.MDL.all = canMsg->au32Data[0];
ECanaMboxes.MBOX16.MDH.all = canMsg->au32Data[1];
ECanaMboxes.MBOX16.MSGCTRL.bit.DLC = canMsg->DLC;
ECanaShadow.CANTRS.bit.TRS16 = 1; // Set TRS for mailbox under test
ECanaShadow.CANTA.bit.TA16 = 1;
ECanaShadow.CANME.bit.ME16 = 1; /* Enable Mailbox under test */
ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;
ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;
ECanaRegs.CANME.all = ECanaShadow.CANME.all;
ret = 1;
}
else if (ECanaShadow.CANTRS.bit.TRS17 == 0)
{
ECanaShadow.CANME.bit.ME17 = 0; /* Enable Mailbox under test */
ECanaRegs.CANME.all = ECanaShadow.CANME.all;
ECanaMboxes.MBOX17.MSGID.all = canMsg->u32ID << 18;
ECanaMboxes.MBOX17.MDL.all = canMsg->au32Data[0];
ECanaMboxes.MBOX17.MDH.all = canMsg->au32Data[1];
ECanaMboxes.MBOX17.MSGCTRL.bit.DLC = canMsg->DLC;
ECanaMboxes.MBOX17.MSGID.all = canMsg->u32ID << 18;
ECanaShadow.CANTRS.bit.TRS17 = 1; // Set TRS for mailbox under test
ECanaShadow.CANTA.bit.TA17 = 1;
ECanaShadow.CANME.bit.ME17 = 1; /* Enable Mailbox under test */
ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;
ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;
ECanaRegs.CANME.all = ECanaShadow.CANME.all;
ret = 1;
}
return ret;
}
uint8_t CHAL_Can1Rx(stc_can_rx_frame_t *canMsg)
{
uint8_t ret = 0;
static uint32_t times = 0;
uint32_t redata[2];
struct ECAN_REGS ECanbShadow;
ECanbShadow.CANRMP.all = ECanbRegs.CANRMP.all;
ECanbShadow.CANRML.all = ECanbRegs.CANRML.all;
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
if (ECanbShadow.CANMC.bit.CCR == 1) //瑙e喅ecan busoff 闂
{
times++;
if (times > 7000) // /7 绾�1s
{
times = 0;
EALLOW;
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.CCR = 0; // Set CCR = 0
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
EDIS;
}
}
if (ECanbShadow.CANRMP.bit.RMP2)
{
canMsg->au32Data[0] = ECanbMboxes.MBOX2.MDL.all;
canMsg->au32Data[1] = ECanbMboxes.MBOX2.MDH.all;
canMsg->u32Ctrl = ECanbMboxes.MBOX2.MSGCTRL.all;
canMsg->u32ID = (ECanbMboxes.MBOX2.MSGID.all >> 18) & 0x7ff;
ECanbShadow.CANRMP.all = 0;
ECanbShadow.CANRMP.bit.RMP2 = 1; // clear the flag
ret = 1;
}
else if (ECanbShadow.CANRMP.bit.RMP1)
{
canMsg->au32Data[0] = ECanbMboxes.MBOX1.MDL.all;
canMsg->au32Data[1] = ECanbMboxes.MBOX1.MDH.all;
canMsg->u32Ctrl = ECanbMboxes.MBOX1.MSGCTRL.all;
canMsg->u32ID = (ECanbMboxes.MBOX1.MSGID.all >> 18) & 0x7ff;
ECanbShadow.CANRMP.all = 0;
ECanbShadow.CANRMP.bit.RMP1 = 1; // clear the flag
ret = 1;
}
else if (ECanbShadow.CANRMP.bit.RMP0)
{
canMsg->au32Data[0] = ECanbMboxes.MBOX0.MDL.all;
canMsg->au32Data[1] = ECanbMboxes.MBOX0.MDH.all;
canMsg->u32Ctrl = ECanbMboxes.MBOX0.MSGCTRL.all;
canMsg->u32ID = (ECanbMboxes.MBOX0.MSGID.all >> 18) & 0x7ff;
ECanbShadow.CANRMP.all = 0;
ECanbShadow.CANRMP.bit.RMP0 = 1; // clear the flag
ret = 1;
}
if (ret)
{
ECanbRegs.CANRMP.all = ECanbShadow.CANRMP.all;
}
return ret;
}
/* ret 0: 发送失败 1: 发送成功 */
uint8_t CHAL_Can1Tx(stc_can_tx_frame_t *canMsg)
{
uint8_t ret = 0;
struct ECAN_REGS ECanbShadow;
ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
ECanbShadow.CANTRS.all = ECanbRegs.CANTRS.all;
ECanbShadow.CANME.all = ECanbRegs.CANME.all;
ECanbShadow.CANTA.all = 0;
if (ECanbShadow.CANTRS.bit.TRS16 == 0)
{
ECanbShadow.CANME.bit.ME16 = 0; /* Enable Mailbox under test */
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
ECanbMboxes.MBOX16.MSGID.all = canMsg->u32ID << 18;
ECanbMboxes.MBOX16.MDL.all = canMsg->au32Data[0];
ECanbMboxes.MBOX16.MDH.all = canMsg->au32Data[1];
ECanbMboxes.MBOX16.MSGCTRL.bit.DLC = canMsg->DLC;
ECanbShadow.CANTRS.bit.TRS16 = 1; // Set TRS for mailbox under test
ECanbShadow.CANTA.bit.TA16 = 1;
ECanbShadow.CANME.bit.ME16 = 1; /* Enable Mailbox under test */
ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;
ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
ret = 1;
}
else if (ECanbShadow.CANTRS.bit.TRS17 == 0)
{
ECanbShadow.CANME.bit.ME17 = 0; /* Enable Mailbox under test */
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
ECanbMboxes.MBOX17.MSGID.all = canMsg->u32ID << 18;
ECanbMboxes.MBOX17.MDL.all = canMsg->au32Data[0];
ECanbMboxes.MBOX17.MDH.all = canMsg->au32Data[1];
ECanbMboxes.MBOX17.MSGCTRL.bit.DLC = canMsg->DLC;
ECanbMboxes.MBOX17.MSGID.all = canMsg->u32ID << 18;
ECanbShadow.CANTRS.bit.TRS17 = 1; // Set TRS for mailbox under test
ECanbShadow.CANTA.bit.TA17 = 1;
ECanbShadow.CANME.bit.ME17 = 1; /* Enable Mailbox under test */
ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;
ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
ret = 1;
}
return ret;
}
uint8_t CHAL_Can1Init(char *HIVersion, uint32_t baudRate)
{
uint8_t ret;
InitECanb(baudRate);
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0; // Enable pull-up for GPIO30 (CANRXA)
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; // Enable pull-up for GPIO31 (CANTXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch qual for GPIO30 (CANRXA)
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2; // Configure GPIO30 for CANRXA operation
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2; // Configure GPIO31 for CANTXA operation
// GpioCtrlRegs.GPAPUD.bit.GPIO8 = 0; // Enable pull-up for GPIO30 (CANRXA)
// GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0; // Enable pull-up for GPIO31 (CANTXA)
// GpioCtrlRegs.GPAQSEL1.bit.GPIO10 =3; // Asynch qual for GPIO30 (CANRXA)
// GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 2; // Configure GPIO30 for CANRXA operation
// GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 2; // Configure GPIO31 for CANTXA operation
// GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0; // Enable pull-up for GPIO30 (CANRXA)
// GpioCtrlRegs.GPAPUD.bit.GPIO13 = 0; // Enable pull-up for GPIO31 (CANTXA)
// GpioCtrlRegs.GPAQSEL1.bit.GPIO10 =3; // Asynch qual for GPIO30 (CANRXA)
// GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 2; // Configure GPIO30 for CANRXA operation
// GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 2; // Configure GPIO31 for CANTXA operation
EDIS;
ret = 1;
return ret;
}
uint8_t CHAL_Can0Init(char *HIVersion, uint32_t baudRate)
{
uint8_t ret;
InitECana(baudRate);
EALLOW;
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0; // Enable pull-up for GPIO30 (CANRXA)
GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0; // Enable pull-up for GPIO31 (CANTXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3; // Asynch qual for GPIO30 (CANRXA)
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; // Configure GPIO30 for CANRXA operation
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; // Configure GPIO31 for CANTXA operation
EDIS;
EDIS;
ret = 1;
return ret;
}
BSP层代码:
#ifndef _MCAN0_H_
#define _MCAN0_H_
#include <MQueue.h>
#include "CHAL.h" //
//can数据缓存
#define CAN_BUF_LEN 20
#define M1_NODEID (0X01)
#define M2_NODEID (0X02)
#define M3_NODEID (0X03)
#define M4_NODEID (0X04)
/*修改 以下两个枚举时,必须一一对应 */
/* 需要接收的CAN帧数据 */
typedef enum
{
M1_TPDO1 = 0X180 + M1_NODEID,
M1_TPDO2 = 0X280 + M1_NODEID,
M1_TPDO3 = 0X380 + M1_NODEID,
M1_TPDO4 = 0X480 + M1_NODEID,
M1_TSDO = 0X580 + M1_NODEID,
M1_HEART = 0X700 + M1_NODEID,
M2_TPDO1 = 0X180 + M2_NODEID,
M2_TPDO2 = 0X280 + M2_NODEID,
M2_TPDO3 = 0X380 + M2_NODEID,
M2_TPDO4 = 0X480 + M2_NODEID,
M2_TSDO = 0X580 + M2_NODEID,
M2_HEART = 0X700 + M2_NODEID,
} CAN_ID;
/* 与以上枚举对应的 ID 通道 */
typedef enum
{
CH_M1_TPDO1 = 0,
CH_M1_TPDO2,
CH_M1_TPDO3,
CH_M1_TPDO4,
CH_M1_TSDO,
CH_M1_HEART,
CH_M2_TPDO1,
CH_M2_TPDO2,
CH_M2_TPDO3,
CH_M2_TPDO4,
CH_M2_TSDO,
CH_M2_HEART,
} CAN_ID_CH;
/* 标准帧格式数据 */
typedef struct
{
uint8_t dlc; //帧数据长度
uint32_t dword[2];
} CanData;
typedef struct
{
CanData rbuf[CAN_RX_CH_NUM][CAN_BUF_LEN];
struct MQueue rq[CAN_RX_CH_NUM];
stc_can_tx_frame_t txBuf[CAN_BUF_LEN];
struct MQueue tq;
} MCan_Prop;
typedef struct
{
void (*Init)(uint32_t baudRate_kHz);
uint8_t (*RxData)(int8_t ch,uint8_t *dlc, uint32_t *data);
uint8_t (*TxData)(uint32_t txId,uint8_t dlc, uint32_t *data);
void (*Period)(void);
} MCan_Func;
extern const MCan_Func gCanFunc;
#endif
#include "MCan0.h"
MCan_Prop gCan0;
uint8_t CHAL_Can0Init(char *HIVersion, uint32_t baudRate);
extern uint8_t CHAL_Can0Rx(stc_can_rx_frame_t *canMsg);
extern uint8_t CHAL_Can0Tx(stc_can_rx_frame_t *canMsg);
static void Init(uint32_t baudRate_kHz)
{
int i = 0;
// CHAL_Can0Init(baudRate_kHz * 1000, RxPeriod);
// // // CHAL_Can0RxIdSet(0 , 0 , 0 , 0x7FF); //stadnrd fram
// // CHAL_Can0RxIdSet(0, 1, 0, 0x10000000); // extend fram
// CHAL_Can0RxIdSetAll(0, 0x1FFFFFFF);
// F460_GPIOInitForLed();
CHAL_Can0Init("0",baudRate_kHz * 1000);
for (i = 0; i < CAN_RX_CH_NUM; i++)
{
MQueue(&gCan0.rq[i], CAN_BUF_LEN);
}
MQueue(&gCan0.tq, CAN_BUF_LEN);
}
static void canRxData(stc_can_rx_frame_t *rxMsg)
{
switch (rxMsg->u32ID)
{
case M1_TPDO1:
if (gCan0.rq[CH_M1_TPDO1].deepMax - gCan0.rq[CH_M1_TPDO1].deep)
{
memcpy(gCan0.rbuf[CH_M1_TPDO1][gCan0.rq[CH_M1_TPDO1].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_TPDO1][gCan0.rq[CH_M1_TPDO1].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_TPDO1].Add(&gCan0.rq[CH_M1_TPDO1]);
}
break;
case M1_TPDO2:
if (gCan0.rq[CH_M1_TPDO2].deepMax - gCan0.rq[CH_M1_TPDO2].deep)
{
memcpy(gCan0.rbuf[CH_M1_TPDO2][gCan0.rq[CH_M1_TPDO2].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_TPDO2][gCan0.rq[CH_M1_TPDO2].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_TPDO2].Add(&gCan0.rq[CH_M1_TPDO2]);
}
break;
case M1_TPDO3:
if (gCan0.rq[CH_M1_TPDO3].deepMax - gCan0.rq[CH_M1_TPDO3].deep)
{
memcpy(gCan0.rbuf[CH_M1_TPDO3][gCan0.rq[CH_M1_TPDO3].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_TPDO3][gCan0.rq[CH_M1_TPDO3].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_TPDO3].Add(&gCan0.rq[CH_M1_TPDO3]);
}
break;
case M1_TPDO4:
if (gCan0.rq[CH_M1_TPDO4].deepMax - gCan0.rq[CH_M1_TPDO4].deep)
{
memcpy(gCan0.rbuf[CH_M1_TPDO4][gCan0.rq[CH_M1_TPDO4].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_TPDO4][gCan0.rq[CH_M1_TPDO4].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_TPDO4].Add(&gCan0.rq[CH_M1_TPDO4]);
}
break;
case M1_TSDO:
if (gCan0.rq[CH_M1_TSDO].deepMax - gCan0.rq[CH_M1_TSDO].deep)
{
memcpy(gCan0.rbuf[CH_M1_TSDO][gCan0.rq[CH_M1_TSDO].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_TSDO][gCan0.rq[CH_M1_TSDO].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_TSDO].Add(&gCan0.rq[CH_M1_TSDO]);
}
break;
case M1_HEART:
if (gCan0.rq[CH_M1_HEART].deepMax - gCan0.rq[CH_M1_HEART].deep)
{
memcpy(gCan0.rbuf[CH_M1_HEART][gCan0.rq[CH_M1_HEART].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M1_HEART][gCan0.rq[CH_M1_HEART].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M1_HEART].Add(&gCan0.rq[CH_M1_HEART]);
}
break;
case M2_TPDO1:
if (gCan0.rq[CH_M2_TPDO1].deepMax - gCan0.rq[CH_M2_TPDO1].deep)
{
memcpy(gCan0.rbuf[CH_M2_TPDO1][gCan0.rq[CH_M2_TPDO1].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_TPDO1][gCan0.rq[CH_M2_TPDO1].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_TPDO1].Add(&gCan0.rq[CH_M2_TPDO1]);
}
break;
case M2_TPDO2:
if (gCan0.rq[CH_M2_TPDO2].deepMax - gCan0.rq[CH_M2_TPDO2].deep)
{
memcpy(gCan0.rbuf[CH_M2_TPDO2][gCan0.rq[CH_M2_TPDO2].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_TPDO2][gCan0.rq[CH_M2_TPDO2].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_TPDO2].Add(&gCan0.rq[CH_M2_TPDO2]);
}
break;
case M2_TPDO3:
if (gCan0.rq[CH_M2_TPDO3].deepMax - gCan0.rq[CH_M2_TPDO3].deep)
{
memcpy(gCan0.rbuf[CH_M2_TPDO3][gCan0.rq[CH_M2_TPDO3].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_TPDO3][gCan0.rq[CH_M2_TPDO3].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_TPDO3].Add(&gCan0.rq[CH_M2_TPDO3]);
}
break;
case M2_TPDO4:
if (gCan0.rq[CH_M2_TPDO4].deepMax - gCan0.rq[CH_M2_TPDO4].deep)
{
memcpy(gCan0.rbuf[CH_M2_TPDO4][gCan0.rq[CH_M2_TPDO4].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_TPDO4][gCan0.rq[CH_M2_TPDO4].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_TPDO4].Add(&gCan0.rq[CH_M2_TPDO4]);
}
break;
case M2_TSDO:
if (gCan0.rq[CH_M2_TSDO].deepMax - gCan0.rq[CH_M2_TSDO].deep)
{
memcpy(gCan0.rbuf[CH_M2_TSDO][gCan0.rq[CH_M2_TSDO].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_TSDO][gCan0.rq[CH_M2_TSDO].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_TSDO].Add(&gCan0.rq[CH_M2_TSDO]);
}
break;
case M2_HEART:
if (gCan0.rq[CH_M2_HEART].deepMax - gCan0.rq[CH_M2_HEART].deep)
{
memcpy(gCan0.rbuf[CH_M2_HEART][gCan0.rq[CH_M2_HEART].head].dword, &rxMsg->au32Data[0], sizeof(uint32_t[2]));
gCan0.rbuf[CH_M2_HEART][gCan0.rq[CH_M2_HEART].head].dlc = rxMsg->DLC;
gCan0.rq[CH_M2_HEART].Add(&gCan0.rq[CH_M2_HEART]);
}
break;
default: break;
}
}
// static uint8_t QueryData(uint16_t ch,uint8_t *dlc, uint32_t *data)
static uint8_t RxData(int8_t ch, uint8_t *dlc, uint32_t *data)
{
if ((ch > -1) && (gCan0.rq[ch].deep) > 0)
{
memcpy(data, gCan0.rbuf[ch][gCan0.rq[ch].tail].dword, sizeof(uint32_t[2]));
*dlc = gCan0.rbuf[ch][gCan0.rq[ch].tail].dlc;
gCan0.rq[ch].Del(&gCan0.rq[ch]); //队列删除
return 1;
}
else
{
return 0;
}
}
static uint8_t TxData(uint32_t txId, uint8_t dlc, uint32_t *data)
{
if (gCan0.tq.deepMax - gCan0.tq.deep)
{
// stc_can_tx_frame_t txMsg = {0};
gCan0.txBuf[gCan0.tq.head].DLC = dlc;
gCan0.txBuf[gCan0.tq.head].u32ID = txId;
gCan0.txBuf[gCan0.tq.head].au32Data[0] = data[0];
gCan0.txBuf[gCan0.tq.head].au32Data[1] = data[1];
gCan0.tq.Add(&gCan0.tq);
}
return 0;
}
static void Period(void)
{
// //Rx
stc_can_rx_frame_t rxMsg = {0};
if (CHAL_Can0Rx(&rxMsg))
{
canRxData(&rxMsg);
}
/* TX */
if (gCan0.tq.deep > 0)
{
CHAL_Can0Tx(&gCan0.txBuf[gCan0.tq.tail]);
gCan0.tq.Del(&gCan0.tq); //队列删除
}
//
}
//*
const MCan_Func gCanFunc=
{
.Init=Init,
.Period = Period,
.RxData = RxData,
.TxData = TxData,
};
三、总结
这种分层设计的带缓存DSP28335 CAN驱动程序,通过合理的缓存管理和周期性数据处理,能够在保证数据传输稳定性的同时,提高系统的运行效率。并且,由于避免了频繁的中断处理,使得CPU能够更专注于其他任务的执行,提升了整体系统的性能。在未来的设计和优化中,我们可以进一步细化各层的功能,以适应更复杂的应用场景。