CAN_back_to_back

这篇博客介绍了如何使用eCAN模块进行自检模式测试,通过内部传输数据并验证接收,无需实际CAN收发器。在自检模式下,错误会被标记,且内部处理所有确认信号。博客详细展示了初始化步骤,包括系统控制、GPIO配置、中断设置以及CAN邮箱的设定,最后进行数据传输和接收检查。
摘要由CSDN通过智能技术生成

本例通过连续高速传输数据来测试eCAN。验证接收到的数据。任何错误都会被标记。MBX0传输给MBX16, MBX1传输给MBX17,以此类推....

本例以CAN模块自检模式为例。即,传输/接收发生在模块内部(甚至所需的acknowledge也是在模块内部生成的)。因此,不需要一个CAN收发器来运行这个特定的测试用例,并且在CAN引脚/总线中看不到任何活动。因为一切都是内部的,不需要120欧姆的终端电阻。请注意,一个真实的CAN应用程序需要一个CAN收发器和终端电阻在总线的两端。

void main(void)
{
    Uint16  j;

//eCAN控制寄存器需要使用32位的读/写访问。因此,我们将为这个示例创建一组影子寄存器。这些影子寄存器将用于确保访问是32位而不是16位。
   struct ECAN_REGS ECanaShadow;

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();  // Skipped for this example

// For this example, configure CAN pins using GPIO regs here
// This function is found in DSP2803x_ECan.c
   InitECanaGpio();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2803x_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

//用指向shell中断服务例程(ISR)的指针初始化PIE向量表。
//这将填充整个表,即使在这个例子中没有使用中断。这对于调试非常有用。
// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_PieVect.c.
   InitPieVectTable();

// Step 4. Initialize all the Device Peripherals:
// Not required for this example

// Step 5. User specific code, enable interrupts:
    MessageReceivedCount = 0;
    ErrorCount = 0;
    PassCount = 0;

	InitECana(); // Initialize eCAN-A module

    // Mailboxes can be written to 16-bits or 32-bits at a time
    // Write to the MSGID field of TRANSMIT mailboxes MBOX0 - 15
    ECanaMboxes.MBOX0.MSGID.all = 0x9555AAA0;
    ECanaMboxes.MBOX1.MSGID.all = 0x9555AAA1;
    ECanaMboxes.MBOX2.MSGID.all = 0x9555AAA2;
    ECanaMboxes.MBOX3.MSGID.all = 0x9555AAA3;
    ECanaMboxes.MBOX4.MSGID.all = 0x9555AAA4;
    ECanaMboxes.MBOX5.MSGID.all = 0x9555AAA5;
    ECanaMboxes.MBOX6.MSGID.all = 0x9555AAA6;
    ECanaMboxes.MBOX7.MSGID.all = 0x9555AAA7;
    ECanaMboxes.MBOX8.MSGID.all = 0x9555AAA8;
    ECanaMboxes.MBOX9.MSGID.all = 0x9555AAA9;
    ECanaMboxes.MBOX10.MSGID.all = 0x9555AAAA;
    ECanaMboxes.MBOX11.MSGID.all = 0x9555AAAB;
    ECanaMboxes.MBOX12.MSGID.all = 0x9555AAAC;
    ECanaMboxes.MBOX13.MSGID.all = 0x9555AAAD;
    ECanaMboxes.MBOX14.MSGID.all = 0x9555AAAE;
    ECanaMboxes.MBOX15.MSGID.all = 0x9555AAAF;

    // Write to the MSGID field of RECEIVE mailboxes MBOX16 - 31
    ECanaMboxes.MBOX16.MSGID.all = 0x9555AAA0;
    ECanaMboxes.MBOX17.MSGID.all = 0x9555AAA1;
    ECanaMboxes.MBOX18.MSGID.all = 0x9555AAA2;
    ECanaMboxes.MBOX19.MSGID.all = 0x9555AAA3;
    ECanaMboxes.MBOX20.MSGID.all = 0x9555AAA4;
    ECanaMboxes.MBOX21.MSGID.all = 0x9555AAA5;
    ECanaMboxes.MBOX22.MSGID.all = 0x9555AAA6;
    ECanaMboxes.MBOX23.MSGID.all = 0x9555AAA7;
    ECanaMboxes.MBOX24.MSGID.all = 0x9555AAA8;
    ECanaMboxes.MBOX25.MSGID.all = 0x9555AAA9;
    ECanaMboxes.MBOX26.MSGID.all = 0x9555AAAA;
    ECanaMboxes.MBOX27.MSGID.all = 0x9555AAAB;
    ECanaMboxes.MBOX28.MSGID.all = 0x9555AAAC;
    ECanaMboxes.MBOX29.MSGID.all = 0x9555AAAD;
    ECanaMboxes.MBOX30.MSGID.all = 0x9555AAAE;
    ECanaMboxes.MBOX31.MSGID.all = 0x9555AAAF;

   //将邮箱0-15配置为Tx, 16-31配置为Rx,因为这个写入是对整个寄存器(而不是位域),所以不需要影子寄存器。

    // Enable all Mailboxes */
    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    ECanaRegs.CANME.all = 0xFFFFFFFF;

    // Specify that 8 bits will be sent/received
    ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX3.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX5.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX6.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX7.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX8.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX9.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX10.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX11.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX12.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX13.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX14.MSGCTRL.bit.DLC = 8;
    ECanaMboxes.MBOX15.MSGCTRL.bit.DLC = 8;

    // Write to the mailbox RAM field of MBOX0 - 15
    ECanaMboxes.MBOX0.MDL.all = 0x9555AAA0;
    ECanaMboxes.MBOX0.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX1.MDL.all = 0x9555AAA1;
    ECanaMboxes.MBOX1.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX2.MDL.all = 0x9555AAA2;
    ECanaMboxes.MBOX2.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX3.MDL.all = 0x9555AAA3;
    ECanaMboxes.MBOX3.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX4.MDL.all = 0x9555AAA4;
    ECanaMboxes.MBOX4.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX5.MDL.all = 0x9555AAA5;
    ECanaMboxes.MBOX5.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX6.MDL.all = 0x9555AAA6;
    ECanaMboxes.MBOX6.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX7.MDL.all = 0x9555AAA7;
    ECanaMboxes.MBOX7.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX8.MDL.all = 0x9555AAA8;
    ECanaMboxes.MBOX8.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX9.MDL.all = 0x9555AAA9;
    ECanaMboxes.MBOX9.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX10.MDL.all = 0x9555AAAA;
    ECanaMboxes.MBOX10.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX11.MDL.all = 0x9555AAAB;
    ECanaMboxes.MBOX11.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX12.MDL.all = 0x9555AAAC;
    ECanaMboxes.MBOX12.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX13.MDL.all = 0x9555AAAD;
    ECanaMboxes.MBOX13.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX14.MDL.all = 0x9555AAAE;
    ECanaMboxes.MBOX14.MDH.all = 0x89ABCDEF;

    ECanaMboxes.MBOX15.MDL.all = 0x9555AAAF;
    ECanaMboxes.MBOX15.MDH.all = 0x89ABCDEF;

    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    EALLOW;
    ECanaRegs.CANMIM.all = 0xFFFFFFFF;

    // Configure the eCAN for self test mode
    // Enable the enhanced features of the eCAN.
    EALLOW;
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.STM = 1;    // Configure CAN for self-test mode
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    EDIS;

    // Begin transmitting
    for(;;)
    {
       ECanaRegs.CANTRS.all = 0x0000FFFF;  // Set TRS for all transmit mailboxes
       while(ECanaRegs.CANTA.all != 0x0000FFFF ) {}  // Wait for all TAn bits to be set..
       ECanaRegs.CANTA.all = 0x0000FFFF;   // Clear all TAn
       MessageReceivedCount++;

       //Read from Receive mailboxes and begin checking for data */
       for(j=16; j<32; j++)         // Read & check 16 mailboxes
       {
          mailbox_read(j);         // This func reads the indicated mailbox data
          mailbox_check(TestMbox1,TestMbox2,TestMbox3); // Checks the received data
       }
    }
}

