This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28075:CAN#39;t 从 CANBUS 接收数据

Guru**** 2540720 points
Other Parts Discussed in Thread: ISO1050

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/800633/tms320f28075-can-t-receive-data-from-canbus

器件型号:TMS320F28075
主题中讨论的其他器件:ISO1050

大家好、我将使用 CAN 分析仪测试 CAN 模块。 F28075+ ISO1050连接到 CAN 分析仪。

我可以使用下面的代码将数据发送到 CAN 分析仪、但无法从 CAN 分析仪接收数据。 (当 CAN 分析仪向 F28075发送数据时、CANA.CAN_IF2MCTL.bit.NewDat 永远不会被设置为1)。

请帮助您查看我的代码有什么问题?

该代码基于示例代码 CAN_loopback_bitfields.c

//

//文件: CAN_loopback_bitfields.c

//

//标题: 演示基本 CAN 设置和使用的示例。

//

//! addtogroup cpu01_example_list

//!

使用位字段的 CAN 外部环回(CAN_loopback_bitFields)

//!

//! 重要说明:位字段标头是否需要编译器 v16.6.0.STS 和更高版本!

//!

//! 该示例使用位域报头、显示了中 CAN 的基本设置

//! 以便在 CAN 总线上发送和接收消息。  CAN

//! 外设配置为发送具有特定 CAN ID 的消息。

//! 然后、使用简单的延迟每秒传输一条消息

//! 用于计时的环路。  发送的消息是一个4字节的消息

//! 包含一个递增模式。

//! 此示例将 CAN 控制器设置为外部环回测试模式。

//! 发送的数据在 CAN0TX 引脚上可见、可通过接收

//! 适当的邮箱配置。

//!

//

//######################################################################################################################

//$TI 发行版:F2807x 支持库 V210 $

//$Release Date:Tue Nov1 15:42:43 CDT 2016 $

//版权所有:版权所有(C) 2014-2016 Texas Instruments Incorporated -

//       http://www.ti.com/ 保留所有权利$

//######################################################################################################################

 

//

//包含的文件

//

#include "F28x_Project.h"

 

//

//定义

//

#define CAN_MSG_ID        0x1111

#define CAN_TX_MSG_OBJ      1

#define CAN_RX_MSG_OBJ      2   //   这里是定义1号邮箱是发送,2号邮箱是接收。

#define CAN_MAX_BIT_DIFFERS_(  13) //最大 CAN 位时序除数

#define CAN_MIN_BIT_DIMINUSESCULE  (5)  //最小 CAN 位时序除数

#define CAN_MAX_PRE_DIFFERS_1024 (  1024)//最大 CAN 预除数

#define CAN_MIN_PRE_DIMINUSTERINL  (1)  //最小 CAN 预除数

#define CAN_BTR_BRP_M      (0x3F)

#define CAN_BTR_BRPE_M      (0xF0000)

 

 

//

//全局

//

uint32_t rec1;

unsigned char ucTXMsgData[4]={0x1、0x2、0x3、0x4};// TX 数据

unsigned char ucRXMsgData[4]={0x5、0x6、0x7、0x8};     // RX 数据

uint32_t messageSize = sizeof (ucTXMsgData);      //消息大小(DLC)

volatile unsigned long msgCount = 0;//一个跟踪的计数器

                   //发送次数

                   //成功。

volatile unsigned long errFlag = 0; //一个用于指示某些标志的标志

                   //发生传输错误。

 

静态常量 uint16_t canBitValues[]=            // 设置比特率的时候会用到;

  0x1100、// TSEG2 2、TSEG1 2、SJW 1、除以5

  0x1200、// TSEG2 2、TSEG1 3、SJW 1、除以6

  0x2240、// TSEG2 3、TSEG1 3、SJW 2、分频7

  0x2340、// TSEG2 3、TSEG1 4、SJW 2、8分频

  0x3340、// TSEG2 4、TSEG1 4、SJW 2、9分频

  0x3440、// TSEG2 4、TSEG1 5、SJW 2、10分频

  0x3540、// TSEG2 4、TSEG1 6、SJW 2、分频11

  0x3640、// TSEG2 4、TSEG1 7、SJW 2、12分频

  0x3740 // TSEG2 4、TSEG1 8、SJW 2、分频13

};

 

