1. eCAN模块GPIO初始化
void InitECanbGpio(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 1;
GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;
GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3;
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2;
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2;
EDIS;
}
????使用到的寄存器如下所示: ????上拉输入的好处是减小了电流,输入的电平不会上下浮动而导致输入信号不稳定,在没有信号输入的情况下可以稳定在高电平。 总结:
- 使能接收引脚上拉,禁用发送引脚上拉;
- 设置接收引脚为异步模式;
- 设置GPIO引脚为CAN接收、输出引脚。
2. 初始化eCanb模块:InitEcanb
EALLOW;
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;
EDIS;
????涉及的寄存器如下:
EALLOW;
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.STM = 0;
ECanbShadow.CANMC.bit.SCB = 1;
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
EDIS;
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;
????接下来进行的是相关寄存器的置位工作,包括邮箱发送和接收相关、中断标志位置位,并请求对SCC模式下的CANBTC寄存器进行设置。
EALLOW;
ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
ECanbShadow.CANTA.all = 0xFFFFFFFF;
ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
ECanbShadow.CANRMP.all = ECanbRegs.CANRMP.all;
ECanbShadow.CANRMP.all = 0xFFFFFFFF;
ECanbRegs.CANRMP.all = ECanbShadow.CANRMP.all;
ECanbShadow.CANGIF0.all = ECanbRegs.CANGIF0.all;
ECanbShadow.CANGIF0.all = 0xFFFFFFFF;
ECanbRegs.CANGIF0.all = ECanbShadow.CANGIF0.all;
ECanbShadow.CANGIF1.all = ECanbRegs.CANGIF1.all;
ECanbShadow.CANGIF1.all = 0xFFFFFFFF;
ECanbRegs.CANGIF1.all = ECanbShadow.CANGIF1.all;
ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
ECanbShadow.CANMC.bit.CCR = 1 ;
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
????CANME寄存器的CCE为被置位后,可以进行波特率的设置了。
do
{ECanbShadow.CANES.all=ECanbRegs.CANES.all;}
while(ECanbShadow.CANES.bit.CCE != 1 ) ;
ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;
ECanbShadow.CANBTC.all = 0;
ECanbShadow.CANBTC.bit.BRPREG = 9;
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 ;
ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
do
{
ECanbShadow.CANES.all = ECanbRegs.CANES.all;
} while(ECanbShadow.CANES.bit.CCE != 0 );
????对邮箱的相应配置进行设置。
ECanbRegs.CANME.all = 0;
EDIS;
ECanbMboxes.MBOX0.MSGID.bit.IDE = 0;
...
ECanbMboxes.MBOX31.MSGID.bit.IDE = 0;
ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
...
ECanbMboxes.MBOX31.MSGCTRL.bit.DLC = 8;
ECanbMboxes.MBOX0.MSGCTRL.bit.TPL = 0;
...
ECanbMboxes.MBOX31.MSGCTRL.bit.TPL = 31;
ECanbMboxes.MBOX0.MSGCTRL.bit.RTR = 0;
...
ECanbMboxes.MBOX31.MSGCTRL.bit.RTR = 0;
EALLOW;
EALLOW;
ECanbRegs.CANMIM.all = 0xFFFFFFFE;
ECanbRegs.CANMIL.all = 0;
ECanbRegs.CANGIF0.all = 0xFFFFFFFF;
ECanbRegs.CANGIF1.all = 0xFFFFFFFF;
ECanbRegs.CANGIM.bit.I0EN = 1;
EDIS;
总结:
- 配置接收和发送引脚;
- 配置eCAN模块在eCAN模式;
- 邮箱控制寄存器全部置位,邮箱接收和发送相关标志位置位,请求设置波特率等数据;
- 设置波特率等数据;
- 对邮箱进行配置,如格式、数据长度、优先级等;
- 设置eCAN模块的中断。
3. 主程序
????先要对中断向量进行配置,这里要查看中断向量表,查看ECAN0INTB中断是在哪一条中断线上,又是这条中断线上的第几个中断向量。
EALLOW;
PieVectTable.TINT0 = &ISRTimer0;
PieVectTable.ECAN0INTB = &ISRCanb;
EDIS;
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
PieCtrlRegs.PIEIER1.bit.INTx5 = 1;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
IER |= M_INT9;
IER |= M_INT1;
IER |= M_INT14;
EINT;
ERTM;
????接下来要设置接收邮箱和发送邮箱。
MSGb_Init(0,0,0x0601);
MSGb_Init(1,1,0x0581);
MSGb_Init(2,0,0x0602);
MSGb_Init(3,1,0x0582);
MSGb_Init(4,0,0x0080);
MSGb_Init(5,0,0x0203);
MSGb_Init(6,0,0x0303);
MSGb_Init(7,0,0x0403);
MSGb_Init(8,1,0x0183);
MSGb_Init(9,1,0x0283);
MSGb_Init(10,1,0x0383);
MSGb_Init(11,1,0x0483);
MSGb_Init(12,0,0x0000);
MSGb_Init(13,0,0x0603);
????我们需要看一下MSGb_Init函数是怎么配置邮箱的。
void MSGb_Init(Uint16 msgnum,Uint16 dir,Uint32 id)
{
struct ECAN_REGS ECanbShadow;
switch (msgnum)
{
case 0:
ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
ECanbShadow.CANMD.bit.MD0 = dir;
ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;
if(dir==1)
{
ECanbMboxes.MBOX0.MSGID.bit.AME=1;
}
ECanbMboxes.MBOX0.MSGID.all = (id << 18);
ECanbShadow.CANME.all = ECanbRegs.CANME.all;
ECanbShadow.CANME.bit.ME0 = 1;
ECanbRegs.CANME.all = ECanbShadow.CANME.all;
break;
......
????当我们定义的接收邮箱收到信息后,就会触发邮箱中断,转而去执行中断子程序,中断路线如下。 ????根据之前的初始化工作,我们知道当邮箱1或邮箱3收到信息后,就会将其RMP为置1,即触发中断邮箱接收中断,同时若CANMIM和CANMIL寄存器对应位都被使能,则会通过CANGIM寄存器将所有中断映射到ECAN0INT中断线上。
4. 中断服务子程序
interrupt void ISRCanb(void)
{
switch(ECanbRegs.CANRMP.all)
{
......
case 0x00000002:
ECanbRegs.CANRMP.all=0xffffffff;
L[1] = ECanbMboxes.MBOX1.MDL.all;
H[1] = ECanbMboxes.MBOX1.MDH.all;
if(L[1] == 0x436C6000)
{
HisBuffer_v1[0] = 0x05;
HisBuffer_v1[1] = 0x81;
HisBuffer_v1[2] = (L[1] >> 24) & 0xff;
HisBuffer_v1[3] = (L[1] >> 16) & 0xff;
HisBuffer_v1[4] = (L[1] >> 8) & 0xff;
HisBuffer_v1[5] = L[1] & 0xff;
HisBuffer_v1[6] = H[1] & 0xff;
HisBuffer_v1[7] = (H[1] >> 8) & 0xff;
HisBuffer_v1[8] = (H[1] >> 16) & 0xff;
HisBuffer_v1[9] = (H[1] >> 24) & 0xff;
flag_send_v1 = 1;
}
break;
case 0x00000004:
ECanbRegs.CANRMP.all=0xffffffff;
L[2] = ECanbMboxes.MBOX2.MDL.all;
H[2]= ECanbMboxes.MBOX2.MDH.all;
break;
case 0x00000008:
ECanbRegs.CANRMP.all=0xffffffff;
L[3] = ECanbMboxes.MBOX3.MDL.all;
H[3] = ECanbMboxes.MBOX3.MDH.all;
if(L[3] == 0x436C6000)
{
HisBuffer_v2[0] = 0x05;
HisBuffer_v2[1] = 0x82;
HisBuffer_v2[2] = (L[3] >> 24) & 0xff;
HisBuffer_v2[3] = (L[3] >> 16) & 0xff;
HisBuffer_v2[4] = (L[3] >> 8) & 0xff;
HisBuffer_v2[5] = L[3] & 0xff;
HisBuffer_v2[6] = H[3] & 0xff;
HisBuffer_v2[7] = (H[3] >> 8) & 0xff;
HisBuffer_v2[8] = (H[3] >> 16) & 0xff;
HisBuffer_v2[9] = (H[3] >> 24) & 0xff;
flag_send_v2 = 1;
}
break;
......
????由程序可以发现,当任意RMP位被置位后,就会进入中断,而我们使能的接收邮箱是邮箱1和邮箱3,那么其对应RMP位被置位,就会进入对应的程序段。我们所要做的是将接收到的数据重新进行处理,写入数组HisBuffer中,然后将以太网发送标志置1,再通过以太网发送出去。以太网通信是后续我们需要讨论的了。
|