MSGID寄存器

 

 标识符扩展。IDE位的特性会随着AMI位的值而变化。
当AMI = 1时:
1. 
接收邮箱的IDE位是“不在乎”。
接收邮箱的IDE位被传输的消息的IDE位覆盖。
2. 
必须满足过滤条件才能接收消息。
3.
被比较的比特数是被传输消息的IDE位值的函数。
当AMI = 0时:
1. 
接收邮箱的IDE位决定要比较的位数。
2. 
过滤不适用。
msgid必须匹配位对位才能接收消息。
当AMI = 1时:
IDE = 1: RECEIVED消息具有扩展标识符
IDE = 0: RECEIVED消息有一个标准标识符
当AMI = 0时:
IDE = 1:待接收消息必须具有扩展标识符
IDE = 0:待接收消息必须有一个标准标识符。

接收掩码启用位。AME仅用于接收邮箱。自动回复(AAM[n]=1, CANMD[n]=0)邮箱不能设置,否则邮箱行为未定义。

这个位不会被消息接收修改。

1使用对应的接收掩码。

0没有使用接收掩码,所有标识符位必须匹配才能接收消息

自动应答模式位。此位仅对配置为传输的邮件邮箱有效。对于接收邮箱,此位没有作用:邮箱始终配置为正常接收操作。

这个位不会被消息接收修改。

1自动接听模式。如果接收到匹配的远程请求,CAN模块通过发送邮箱的内容来响应远程请求。

0正常发送模式。邮箱不回复远程请求。接收远程请求帧对消息邮箱没有影响。

 

消息标识符1在标准标识符模式下,如果IDE位(MSGID.31) = 0,则消息标识符存储在ID.28:18位中。在这种情况下,位ID.17:0没有意义。

在扩展标识模式下,如果IDE位(MSGID.31) = 1,则消息标识存储在ID.28:0位中。

CANMDL寄存器和CANMDH寄存器

 