typedef 枚举

    //! 发送报文对象。

    MSG_obj_type_transmit、

 

    //! 接收报文对象。

    MSG_OBJ_TYPE_Receive

msgObjType;

 

//

//函数原型

//

uint32_t setCANBitRate (uint32_t sourceClock、uint32_t bitrate);  // 设置比特率;

void setupMessageObject (uint32_t Objid、uint32_t msgid、msgObjType msgType); // 设置消息对象;

void sendCANMessage (uint32_t Objid);  // 发送can信息;

bool getCANMessage (uint32_t Objid);  // 接收can信息;

 

//

//主函

//

内部

main (空)

  //

  //初始化系统控制:

  // PLL、安全装置、启用外设时钟   // 初始化系统时钟,PLL,外设时钟等

  //此示例函数位于 F2807x_sysctrl.c 文件中。

  //

  InitSysCtrl();  //  系统初始化里就已经讲外设时钟初始化了。

 

  //

  //初始化 GPIO:

  //此示例函数位于 F2807x_GPIO.c 文件和中

  //说明了如何将 GPIO 设置为其默认状态。

  //

  InitGpio();

  GPIO_SetupPinMux (62、GPIO_MUX_CPU1、6); //GPIO30 - CANRXA      // 这几个函数都是在gpio c里定义的;

  GPIO_SetupPinMux (63、GPIO_MUX_CPU1、6); //GPIO31 - CANTXA

  GPIO_SetupPinOptions (62、GPIO_INPUT、GPIO_异 步);

  GPIO_SetupPinOptions (63、GPIO_OUTPUT、GPIO_PushPull);

 

  //

  //初始化 CAN-A 控制器

  //

  InitCAN();

 

  //

  //设置可以关闭 SYSCLKOUT

  //

  ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0;   // CAN clock为系统时钟;

 

  //

  //设置 CAN 总线的比特率。  此函数设置 CAN

  针对标称配置的//总线时序。

  //在此示例中、CAN 总线设置为500kHz。

  //

  //有关的更多信息,请查阅数据表

  // CAN 外设时钟。

  //

  uint32_t status = setCANBitRate (120000000、50000); // 这里设置的sourceclock是200M,比特率是500k

 

  //

  //如果请求的值太小或太大,则捕获错误

  //

  if (status =0)

  {

    errFlag++;

    ESTOP0;     //在此处停止并处理错误

  }

 

  //

  //步骤3. 清除所有中断并初始化 PIE 矢量表:

  //禁用 CPU 中断

  //

  Dint; // 禁止中断;

 

  //

  //将 PIE 控制寄存器初始化为默认状态。

  //默认状态为禁用所有 PIE 中断和标志

  //被清除。

  //此函数位于 F2807x_PIECTRL.c 文件中。

  //

  InitPieCtrl();

 

  //

  //禁用 CPU 中断并清除所有 CPU 中断标志:

  //

  IER = 0x0000;

  IFR = 0x0000;

 

  //

  //使用指向 shell 中断的指针初始化 PIE 矢量表

  //服务例程(ISR)。

  //这将填充整个表,即使是中断也是如此

  //在本例中未使用。  这对于调试很有用。

  //可以在 F2807x_DefaultIsr.c 中找到 shell ISR 例程

  //此函数位于 F2807x_PieVect.c 中

  //

  InitPieVectTable();

 

  //

  //启用测试模式并选择外部环回。  

  //

  /*CanaRegs.CAN_CTL.bit.Test = 1;  // 通过注释掉这两句来禁用测试模式。

  CANaRegs.CAN_TEST.BIT.EXL = 1; // EXL 外部循环使能位;*

  /* CanaRegs.CAN_CTL.bit.Test = 0;   // 该位为0后,测试寄存器里面的功能就全部取消;*

 

  //

  //初始化将用于发送 CAN //初始化将用于发送CAN的消息对象;的消息对象

  //消息。  这个实际是上是配置邮箱 μ s

  //

  setupMessageObject (CAN_TX_MSG_obj、CAN_MSG_ID、MSG_OBJ_TYPE_transmit);

 

  //

  //初始化将用于接收 CAN 的消息对象

  //消息。

  //

  setupMessageObject (CAN_RX_MSG_obj、CAN_MSG_ID、MSG_OBJ_TYPE_Receive);   

 

  //

  //启用 CAN 以进行操作。

  //

  CANaRegs.CAN_CTL.bit.Init = 0;

 

  //

  //输入循环以发送消息。  根据、将发送一条新消息

  //秒。  4字节的消息内容将被视为无符号

  // long 并每次递增1。

  //

  for (;;)

  {

    //

    //使用对象1发送 CAN 消息(与不一样

    // CAN ID、在本例中也是1)。  此函数将导致

    //要立即传输的消息。   // 发送信息1,

    //

    /* sendCANMessage (CAN_TX_MSG_obj); // CAN_TX_MSG_obj ID=1*/

 

    //

    //现在等待1秒后再继续

    //

    DELAY_US (1000*1000);

 

    //

    //获取接收消息

    //

    getCANMessage (CAN_RX_MSG_obj);

    //

    //确保接收到的数据与发送的数据匹配

    //

  /*  if ((*(unsigned long *) ucTXMsgData)!=(*(unsigned long *) ucRXMsgData))

    {

      errFlag++;

      asm (" ESTOP0");

    }*/

 

    //

    //递增成功的消息计数和中的值

    //传输的消息数据。

    //

    msgCount++;

   /* (*(unsigned long *) ucTXMsgData)++;*/

  }

 

