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.

[参考译文] RTOS/TM4C1294NCPDT:用于 TM4C1294NCPDT 的 CAN 驱动程序

Guru**** 2482105 points
Other Parts Discussed in Thread: TM4C1294NCPDT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/710534/rtos-tm4c1294ncpdt-can-driver-for-tm4c1294ncpdt

器件型号:TM4C1294NCPDT

工具/软件:TI-RTOS

我使用的是 TM4C1294NCPDT、CCS 6.1.2、 TIRTOS 2.16.0.08和编译器5.2.7。

我查看了几个编写 CAN 驱动程序的示例、但我的驱动程序尚不能发送或接收 CAN 数据。

我正在使用的 CPU 可以连接到 CPU 引脚 PB0 (CAN RX)和 PB1 (CAN TX)。  我使用一个宽开滤波器/掩码为接收配置对象编号(CAN 邮箱) 1、并使用对象编号2、3和4来发送以测试代码。

总之、这是我的代码。

全局变量:

typedef 结构

   bool 忙;
   bool CAN_configured;
   unsigned long g_ulMsg1Count、g_ulMsg2Count、g_ulMsg3Count、g_bMsgObj3Sent;
   tCANMsgObject sMsgObjectRx;
   tCANMsgObject sMsgObjectTx;
   bool g_bErrFlag;
   uint8_t message[message_length]; //数据缓冲区
} CAN_Manager;
静态 CAN_Manager CAN_Manager ={0、0、0、0、0、0、0、0、0};


tCANMsgObject testTx;

#define CAN_MSG_OBJ_RX     1.

主循环 init 可以反复发送消息。

int main (void){ //>>>>> 禁用看门狗以调试此情况、否则看门狗将在休息点 TMO 并重置电路板。

   Board_initGeneral();


   CAN_init();
   while (1)
   {
         sendTestCAN_Message();
         small_delay;
   }

 

如何完成 CAN 初始化。

void CAN_init (void)

   Hwi_handle myHwi;
   ERROR_Block EB;
   Hwi_Params HwiParams;

   memset ((void*)&CAN_Manager、0x00、sizeof (CAN_Manager));

   SysCtlPeripheralEnable (GPIO_PORTB_BASE);
   small_delay;//调用 SysCtlPeripheralEnable()时、需要一个小延迟才能使用器件。

    GPIOPinConfigure (GPIO_PB0_CAN1RX);      // CAN RX 为 PB0
   GPIOPinConfigure (GPIO_PB1_CAN1TX);      // CAN TX 为 PB1
   GPIOPinTypeCAN (GPIO_PORTB_BASE、GPIO_PIN_0 | GPIO_PIN_1);
   SysCtlPeripheralEnable (SYSCTL_Periph_CAN0);

    CANInit (CAN0_BASE);

   CANBitRateSet (CAN0_BASE、120000000、50000);
   printf ("CAN 0 init\n");

   //CANBitRateSet (CAN0_BASE、SysCtlClockGet ()、50000);
   printf ("CAN 0时钟集\n"\});

   CANEnable (CAN0_BASE);
   printf ("CAN 0已启用\n");

   //p81/706 Periph 驱动程序库 spmu298a.pdf 启用 CAN 中断(全部三个 IRQ)
   CANIntEnable (CAN0_BASE、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
   printf ("CAN 0 INT enabled \n"\n);

   //配置接收对象。  
   CAN_Manager.sMsgObjectRx.ui32MsgID =(0x602);       
   CAN_Manager.sMsgObjectRx.ui32MsgIDMask = 0;         //过滤器掩码。 0=接受所有 e2e.ti.com/.../568684
   CAN_Manager.sMsgObjectRx.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;   //启用 RX 上的中断
   CAN_Manager.sMsgObjectRx.ui32MsgLen = 8;      //最多允许8个字节
   CANMessageSet (CAN0_BASE、1、CAN_Manager.sMsgObjectRx、MSG_OBJ_TYPE_RX);

   /*   立即安装 IRQ */
   ERROR_INIT (&EB);
   Hwi_Params_init (hwiParams);
   myHwi = Hwi_create (INT_CAN0_TM4C129、CANIntHandler、&hwiParams、&EB); //请参阅 TIvAware \inc\hw_ints.h

   if (NULL ==myHwi)
   {
      LOG_EVENT (ERROR_CIB_APP_Board_ERROR、"Error installing IRQ for CAN0");
   }

   //IntEnable (INT_CAN0);//Enable CAN 中断
   //CANEnable (CAN0_BASE);//Enable CAN for operation

   CAN_Manager.CAN_Configured = true;
}//结束 CAN_init()

发送一条消息、在初始化后从 main 循环中调用。

void sendTestCAN_Message (void)

   if (CAN_Manager.CAN_Configured = 0)
   {
      printf ("无法配置、从发送 CAN 消息\n 返回");
      返回;
   }

   CAN_Manager.sMsgObjectTx.ui32MsgID = 0x7A7;
   CAN_Manager.sMsgObjectTx.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
   CAN_Manager.sMsgObjectTx.ui32MsgLen = 8;
   CAN_Manager.sMsgObjectTx.pui8MsgData = CAN_Manager.message;// ptr 至 TX 消息内容


   CANMessageSet (CAN0_BASE、2、&CAN_Manager.sMsgObjectTx、MSG_OBJ_TYPE_TX);//将消息发送到 mbx 2
   CANMessageSet (CAN0_BASE、3、&CAN_Manager.sMsgObjectTx、MSG_OBJ_TYPE_TX);//将消息发送到 mbx 3.
   CANMessageSet (CAN0_BASE、4、&CAN_Manager.sMsgObjectTx、MSG_OBJ_TYPE_TX);//将消息发送到 mbx 4



   testTx.ui32MsgID = 0x7A7;
   testTx.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
   testTx.ui32MsgLen = 8;
   testTx.pui8MsgData = CAN_Manager.message;// ptr 至 TX 消息内容
   CANMessageSet (CAN0_BASE、2、&testTx、MSG_OBJ_TYPE_TX);//发送消息

   printf ("CAN TX\n");