邮箱的8个字节用来存储CAN消息的数据字段。DBO (MC.10)的设置决定了存储数据的顺序。数据从CAN总线传输或接收,从0字节开始。

•当DBO (MC.10) = 1时,数据存储或读取从CANMDL寄存器的最低有效字节开始,到CANMDH寄存器的最高有效字节结束。

•当DBO (MC.10) = 0时,数据存储或读取从CANMDL寄存器的最高有效字节开始,到CANMDH寄存器的最低有效字节结束。

只有配置邮箱n进行传输(CANMD[n] (CANMD.31-0)=0)或关闭邮箱(CANME[n] (CANME.31-0)=0),寄存器CANMDL(n)和CANMDH(n)才能写入。如果TRS[n] (TRS.31-0)=1,则寄存器CANMDL(n)和CANMDH(n)不能写入,除非CDR (MC.8)=1,且MBNR (MC.4-0)设置为n。这些设置也适用于应答模式(AAM (MSGID.29)=1)配置的消息对象。

CANMIM寄存器

 每个邮箱都有一个可用的中断标志。这可以是接收中断,也可以是传输中断,具体取决于邮箱的配置。该寄存器受EALLOW保护。

邮箱中断屏蔽。上电后,所有中断掩码位被清除,中断被禁用。这些位允许单独屏蔽任何邮箱中断。

1启用邮箱中断。如果消息已成功传输(对于发送邮箱),或者消息已接收而没有任何错误(对于接收邮箱),则会产生中断。

0邮箱中断被禁用。

       CANMC寄存器

 

自我测试模式。该位受EALLOW保护。

1 模块处于自检模式。在这种模式下,CAN模块产生自己的确认(ACK)信号,从而可以在没有总线连接模块的情况下进行操作。消息不发送,而是回读并存储在适当的邮箱中。收到的帧的MSGID不存储在STM的MBR中。

注意:在STM中,如果没有配置MBX接收传输的帧,那么该帧将被存储在MBX0中,即使MBX0没有配置接收操作。如果将lam配置为某些邮箱可以接收和存储数据帧,则将丢失不满足任何接收邮箱的接收掩码过滤条件的数据帧。

0 模块处于正常模式。

CANTRS寄存器 

 

当邮箱n准备传输时,CPU应该将TRS[n]位设置为1以启动传输。

这些位通常由CPU设置,并由CAN模块逻辑清除。CAN模块可以为远程帧请求设置这些位。当传输成功或中止时,这些位被重置。

如果将邮箱配置为接收邮箱,则CANTRS中对应的位将被忽略,除非接收邮箱配置为处理远程帧。如果设置了接收邮箱的TRS[n]位,则不会忽略接收邮箱的TRS[n]位。因此,设置了RTR的接收邮箱可以发送远端帧,只要设置了接收邮箱的TRS位。一旦远端帧被发送,TRS[n]位被CAN模块清除。因此,可以使用同一个邮箱从另一种模式请求数据帧。如果CPU尝试设置位,而eCAN模块尝试清除位,则该位被设置。

设置CANTRS[n]导致特定的消息n被发送。可以同时设置多个位。因此,所有设置了TRS位的消息依次传输,从拥有最高邮箱号(=最高优先级)的邮箱开始,除非TPL位另有规定。

CANTRS中的位是通过从CPU写入1来设置的。写一个0没有影响。上电后,所有位被清除。

1设置TRSn发送消息到该邮箱。可以同时设置几个比特位,并依次传送所有消息。

0没有操作

//这个函数读取邮箱号(MBXnbr)所指示的内容。
void mailbox_read(int16 MBXnbr)
{
   volatile struct MBOX *Mailbox;
   Mailbox = &ECanaMboxes.MBOX0 + MBXnbr;
   TestMbox1 = Mailbox->MDL.all; // = 0x9555AAAn (n is the MBX number)
   TestMbox2 = Mailbox->MDH.all; // = 0x89ABCDEF (a constant)
   TestMbox3 = Mailbox->MSGID.all;// = 0x9555AAAn (n is the MBX number)
} // MSGID of a rcv MBX is transmitted as the MDL data.
void mailbox_check(int32 T1, int32 T2, int32 T3)
{
    if((T1 != T3) || ( T2 != 0x89ABCDEF))
    {
       ErrorCount++;
    }
    else
    {
       PassCount++;
    }
}
void InitECanaGpio(void)
{
   EALLOW;

/* Enable internal pull-up for the selected CAN pins */
// Pull-ups can be enabled or disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.

    GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0;     // Enable pull-up for GPIO30 (CANRXA)
    GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0;     // Enable pull-up for GPIO31 (CANTXA)

/* Set qualification for selected CAN pins to asynch only */
// Inputs are synchronized to SYSCLKOUT by default.
// This will select asynch (no qualification) for the selected pins.

    GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3;   // Asynch qual for GPIO30 (CANRXA)

/* Configure eCAN-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be eCAN functional pins.

    GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1;    // Configure GPIO30 for CANRXA operation
    GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;    // Configure GPIO31 for CANTXA operation

    EDIS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值