上一篇将到了如何配置28335的发送寄存器,本篇讲如何配置CAN接受中断。
上一篇的链接:
28335 CAN 通讯寄存器配置标准步骤流程_追火青木的博客-CSDN博客
CAN接受中断配置,不可以盲目信任从网上copy过来的code,因为开发板硬件环境可能不同。举个例子,copy过来的code如果是ECanaRegs,但你的硬件CAN输出只是连接了一个对CAN输出GPIO,而该GPIO对应的是CANB,那无论你怎么配置都是错误的。
另外,需要注意的是,28335的CAN中断必须按照28335的手册进行配置,而不能随意配置。这点对于没有硬件编程经验的人可能会踩坑。举例如下,28335的中断分为32个中断源,其中留给用的专断有12个,每个又分为8组,因此共有96组外设级中断可供用户配置使能。但问题是虽然看似这么多,但其实芯片出厂时已经给你固定了96个能配置成什么样子。从28335手册中截图如下:
从上面手册可知,如果你自己的板子电路只使用了CANB,那接受中断就只能使用TNT9.7、或者INT9.8,配置为别的都会是错误的。关键代码如下:
PieVectTable.ECAN1INTB = &Ecana_isr1;//把中断入口函数写入中断向量表ECAN1INTB对应的中断上
PieCtrlRegs.PIEIER9.bit.INTx8 = 1; //CANB的中断1
上面红色字体都是关键点,需要格外注意,避免踩坑。
附配置接受CAN中断的代码:
static void CANB_RX_Config(void)
{
struct ECAN_REGS ECan_Reg_Shadow;
ECan_Reg_Shadow.CANME.all = ECanbRegs.CANME.all;
ECan_Reg_Shadow.CANME.bit.ME1 = 0;//不使能邮箱1
ECan_Reg_Shadow.CANME.bit.ME31 = 0;//不使能邮箱31
ECanbRegs.CANME.all = ECan_Reg_Shadow.CANME.all;
/*----------以下代码是配置接受邮箱的相关代码------------*/
//邮箱1相关配置
ECanbMboxes.MBOX1.MSGCTRL.bit.DLC = 8;//配置数据长度,应该是没意义的;
ECanbMboxes.MBOX1.MSGID.all = 0x0123C;//设置接收消息的有效ID
ECanbMboxes.MBOX1.MSGID.bit.AME =1;//屏蔽使能位,
ECanbMboxes.MBOX1.MSGID.bit.IDE = CAN_ID_EXT;
/*
LAM[28:0]
这些位启用一个进入消息的任意标识符位的屏蔽。
1 针对接受到的标识符的相应位, 接受一个 0 或 1( 无关) 。
0 接收到的标识符位值必须与 MSGID 寄存器的相应标识符位相匹配。
*/
ECanbLAMRegs.LAM1.all = 0x000000F;//
/*
LAMI 本地接受屏蔽标识符扩展位
1 可以接收标准和扩展帧。 在扩展帧的情况下, 标识符的所有 29 位被存储在邮箱中, 本地接受屏蔽寄
存器的所有 29 位被过滤器使用。 在一个标准帧的情况下, 只有标识符的头 11 个位( 28 至 18 位)
和本地接受屏蔽被使用。
0 存储在邮箱中的标识符扩展位决定了哪些消息应该被接收到
*/
ECanbLAMRegs.LAM1.bit.LAMI = 1;
//邮箱31相关配置
ECanbMboxes.MBOX31.MSGCTRL.bit.DLC = 8;//配置数据长度,应该是没意义的;
ECanbMboxes.MBOX31.MSGID.all = 0x07909ABC;//设置接收消息的有效ID
ECanbMboxes.MBOX31.MSGID.bit.AME =1;//屏蔽使能位,
ECanbMboxes.MBOX31.MSGID.bit.IDE = CAN_ID_EXT;
/*
LAM[28:0]
这些位启用一个进入消息的任意标识符位的屏蔽。
1 针对接受到的标识符的相应位, 接受一个 0 或 1( 无关) 。
0 接收到的标识符位值必须与 MSGID 寄存器的相应标识符位相匹配。
*/
ECanbLAMRegs.LAM31.all = 0x0000000;//
/*
LAMI 本地接受屏蔽标识符扩展位
1 可以接收标准和扩展帧。 在扩展帧的情况下, 标识符的所有 29 位被存储在邮箱中, 本地接受屏蔽寄
存器的所有 29 位被过滤器使用。 在一个标准帧的情况下, 只有标识符的头 11 个位( 28 至 18 位)
和本地接受屏蔽被使用。
0 存储在邮箱中的标识符扩展位决定了哪些消息应该被接收到
*/
ECanbLAMRegs.LAM31.bit.LAMI = 1;
ECanbRegs.CANRMP.all = 0xFFFFFFFF;
ECan_Reg_Shadow.CANMD.all = ECanbRegs.CANMD.all;
ECan_Reg_Shadow.CANMD.bit.MD1 = 1;
ECan_Reg_Shadow.CANMD.bit.MD31 = 1;
ECanbRegs.CANMD.all = ECan_Reg_Shadow.CANMD.all;
ECan_Reg_Shadow.CANME.all = ECanbRegs.CANME.all;
ECan_Reg_Shadow.CANME.bit.ME1 = 1;//使能邮箱1
ECan_Reg_Shadow.CANME.bit.ME31 = 1;//使能邮箱1
ECanbRegs.CANME.all = ECan_Reg_Shadow.CANME.all;
}
void CAN_Rx_IT_Concig(void)
{
EALLOW;
ECanbRegs.CANMIM.bit.MIM31 = 1;//使能中断邮箱31的中断;
ECanbRegs.CANMIL.bit.MIL31 = 1;//将中断31连接至中断1;
ECanbRegs.CANGIM.bit.I1EN = 1;//使能中断1;
EDIS;
}
//配置中断
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PieCtrlRegs.PIEIER9.bit.INTx8 = 1; //CANB的中断1
IER |= M_INT9;
IER |= M_INT1;
EINT;
// Enable Global interrupt INTM
ERTM;
__interrupt void Ecana_isr1(void)
{
DINT;
if(ECanbRegs.CANGIF1.bit.GMIF1 == 1)
{
if(ECanbRegs.CANRMP.bit.RMP31 == 1)
{
can_rx_msg.rx_update = UPDATE;
can_rx_msg.MBox_num = ECanbRegs.CANGIF1.bit.MIV1;
can_rx_msg.DLC = ECanbMboxes.MBOX31.MSGCTRL.bit.DLC;
can_rx_msg.IDE = ECanbMboxes.MBOX31.MSGID.bit.IDE;
if(can_rx_msg.IDE == CAN_ID_EXT)
{
can_rx_msg.ExtId = ECanbMboxes.MBOX31.MSGID.all&0x1FFFFFFF;
can_rx_msg.SAE_J1939_ID.id = can_rx_msg.ExtId;
}
else if(can_rx_msg.IDE == CAN_ID_STD)
{
can_rx_msg.StdId = ECanbMboxes.MBOX31.MSGID.bit.STDMSGID;
}
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte0 = ECanbMboxes.MBOX31.MDL.byte.BYTE0;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte1 = ECanbMboxes.MBOX31.MDL.byte.BYTE1;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte2 = ECanbMboxes.MBOX31.MDL.byte.BYTE2;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte3 = ECanbMboxes.MBOX31.MDL.byte.BYTE3;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte4 = ECanbMboxes.MBOX31.MDH.byte.BYTE4;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte5 = ECanbMboxes.MBOX31.MDH.byte.BYTE5;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte6 = ECanbMboxes.MBOX31.MDH.byte.BYTE6;
can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte7 = ECanbMboxes.MBOX31.MDH.byte.BYTE7;
ECanbRegs.CANRMP.bit.RMP31 = 1;
}
}
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
//ECanbRegs.CANGIF1.bit.GMIF1 = 1;
EINT;
}
以上代码实测可用,希望能帮到后来者。