send函数寄存器配置
{
struct ECAN_REGS ECan_Reg_Shadow;
//-------------------------
volatile struct ECAN_REGS *ECanReg;
volatile struct ECAN_MBOXES *ECanMboxe;
//时钟使能
if (CAN == CANA)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ECANAENCLK = 1;
EDIS;
ECanReg = &ECanaRegs;
ECanMboxe = &ECanaMboxes;
}
else if (CAN == CANB)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ECANBENCLK = 1;
EDIS;
ECanReg = &ECanbRegs;
ECanMboxe = &ECanbMboxes;
}
else
{
return;
}
#if 1
//引脚分配
EALLOW;
// EALLOW enables access to protected bits
ECan_Reg_Shadow.CANTIOC.all = ECanReg->CANTIOC.all;
ECan_Reg_Shadow.CANTIOC.bit.TXFUNC = 1;
ECanReg->CANTIOC.all = ECan_Reg_Shadow.CANTIOC.all;
ECan_Reg_Shadow.CANRIOC.all = ECanReg->CANRIOC.all;
ECan_Reg_Shadow.CANRIOC.bit.RXFUNC = 1;
ECanReg->CANRIOC.all = ECan_Reg_Shadow.CANRIOC.all;
EDIS;
ECanReg->CANME.all = 0; //禁用所有邮箱
ECanMboxe->MBOX0.MSGID.all = 0x1349; //设置一对邮箱的ID,保持一致
ECanMboxe->MBOX31.MSGID.all = 0x1349; //设置一对邮箱的ID,保持一致
#if 0
ECanMboxe->MBOX0.MSGID.all = 0x9555AAA0;
ECanMboxe->MBOX1.MSGID.all = 0x9555AAA1;
ECanMboxe->MBOX2.MSGID.all = 0x9555AAA2;
ECanMboxe->MBOX3.MSGID.all = 0x9555AAA3;
ECanMboxe->MBOX4.MSGID.all = 0x9555AAA4;
ECanMboxe->MBOX5.MSGID.all = 0x9555AAA5;
ECanMboxe->MBOX6.MSGID.all = 0x9555AAA6;
ECanMboxe->MBOX7.MSGID.all = 0x9555AAA7;
ECanMboxe->MBOX8.MSGID.all = 0x9555AAA8;
ECanMboxe->MBOX9.MSGID.all = 0x9555AAA9;
ECanMboxe->MBOX10.MSGID.all = 0x9555AAAA;
ECanMboxe->MBOX11.MSGID.all = 0x9555AAAB;
ECanMboxe->MBOX12.MSGID.all = 0x9555AAAC;
ECanMboxe->MBOX13.MSGID.all = 0x9555AAAD;
ECanMboxe->MBOX14.MSGID.all = 0x9555AAAE;
ECanMboxe->MBOX15.MSGID.all = 0x9555AAAF;
// Write to the MSGID field of RECEIVE mailboxes MBOX16 - 31
ECanMboxe->MBOX16.MSGID.all = 0x9555AAA0;
ECanMboxe->MBOX17.MSGID.all = 0x9555AAA1;
ECanMboxe->MBOX18.MSGID.all = 0x9555AAA2;
ECanMboxe->MBOX19.MSGID.all = 0x9555AAA3;
ECanMboxe->MBOX20.MSGID.all = 0x9555AAA4;
ECanMboxe->MBOX21.MSGID.all = 0x9555AAA5;
ECanMboxe->MBOX22.MSGID.all = 0x9555AAA6;
ECanMboxe->MBOX23.MSGID.all = 0x9555AAA7;
ECanMboxe->MBOX24.MSGID.all = 0x9555AAA8;
ECanMboxe->MBOX25.MSGID.all = 0x9555AAA9;
ECanMboxe->MBOX26.MSGID.all = 0x9555AAAA;
ECanMboxe->MBOX27.MSGID.all = 0x9555AAAB;
ECanMboxe->MBOX28.MSGID.all = 0x9555AAAC;
ECanMboxe->MBOX29.MSGID.all = 0x9555AAAD;
ECanMboxe->MBOX30.MSGID.all = 0x9555AAAE;
ECanMboxe->MBOX31.MSGID.all = 0x9555AAAF;
#endif
ECanReg->CANMD.all = 0xFFFF0000; //前16个是发送,后16个是收取
ECanReg->CANME.all = 0xFFFFFFFF; //使能所有邮箱
//RTR=1:远程帧
ECanMboxe->MBOX0.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX1.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX2.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX3.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX4.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX5.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX6.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX7.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX8.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX9.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX10.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX11.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX12.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX13.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX14.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX15.MSGCTRL.bit.RTR = 0;
ECanMboxe->MBOX31.MSGCTRL.bit.DLC = 8;
ECanMboxe->MBOX0.MSGCTRL.bit.DLC = 8; //配置长度
//把待发数据写入发送邮箱,暂空缺
/
ECan_Reg_Shadow.CANBTC.bit.BRPREG = 9;
ECan_Reg_Shadow.CANBTC.bit.TSEG2REG = 2;
ECan_Reg_Shadow.CANBTC.bit.TSEG1REG = 10;
#endif
ECan_Reg_Shadow.CANBTC.bit.SAM = 1;
ECanReg->CANBTC.all = ECan_Reg_Shadow.CANBTC.all;
ECan_Reg_Shadow.CANMC.all = ECanReg->CANMC.all;
ECan_Reg_Shadow.CANMC.bit.CCR = 0;
ECan_Reg_Shadow.CANMC.bit.ABO = 0; //识别到总线自动恢复
ECan_Reg_Shadow.CANMC.bit.SUSP = 1; //挂起模式下继续运行
ECanReg->CANMC.all = ECan_Reg_Shadow.CANMC.all;
EDIS;
//禁用寄存器更改权限
do
{
ECan_Reg_Shadow.CANES.all = ECanReg->CANES.all;
}
while (ECan_Reg_Shadow.CANES.bit.CCE != 0); //CCE被清零,表明CAN已经被配置成功
// HECC mode also enables time-stamping feature
//选择CAN工作模式工作于eCAN模式,32个邮箱都工作。
EALLOW;
ECan_Reg_Shadow.CANMC.all = ECanReg->CANMC.all;
ECan_Reg_Shadow.CANMC.bit.SCB = 1;
ECan_Reg_Shadow.CANMC.bit.STM = 0; //正常模式
ECanReg->CANMC.all = ECan_Reg_Shadow.CANMC.all;
EDIS;
}
Main()
{
ECanbRegs.CANTRS.all = 0x0000FFFF; // Set TRS for all transmit mailboxes
ECan_Reg_Shadow.CANTA.all = ECanbRegs.CANTA.all;
while (ECan_Reg_Shadow.CANTA.all != 0x0000FFFF)
{
ECan_Reg_Shadow.CANTA.all = ECanbRegs.CANTA.all;
} // Wait for all TAn bits to be set..
ECanbRegs.CANTA.all = 0x0000FFFF; // Clear all TAn
}
以上为在研旭开发板上实测可行的代码
注意点:
1、GPIO配置为CANTX和CANRX时是一一对应的,笔者在这里查找了好久才找到问题根源:举例,GPIO16和GPIO17只能配置为CANB收或者发,而不能配置为CANA的收发,CANA收发需要别的GPIO口来配置。这个要注意。如果你仅仅配置了CANA,那如果你用CANB去做收发,不论配置多准确,都无法通讯。
2、发送成功后TA寄存器就会变为1,再次写入1就清零了————这点和惯性思维不太一样。笔者遇到的问题是TA不置位1,也就是说没有发送成功。此类情况很多人都出现。问题原因很多:1、硬件环境没有搭建好,如CAN网络没有配置两个120欧姆电阻,或者CANH和CANL接反(万用表笔可以测量到);2、收发邮箱寄存器配置错误;3、没有使能邮箱;4、GPIO配置没有对应好;等等。不对寄存器有深入理解,不耗费点精力,很难解决问题。5、其它可能原因。
3、别忘记使能邮箱,ME寄存器负责使能;
4、收发邮箱的ID必须保持一致。举例:单片机邮箱1发送数据给PC,假如邮箱发送帧的ID是0x1234,PC响应数据给单片机,单片机收取数据邮箱如果是17,则邮箱17的ID号也必须是0x1234,否则收不到上位机的响应数据。换句话,如果你单片机只负责发送帧,则无需配置接受的邮箱,否则配对的接受邮箱ID需要和发送邮箱帧ID保持一致。
5、硬件环境需要保持两个120欧姆电阻串联在CAN网络中,严格来说一个120欧姆是在单片机(Slave)上,一个是在Master上,但直接放在一个地方也可以。
以上都是笔者走过的路,希望能给后来者一点帮助。



