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.

[参考译文] EK-TM4C1294XL:基于 CAN 的消息传输不工作。

Guru**** 2468610 points
Other Parts Discussed in Thread: TM4C129ENCPDT, TM4C1294NCPDT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/672552/ek-tm4c1294xl-can-based-message-transfer-not-working

器件型号:EK-TM4C1294XL
主题中讨论的其他器件:TM4C129ENCPDTTM4C1294NCPDT

您好!

我尝试使用收发器测试2个定制 TM4C129ENCPDT 板之间的 CAN 通信。 为此、我修改了简单 RX 和简单 TX 示例程序、并将它们刷写到2个单独的电路板上、然后将它们连接起来。 但是、当中断处理程序被命中时、我会在状态寄存器中对应于总线关闭的错误语句0x8000之后看到错误0x05。

为了测试代码的有效性、我尝试了内部回送(在使用 CAN_ENABLE API 启用 CAN 之前配置测试模式和内部回送寄存器)并且 AM 能够看到0x01的状态(对应于 TX 消息目标 ID)、即内部回送正常工作。

此外、我尝试探测收发器的环回代码、并且能够在收发器的 CAN TX 引脚中看到数据、但在收发器的 CAN_HI 和 CAN _LO 引脚上看不到数据。

我出了什么问题?

以下是我为 CAN_Transmit 使用的代码(在注释掉环回语句的情况下):

#include "config.h"

#ifdef CAN_TX_ENABLE

#include 
#include 
#include "inc/hw_ca.h"
#include "include/hw_ints.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/ca.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/trunic.h"#include "driverlib/driverlib.udio.idio.h"#include "driverlib





//
//! \addtogroup CAN_examples_list
//! 

简单 CAN TX (simple_tx)