IRQ 处理程序、请注意、这永远不会被调用。

空 CANIntHandler (UARg 参数)

   unsigned long ulStatus;

   //
   //读取 CAN 中断状态以查找中断原因
   ulStatus = CANIntStatus (CAN0_BASE、CAN_INT_STS_CAUST);

   //
   //如果原因是控制器状态中断,则获取状态
   if (ulStatus = CAN_INT_INTID_STATUS)
   {
       //
       //读取控制器状态。  这将返回状态字段
       //可以指示各种错误的错误位。  错误处理
       //本示例中不是为了简单起见。  请参阅
       // API 文档,了解有关错误状态位的详细信息。
       //读取此状态的操作将清除中断。  如果
       // CAN 外设未与其它 CAN 器件连接到 CAN 总线
       //存在,则会发生错误,并在中指示
       //控制器状态。
       //
       ulStatus = CANStatusGet (CAN0_BASE、CAN_STS_CONTROL); // CAN_STS_NEWDAT

       //
       //设置一个标志来指示可能发生的某些错误。
       //
       CAN_Manager.g_BErrFlag = 1;
       return; //我们是否要返回这里?
   }
   if (ulStatus = 1)//如果 msg 对象为1,则接收到的消息可以 obj 1
   {
       CANIntClear (CAN0_BASE、1);
       CAN_Manager.g_ulMsg1Count++;
       CAN_Manager.g_BErrFlag = 0;
   }
   否则、如果(ulStatus = 2) //如果 msg 对象为2、则接收到的消息可以 obj 2
   {
       CANIntClear (CAN0_BASE、2);
       CAN_Manager.g_ulMsg2Count++;
       CAN_Manager.g_BErrFlag = 0;
   }
   否则、如果(ulStatus = 3)
   {
       CANIntClear (CAN0_BASE、3);
       CAN_Manager.g_ulMsg3Count++;
       CAN_Manager.g_bMsgObj3Sent = 1;
       CAN_Manager.g_BErrFlag = 0;
   }
   否则、如果(ulStatus = 8)
   {
      CANIntClear (CAN0_BASE、8);
      CAN_Manager.g_ulMsg3Count++;
      CAN_Manager.g_bMsgObj3Sent = 1;
      CAN_Manager.g_BErrFlag = 0;
   }
   否则、如果(ulStatus = 16)
   {
      CANIntClear (CAN0_BASE、16);
      CAN_Manager.g_ulMsg3Count++;
      CAN_Manager.g_bMsgObj3Sent = 1;
      CAN_Manager.g_BErrFlag = 0;
   }
   //
   //否则,发生意外导致中断的情况。  这应该是
   //永远不会发生。
   //
   其他
   {
       //
       //可以在此处执行伪中断处理。
       //
   }


我可能错过了一些简单的东西、但我还没有找到。

谢谢、

道格

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

    除非设置了环回模式、否则 CAN 模块不会接收自己的消息。 遗憾的是、没有 TivaWare 函数来实现该目的。 这里是我用于设置该模式的代码。 我还附上了一个简单的 CCS 项目示例。

    //启用环回模式
    HWREG (CAN1_BASE + CAN_O_CTL)|= CAN_CTL_TEST;//设置测试位
    HWREG (CAN1_BASE + CAN_O_TST)|= CAN_TST_LBACK;//设置环回位
    

    /cfs-file/__key/communityserver-discussions-components-files/908/4213.CanLoopback.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    使用我在原始文章中发布的代码、我在 CAN TX 引脚上放置了一个示波器探针、以查找是否发送了任何 CAN 消息。 代码将首先初始化 CAN 器件0、然后以循环的方式发送 CAN 消息并查看示波器、我从未看到任何指示我正在实际发送数据。 我将更仔细地查看您的示例、并将其与我的代码进行比较、希望我可以看到我错过了什么。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在您的原始示例中、如果不启用环回、除非您在 CAN 总线上有一个 CAN 收发器和另一个器件、否则第一条消息将看不到应答。 它假定消息未成功发送(根据定义、如果没有其他节点将其确认为良好消息、则不会成功发送)并尝试再次发送。 这一切都由 CAN 硬件完成。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果我查看 CPU 上的 CAN TX 引脚、我是否应该看不到它尝试发送消息? 我有一个 CAN 总线分析仪、我也在使用它来尝试与 Tiva 通信、因此如果 Tiva 发送了一条消息、总线分析仪应该会看到它、我也可以使用 CAN 总线分析仪发送一条 CAN 消息、我应该能够这样做 在 Tiva 上接收 CAN 消息。 我使用示波器查看 CPU 上的 CAN TX 引脚、以使设置尽可能基本。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不能"佩戴"-但我认为- CAN RX 引脚必须"有序"-以便 CAN TX "活起来!"   (在测试/验证期间通过 CAN Xcvr (如果存在)或简单的"将 R 上拉至 CAN_RX"实现)

    使用(适当的) CAN Xcvrs (@两端)-我们发现-比(任何)供应商的"回送"更可靠、更"更接近现实世界应用程序"。   (例如、为什么"拒绝"-您的"带现实的 BOUT?")

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

    我有机会 再次查看、发现了代码的问题。  问题是我使用的引脚(PB0和 PB1)与 CAN1一起工作、并且我为这些引脚配置 CAN0、这就是它不工作的原因。

    道格。