//

// setCANBitRate -根据器件时钟(Hz)设置 CAN 比特率

//         和所需的比特率(Hz)

//

uint32_t setCANBitRate (uint32_t sourceClock、uint32_t 比特率)

  uint32_t 设计位置;

  uint32_t canBits;

  uint32_t 预分频;

  uint32_t regValue;

  uint16_t canControlValue;

 

  //

  //计算所需的时钟速率。

  //

  desedRatio = sourceClock/bitrate;

 

  //

  //确保所需比率不会太大。  这将强制执行

  //要求比特率大于请求的。

  //

  if ((sourceClock / desedRatio)>位速率)

  {

    希望+=1;

  }

 

  //

  //检查所有可能的值以查找匹配的值。

  //

  while (希望的位置<= CAN_MAX_PRE_DIFFERS_CAN_MAX_BIT_DIFFERS_DIFFERS_CAN_MAX_BIT_DIFFERS_DIFFERS_OUR)

  {

    //

    //循环遍历所有可能的 CAN 位分频器。

    //

    对于(CANBits = CAN_MAX_BIT_DIFFERS_DIFFERS_IN;

      CANBits >= CAN_min_bit_di遮 阳板;

      坎比特:-)

    {

      //

      //对于一个给定的 CAN 位分频值、保存预分频值。

      //

      预分频=需要的 Ratio / canBits;

 

      //

      //如果计算出的分频值与所需的时钟比率相匹配

      //返回这些比特率并设置 CAN 位时序。

      //

      if ((preDivide * canBits)==desedRatio)

      {

        //

        //通过添加位时序开始构建位时序值

        //在时间份额中。

        //

        regValue = canBitValues[canBits - CAN_MIN_BIT_DIESS];

 

        //

        //要设置位时序寄存器,控制器必须是

        //放置

        //处于初始化模式(如果尚未),以及配置更改

        //位被启用。  应保存寄存器的状态

        //这样就可以恢复。

        //

        canControlValue = CanaRegs.CAN_CTL.ALL;

        CANaRegs.CAN_CTL.bit.Init = 1;

        CANARegs.CAN_CTL.bit.CCE = 1;

 

        //

        //现在添加位速率的预分频器。

        //

        regValue |=((preDivide-1)& CAN_BTR_BRP_M)|

              (((预分频器- 1)<< 10)& CAN_BTR_BRPE_M);

 

        //

        //在和中设置时钟位

        //预分频器。

        //

        CanaRegs.CAN_BTR.All = regValue;

 

        //

        //恢复保存的 CAN 控制寄存器。

        //

        CanaRegs.CAN_CTL.ALL = canControlValue;

 

        //

        //返回计算出的比特率。

        //

        return (sourceClock /(preDivide * canBits));

      }

    }

 

    //

    //将除数上移一并重新查看。  只有在极少数情况下才会发生这种情况

    //找到该值需要2个以上的循环。

    //

    需要的信息++;

  }

  返回0;

 