//! //! 此示例显示了 CAN 的基本设置、以便传输消息 //! 总线上的电流。 CAN 外设配置为发送消息 //! 具有特定的 CAN ID。 然后每秒传输一条消息 、//! 使用简单的延迟环路进行计时。 发送的消息是4 //! 包含递增模式的字节消息。 A CAN 中断 //! 处理程序用于确认消息传输并计数 //! 已发送的消息。 //! //! 此示例使用以下外设和 I/O 信号。 您必须 //! 查看这些内容并根据您自己的董事会需要进行更改: //! - CAN0外设 //! - GPIO 端口 A 外设(用于 CAN0引脚) //! - CAN0RX - PA0 //! - CAN0TX - PA1 //! //! //! 此示例使用以下中断处理程序。 要使用此示例 //! 在您自己的应用程序中、您必须将这些中断处理程序添加到 您的//! 矢量表。 //! - INT_CAN0 - CANIntHandler // /********* // // //跟踪 TX 中断次数 的计数器//发生,该计数器应与发送的 TX 消息数匹配。 //// ***************** 易失性 uint32_t g_ui32MsgCount = 0; //********* // //指示发生了一些传输错误的标志。 //// ***************** volatile bool g_BErrFlag = 0; //********* // //此函数使用简单的轮询方法提供1秒延迟。 //// ***************** void SimpleDelay (void) { // //延迟周期1秒 // SysCtlDelay (16000000 / 3); } //********* // //此函数是 CAN 外设的中断处理程序。 它会检查 //中断原因,并保持 //已传输的所有消息的计数。 //// ***************** void CANIntHandler (void) { uint32_t ui32Status; // //读取 CAN 中断状态以查找中断原因 // ui32Status = CANIntStatus (CAN0_BASE、CAN_INT_STS_CAUST); // //如果原因是控制器状态中断,则获取状态 // if (ui32Status = CAN_INT_INTID_STATUS) { // //读取控制器状态。 这将返回状态字段 //可以指示各种错误的错误位。 错误处理 //本示例中不是为了简单起见。 请参阅 // API 文档,了解有关错误状态位的详细信息。 //读取此状态的操作将清除中断。 如果 // CAN 外设未与其它 CAN 器件连接到 CAN 总线 //存在,则会发生错误,并在中指示 //控制器状态。 // ui32Status = CANStatusGet (CAN0_BASE、CAN_STS_CONTROL); // //设置一个标志来指示可能发生的某些错误。 // G_bErrFlag = 1; } // //检查原因是否是我们正在使用的消息对象1 //发送消息。 // 否则、如果(ui32Status = 1) { // //到达这一点意味着 TX 中断发生在上 //消息对象1、消息 TX 完成。 清除 //消息目标中断。 // CANIntClear (CAN0_BASE、1); // //递增计数器以跟踪已有多少消息 //已发送。 在实际应用中、这可用于将标志设置为 //指示何时发送消息。 // G_ui32MsgCount++; // //由于消息已发送,请清除所有错误标志。 // G_bErrFlag = 0; } // //否则,发生意外导致中断的情况。 这应该是 //永远不会发生。 // 其他 { // //可以在此处执行伪中断处理。 // } } //********* // //配置 CAN 并输入循环以传输周期性 CAN 消息。 //// ***************** int main (void) { #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif tCANMsgObject sCANMessage; tCANMsgObject sCANMessage1; uint32_t ui32MsgData; uint8_t * pui8MsgData; pui8MsgData =(uint8_t *) ui32MsgData; // //将时钟设置为直接从外部晶振/振荡器运行。 // TODO:必须更改 SYSCTL_XTAL_VALUE 以匹配的值 板上的//晶体。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC) 25000000); #else SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz); #endif // //设置用于显示消息的串行控制台。 这是 //仅针对此示例程序,CAN 操作不需要。 // // InitConsole(); // //对于此示例、CAN0与端口 B4和 B5上的 RX 和 TX 引脚一起使用。 //您使用的实际端口和引脚可能有所不同,请参阅 //数据表以了解更多信息。 // GPIO 端口 B 需要启用、以便可以使用这些引脚。 // TODO:将其更改为您正在使用的 GPIO 端口 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //配置 GPIO 引脚复用以选择这些引脚的 CAN0功能。 //此步骤选择可用于这些引脚的替代功能。 //如果您的器件支持 GPIO 引脚功能多路复用、这是必需的。 //请查阅数据表以查看每个引脚分配的函数。 // TODO:更改此选项以选择您正在使用的端口/引脚 // GPIOPinConfigure (GPIO_PA0_CAN0RX); GPIOPinConfigure (GPIO_PA1_CAN0TX); // //启用 GPIO 引脚上的复用功能。 以上步骤选择 //可用的备用功能。 此步骤实际上启用 //这些引脚的替代功能、而不是 GPIO。 //待办事项:更改此项以匹配您正在使用的端口/引脚 // GPIOPinTypeCAN (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); // //已为 CAN 设置 GPIO 端口和引脚。 CAN 外设 //必须启用。 // SysCtlPeripheralEnable (SYSCTL_Periph_CAN0); // //初始化 CAN 控制器 // CANInit (CAN0_BASE); // //设置 CAN 总线的比特率。 此函数设置 CAN 针对标称配置的//总线时序。 您可以实现更多控制 //使用函数 CANBitTimingSet()代替 CAN 总线时序 //如果需要。 //在此示例中、CAN 总线设置为500kHz。 在以下函数中、 // SysCtlClockGet ()或 ui32SysClock 的调用被用来确定 //用于为 CAN 外设计时的时钟速率。 这是可以的 //如果您知道系统时钟的值,则替换为固定值, //保存额外的函数调用。 对于某些器件、CAN 外设是 //使用固定的8MHz 时钟进行计时,而不管在哪种情况下是系统时钟 //对 SysCtlClockGet()或 ui32SysClock 的调用应替换为 // 80000。 有关 CAN 的更多信息、请参阅数据表 //外设时钟。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) CANBitRateSet (CAN0_BASE、ui32SysClock、50000); #else CANBitRateSet (CAN0_BASE、SysCtlClockGet ()、50000); #endif // //在 CAN 外设上启用中断。 此示例使用静态 //分配中断处理程序,表示处理程序的名称 //位于启动代码的矢量表中。 如果您想使用动态的 //分配矢量表,然后还必须调用 CANIntRegister() //此处。 // // CANIntRegister (CAN0_BASE、&CANIntHandler);//如果使用动态向量 // HWREG (CAN0_BASH+CAN_O_CTL)|= CAN_CTL_TEST; HWREG (CAN0_BASH+CAN_O_TST)|= CAN_TST_LBACK; CANIntEnable (CAN0_BASE、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // //在处理器(NVIC)上启用 CAN 中断。 // IntEnable (INT_CAN0); // //启用 CAN 以进行操作。 // CANEnable (CAN0_BASE); // //初始化将用于发送 CAN 的消息对象 //消息。 消息将是包含一个递增的4个字节 //值。 最初它将设置为0。 // ui32MsgData = 0; sCANMessage.ui32MsgID = 1; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; sCANMessage.ui32MsgLen = sizeof (pui8MsgData); sCANMessage.pui8MsgData = pui8MsgData; // //初始化用于接收 CAN 消息的消息对象 //任何 CAN ID。 为了接收任何 CAN ID、ID 和掩码必须同时存在 //设置为0,并启用 ID 过滤器。 // // sCANMessage1.ui32MsgID = 0; // sCANMessage1.ui32MsgIDMask = 0; // sCANMessage1.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; // sCANMessage1.ui32MsgLen = 8; // //输入循环以发送消息。 根据、将发送一条新消息 //秒。 4字节的消息内容将被视为 uint32_t //并每次递增1。 // while (1) { // //使用对象1发送 CAN 消息(与不一样 // CAN ID、在本例中也是1)。 此函数将导致 //要立即传输的消息。 // CANMessageSet (CAN0_BASE、1、&sCANMessage、MSG_OBJ_TYPE_TX); // //现在将消息对象加载到 CAN 外设中。 加载后 // CAN 将在总线上接收任何消息,并将发生中断。 //使用消息对象1接收消息(与不同) //此示例中可以是任何值的 CAN ID)。 // // CANMessageSet (CAN0_BASE、2、&sCANMessage1、MSG_OBJ_TYPE_RX); // //现在等待1秒后再继续 // SimpleDelay(); // //递增消息数据中的值。 // ui32MsgData++; } // //返回无错误 // return (0); } #endif

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

    正如您所说的、这可能是收发器问题、您在收发器输入上看到了 TXD、但没有 CAN_H 和 CAN_L 检查 CAN_H 和 CAN_L 上的端接电阻是否正确 它们通常为120欧姆。 对其进行谷歌搜索。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="APOORV Garg"]我尝试测试2 个定制 TM4C129ENCPDT 板与收发器之间的 CAN 通信。 为此、我修改了简单 RX 和简单 TX 示例程序[/quot]

    "修改、"简单 RX/TX"是否会导致(甚至可能)您的问题?

    Fi/I-多年来-努力(始终)开始使用"未修改的供应商计划"(以最好地确保其成功)-并且仅在(以后)-一旦计划"得到证明"-尝试逐步修改。   这是一种标准做法-由"kiss"规定。   限制 "未知"的数量始终是明智之举。

     "修改"没有现成(也没有明确)的描述、"不合理"的是期望这里的修改会试图"挖掘出来"。

    [引用 user="APOORV Garg"]可以在收发器的 CAN TX 引脚中查看数据,但在 CAN_HI 和 CAN _LO 引脚上看不到数据

    @-有(许多)个 CAN 收发器-并非所有收发器都能成功运行-现代 MCU 的3V3级别。   正如您报告的、"无输出"-您的收发器是否"确定"能够很好地适应3V3信号电平?   即使您的收发器由5V 电源供电、也是如此?

    我可以报告、我的公司-至少五年-在 LM3S、LX4F 和 TM4C 范围内部署了未经修改的"简单 RX/TX 程序示例"、因此"始终"获得成功。  (供应商 MCU)

     收发器的安装方式和位置"没有提到"。   引线过长-和"试验电路板结构"(可能)起作用-但不能保证。   检查并重新检查所有连接、尤其是每个收发器的电源。

    我很高兴看到您没有采用 "最大 CAN 总线 数据速率"、但在初始测试期间、我会将您的数据速率减半(或更多)。    在您的实施过程中、您可以尽一切努力"减轻压力"、这通常会产生最佳结果。   尝试"过早优化"-太频繁-阻止和/或阻止-甚至是最简单的操作...

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

    您好,

    感谢您的回复。

    1) 收发器的能力不正确。 我使用的是 ISO1050DUBR 版本的 TI 作为收发器。

    2) 因为它是定制板。 我需要分别使用 PA0和 PA1作为 RX 和 TX 的 CAN。 这个和删除控制台函数是我对简单 RX 和 TX 示例程序所做的唯一更改。

    3) 我在1个板中刷写了 simple_tx (在 Simple TX 示例中为消息对象 ID =1)、在另一个板中刷写了 simple_RX (在 Simple RX 示例中为消息对象 ID =1)。

    在探测时、我在收发器的 RX 引脚上获取数据、但未命中代码中断处理程序。

    我还发现 tivaware ca.c 文件中存在错误(链接: )

    因此、我在 CAN.c 文件中进行了建议的更改。

    但是、我仍然无法在接收端看到任何中断。

    可以做些什么?

    4) 是否没有可用的外部回送。 基本而言、只要我移除线

      HWREG (CAN0_BASH+CAN_O_CTL)|= CAN_CTL_TEST;

      HWREG (CAN0_BASH+CAN_O_TST)|= CAN_TST_LBACK;

    在 CAN_Enable 和执行外部回送(短接 CAN_RX 和 CAN_TX 引脚)之前、我在发送中断处理程序中得到错误0x69。

    如果我删除了这些行 I 和 short、则在发送中断处理程序中会出现错误0x05 (总线关闭)。

    因此、我将代码置于环回模式、并将其连接到刷写了 simple_RX 示例的第二个定制板、我可以在 RX 引脚中看到数据、但没有接收中断。

    我是全局静态中断矢量分配。

    我出了什么问题?

    此致、

    奥 poorv

    e2e.ti.com/.../CAN_5F00_Transmit.c

    e2e.ti.com/.../CAN_5F00_Receive.c

    e2e.ti.com/.../config.h

    e2e.ti.com/.../tm4c1294ncpdt_5F00_startup_5F00_ccs.c

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

    感谢您-您的(新)数据在很大程度上帮助了您、"远程诊断"-您是否同意?

    现在、我对您的代码进行了审查、发现:

    "CANIntEnable (CAN0_BASE、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);"

    自公司/我在 CAN 模式下使用该供应商的 MCU (已经有一段时间了)-因此我必须问-"CAN  总线-数据接收 MCU 的上述功能是否"完全正确"?

    由于您的问题(现在)已(仅限-现在)转移到故障、"识别和/或响应基于 CAN 的中断"-所有代码 :"设置、配置和实现接收端的 CAN 中断应"仔细检查"。

    我要补充一点,你对"CAN simple"的"修改"是合理的,但没有这个细节,你的助手 crüe 没有"选择",而是要问。

    您将注意力集中在接收端的中断"代码和处理"上、应该 是"朝着您的目标前进"。   祝您有机会、我是 AMI。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    当您在 TXD 和 RXD 引脚之间连接时、ACK 将失败。 ACK 位应由另一个节点(接收器)驱动。 当接收器接收到帧时、它将驱动显性 ACK。 连接两个电路板时、请在 RXD 引脚上显示示波器电容。

    此外、请确保您的收发器未处于待机模式。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我的问题已解决。 有2个错误:
    1) Tivaware 版本2.1.3.156在 CAN.c 文件中有 abug、因此中断不能被正确清除。
    2) 我使用的是返回0的 sysclkfreqget (TM4C1294NCPDT 有一些问题)。 相反、我存储了频率。 并传递该变量以设置 CANsetbit时序 函数、我的代码开始正常运行。

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

    很高兴您的问题得到解决。

    下面是您为代码粘贴的内容。 如果您具有正确的 TARGET_IS_TM4C129_RAX 预定义符号、则它将正确配置 CAN 时钟。 不确定您代码中的何处误用了 SysCtlClockGet ()。 如果您要开始新的开发、请务必使用最新的 TivaWare 库。


    #if defined (target_IS_TM4C129_RA0)|| \
    已定义(TARGET_IS_TM4C129_RA1)|| \
    已定义(TARGET_IS_TM4C129_RA2)
    CANBitRateSet (CAN0_BASE、ui32SysClock、50000);
    其他
    CANBitRateSet (CAN0_BASE、SysCtlClockGet ()、50000);
    #endif
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、
    我尚未在预定义符号中定义 TARGET_IS_TM4C129_RA1、因此它进入了 else 循环。
    此致、
    奥 poorv