您好,我最近在测试MPC5748G的CANFD功能,能实现它的发送以及接收中断功能,但是目前遇到的问题是,我无法使用block块1/2来进行发送数据,只能使用block0才能发送数据,如下是我的代码:
void FlexCAN0_Init(void)
{
uint32_t i = 0;
/* enable the FlexCAN module, reset and freeze */
CAN_0.MCR.R = (0
| CAN_MCR_FRZ /* enabled to enter Freeze mode */
| CAN_MCR_HALT /* enter freeze mode if FRZ bit is set */
//| CAN_MCR_SOFTRST /* soft reset */
//| CAN_MCR_SRXDIS /* self reception enabled */
| CAN_MCR_BCC /* individual Rx masking and queue */
| 0x0000001F);
/* double check that we are actually in freeze mode */
while(0 == CAN_0.MCR.B.FRZACK) {};
while(0 == CAN_0.MCR.B.NOTRDY) {};
CAN_0.MCR.R = (0
| CAN_MCR_FRZ /* enabled to enter Freeze mode */
| CAN_MCR_HALT /* enter freeze mode if FRZ bit is set */
/*| CAN_MCR_SRXDIS */ /* self reception enabled */
| CAN_MCR_BCC /* individual Rx masking and queue */
| CAN_MCR_AEN /* Safe Tx abort enable */
| CAN_MCR_FDEN /* CAN FD enabled */
| 0x0000001F); /* enable 32 MBs */
//CAN_0.CBT.R = 0x802D29AD; // Nominal bit time: 40 MHz clksrc, 500K bps with 40 tq
// EPRESDIV = 1, EPROPSEG = 10, EPSEG1 = 13, EPREG2 = 13
CAN_0.CBT.R = 0x80272A67; // bitrate=500kbps, CPI clk=40 MHz; Prescaler= 2, PROPSEG=11, PSEG1=20, PSEG2=8, RJW=8, smp=80%
CAN_0.FDCBT.R = 0x00111421; // bitrateFD=2000kbps, CPI clk=40 MHz; fPrescaler= 2, fPROPSEG=5, fPSEG1=2, fPSEG2=2, fRJW=2, smp=80%
//CAN_0.FDCBT.R = 0x00130862; // Data bit time: 40 MHz clksrc, 2Mbps with 10 tq
// FPRESDIV = 1, FPROPSEG = 2, FPSEG1 = 3, FPREG2 = 4
//CAN_0.FDCBT.R = 0x00330425;
CAN_0.FDCTRL.R = 0x8030000; // bit rate switching enable, 64byte payload for region 0
// CAN_0.FDCTRL.B.MBDSR1 = 3; // TCD disabled
/* clear MB are for first 32MBs */
for(i=0;i<(32*4);i++)
{
CAN_0.RAMn[i].R = 0;
}
/* set mask registers - all ID bits must match */
for(i=0;i<32;i++)
{
CAN_0.RXIMR[i].R = 0x1FFFFFFF;
}
CAN_0.CTRL2.R |= 0x1000; // set ISOCANFDEN bit 大端
/*enable interrupt for MB3*/
CAN_0.IMASK1.R = 0x00000004; //小端
/* Finally clear the HALT flag in MCR to enable the FlexCAN
* to synchronize with the CAN bus and allow
* participation in communication. */
CAN_0.MCR.B.HALT = 0;
/* wait until FlexCAN ready */
while(1 == CAN_0.MCR.B.FRZACK){};
while(1 == CAN_0.MCR.B.NOTRDY){};
}
/*******************************************************************************
Function Name : GetMBAddr
Engineer : Petr Stancik
Date : Jun-22-2021
Parameters : mb ... mb number used
Modifies : NONE
Returns : address of MB
Notes : get address of selected MB depending on payload set for memory block
memory block 0 is only checked
Issues : NONE
*******************************************************************************/
uint32_t GetMBAddr(uint32_t mb)
{
//根据payload有效载荷大小来计算出每个MB的地址长度,因为这个版本的库没有封装MB寄存器
//检查的MBDSR0位的有效载荷大小,这个位描述的是block 0 的有效载荷,如果要知道其他 block 的 MB就需要修改与的位,以及下方RAMn的积地址(修改RAMn是个人理解,还未实践过)
uint8_t payload_size = 1UL << (((CAN_0.FDCTRL.R & 0x30000U) >> 16U) + 3U); // R & 0x30000U get payload size for memory block 0
//根据上面的小算法按照有效载荷大小来计算MB地址长度,根据地址长度在基地址上进行偏移得到想要的MB寄存器的地址
//CAN_0.RAMn是每个元素占用4字节,384/96 = 4 ,定义的这个数组空间实际表示的是MB一共占用的内存大小
return ((uint32_t)&CAN_0.RAMn[0].R + (8+payload_size)*mb);
/* 如果要知道其他 block 下的 MB 地址,则需要根据 */
}
/*******************************************************************************
Function Name : TransmitMsgFD
Engineer : Petr Stancik
Date : Jun-22-2021
Parameters : mb ... mb number used
ext ... 0-standard ID, 1-extended ID
ID ... ID to be sent
length ... number of bytes to be sent
Modifies : NONE
Returns : NONE
Notes : Transmit message once using selected MB
Issues : NONE
*******************************************************************************/
void TransmitMsgFD(uint32_t mb, uint8_t ext, uint32_t ID, uint8_t length)
{
/* Assumption: Message buffer CODE is INACTIVE */
uint8_t i,dlc,z=0;
uint32_t *pTxMB = GetMBAddr(mb);
uint32_t txID = (ext==0) ? ID<<18 : ID;
/*calculate dlc value from no. bytes*/
if(length < 0x09)
{
dlc = length;
}else if(length < 0x0D){
dlc = 0x9;
}else if(length < 0x11){
dlc = 0xA;
}else if(length < 0x15){
dlc = 0xB;
}else if(length < 0x19){
dlc = 0xC;
}else if(length < 0x21){
dlc = 0xD;
}else if(length < 0x31){
dlc = 0xE;
}else{
dlc = 0xF;
}
*(pTxMB + 1) = txID; // write ID
for (i=0; i<length/4; i++,z+=4) {
*(pTxMB + 2 + i) = z<<24 | (z+1)<<16 | (z+2)<< 8 | z+3; /* Data to be transmitted */
}
*pTxMB = (0 // Tx Buffer 0 T0 word
| 1<<31 // extended Data Length
| 1<<30 // bit rate switch
| 0xC<<24 // code = 0xC, TX once
| 1<<22 // SRR = 1
| ext<<21 // IDE
| 0<<20 // RTR = 0
| dlc<<16); // DLC
while (!(CAN_0.IFLAG1.R & 1<<mb)) {}; /* Wait for CAN 0 MB 0 flag */
CAN_0.IFLAG1.R = 1<<mb; // clear MB flag
}
我个人理解的是,我将block0配置payload为64字节,因此只能使用0~6的MB,为了能使用block1,我将设置CAN_0.FDCTRL.R = 0x80180000; 是block1也为64字节有效载荷,除了更改这一部分还更改的部分有GetMBAddr中payload_size = 1UL << (((CAN_0.FDCTRL.R & 0x180000U) >> 16U) + 3U);使其能获得MB7~13的地址,但是我这么修改我无法发送出数据,程序会一直卡在while (!(CAN_0.IFLAG1.R & 1<<mb)) {};不知道是什么原因,我认为问题是出在GetMBAddr函数获取MB地址这一部分,对于这一部分我理解的不是很透彻,不知道要如何进行修改才能获取block1下MB的地址,使block1也能发送canfd数据