//

// setupMessageObject -将消息对象设置为发送或接收   

//

void setupMessageObject (uint32_t Objid、uint32_t msgid、msgObjType msgType)

  //

  //等待忙位清零。

  //

  while (CANaRegs.CAN_IF1CMD.bit.BUSY)

  {

  }

 

  //

  //清除并写出寄存器以编程报文对象。   

  //

  CANARegs.CAN_IF1CMD.ALL = 0;      

  CANaRegs.CAN_IF1MSK.ALL = 0;      

  CanaRegs.CAN_IF1ARB.all = 0;     

  CANaRegs.CAN_IF1MCTL.ALL = 0;      

 

  //

  //设置 Control、Mask 和 ARB 位,以便将它们传送到

  //消息对象。

  //

  CANARegs.CAN_IF1CMD.bit.Control = 1;      

  CanaRegs.CAN_IF1CMD.bit.ARB = 1;        

  CANARegs.CAN_IF1CMD.bit.Mask = 1;       

  CANARegs.CAN_IF1CMD.bit.DIR = 1;      

 

  //

  //设置发送方向       //   

  //

  if (msgType = MSG_obj_type_transmit)

  {

    CANARegs.CAN_IF1ARB.bit.Dir = 1;    //   

  }

 

  //

  //设置消息 ID (此示例假定11位 ID 掩码)  //    

  //

  CanaRegs.CAN_IF1ARB.bit.ID = msgid;       //   

  CANARegs.CAN_IF1ARB.bit.MsgVal = 1; //    

 

  //

  //设置数据长度,因为这是为所有传输设置的。  这是

  //也是单次传输,而不是 FIFO 传输,所以将 EOB 位置位。

  //

  CanaRegs.CAN_IF1MCTL.bit.DLC =消息大小;  //  

  CANaRegs.CAN_IF1MCTL.bit.EOB = 1;   //  

 

  //

  //将数据传输到消息对象 RAM   // 将data传到消息RAM;

  //

  CANARegs.CAN_IF1CMD.bit.MSG_NUM = Objid;    //

 

//

// sendCANMessage -从 传输数据;报文对象发送数据//μ s

//

空 sendCANMessage (uint32_t Objid)

  //

  //等待忙位清零。

  //

  while (CANaRegs.CAN_IF1CMD.bit.BUSY)

  {

  }

 

  //

  //将要传输的数据写入数据 A 和数据 B 接口寄存器

  //

 

  uint16_t 索引;

  for (index = 0;index < messageSize;index++)

  {

    switch (索引)

    {

      情况0:

        CANARegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[index]; //   

        中断;

      案例1:

        CANARegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[index];

        中断;

      案例2:

        CANARegs.CAN_IF1DATA.bit.Data_2 = ucTXMsgData[index];

        中断;

      案例3:

        CANARegs.CAN_IF1DATA.bit.Data_3 = ucTXMsgData[index];

        中断;

      案例4:

        CANARegs.CAN_IF1DATB.bit.Data_4 = ucTXMsgData[index];

        中断;

      情况5:

        CANARegs.CAN_IF1DATB.bit.Data_5 = ucTXMsgData[index];

        中断;

      案例6:

        CANARegs.CAN_IF1DATB.bit.Data_6 = ucTXMsgData[index];

        中断;

      案例7:

        CANARegs.CAN_IF1DATB.bit.Data_7 = ucTXMsgData[index];

        中断;

    }

  }

 

  //

  //设置写入方向并设置要传输到的数据 A/数据 B

  //消息对象

  //

  CANaRegs.CAN_IF1CMD.ALL = 0x830000; //  DIR=1;dataaa,dataB=1;   

 

  //

  //设置 Tx 请求位

  //

  CANARegs.CAN_IF1CMD.bit.TXRQST = 1;    

 

  //

  //将报文对象传输到由指定的报文对象

  // Objid。

  //

  CANaRegs.CAN_IF1CMD.bit.MSG_NUM = Objid;     ;μ A

 

//

// getCANMessage -检查消息对象是否有新数据。

//         如果是新数据、则写入数组并返回 true。

//         如果没有新数据、则返回 false。

//

 

bool getCANMessage (uint32_t Objid)

  bool 状态;

 

  //

  //设置要读取的消息数据 A、数据 B 和控制值

  //从报文对象请求数据时。

  //

  CANARegs.CAN_IF2CMD.ALL = 0;

  CANARegs.CAN_IF2CMD.bit.Control = 1;     ;μ A

  CANARegs.CAN_IF2CMD.bit.DATA_A = 1;     

  CANARegs.CAN_IF2CMD.bit.DATA_B = 1;      

 

  //

  //将报文对象传输到报文对象 IF 寄存器。

  //

  CANARegs.CAN_IF2CMD.bit.MSG_NUM = Objid;

 

  //

  //等待忙位清零。

  //

  while (CANaRegs.CAN_IF2CMD.bit.BUSY)

  {

  }

 

  //

  //查看是否有可用的新数据。

  //

  if (CANaRegs.CAN_IF2MCTL.bit.NewDat = 1)    // 有新的消息写入;

  {

    //

    //从 CAN 寄存器中读出数据。

    //

    uint16_t 索引;

    for (index = 0;index < messageSize;index++)

    {

      switch (索引)

      {

        情况0:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_0;

        中断;

        案例1:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_1;

        中断;

        案例2:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_2;

        中断;

        案例3:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_3;

        中断;

        案例4:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_4;

        中断;

        情况5:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_5;

        中断;

        案例6:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_6;

        中断;

        案例7:

          ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_7;

        中断;

      }

    }

 

    //

    //清除新数据标志

    //

    CANaRegs.CAN_IF2CMD.bit.TxRqst = 1;     // 清除 newDATA 位;

 

 

    //等待忙位清零。

    //

    while (CANaRegs.CAN_IF2CMD.bit.BUSY)

    {

    }

 

    //

    //将报文对象传输到报文对象 IF 寄存器。

    //

    CANARegs.CAN_IF2CMD.bit.MSG_NUM = Objid;

 

    状态= true;

  }

  其他

  {

    状态= false;

  }

 

  退货(状态);


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您能够向 CAN 总线分析仪发送数据这一事实表明、可能没有硬件问题、并且节点之间的比特率是相同的。 确保节点之间的 MSGID 相同。 (有关详细信息、请查看 SPRA876中的调试提示)。 也可以尝试使用 CANES 中的 RxOK 位。 请注意,它将被设置为总线上的*ANY*帧,但至少它是一个很好的指示,表明是否监视了一个完整的帧。

     

    在另一个注释中,如果您在帖子中插入代码片段,请始终使用“Syntax Highlighter”选项进行粘贴。 这使得代码更易于阅读。