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**** 2451240 points
Other Parts Discussed in Thread: EK-TM4C1294XL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/624049/ek-tm4c1294xl-issue-with-can-bus-transmitter-code

器件型号:EK-TM4C1294XL

我正在尝试为 CAN Tx 侧调试以下代码。 我已使用 USB 并使用 PuTTy 通过 UART 查看结果、将 EK-TM4C1294XL 板连接到 PC。

我正在运行的代码如下:

//

#include

#include

#include "inc/hw_ca.h"

#include "inc/hw_ints.h"

#include "inc/hw_memmap.h"

#include "driverlib/CAN.h"

#include "driverlib/gpio.h"

#include "driverlib/interrupt.h"

#include "driverlib/pin_map.h"

#include "driverlib/sysctl.h"

#include "driverlib/uart.h"

#include "utils/uartstdio.h"

#include "utils/uartstdio.c"

//

//

//! addtogroup CAN_examples_list

//!

多 CAN TX (MULTI_TX)

//!

//! 此示例显示了如何设置 CAN 以发送多条消息。  。

//! CAN 外设配置为发送具有4个不同 CAN ID 的消息。

//! 使用共享发送两条消息(具有不同的 CAN ID)

//! 消息目标。  这显示了如何将一个消息对象重复用于多个对象

//! 消息。  其他两条消息使用其自己的消息对象发送。

//! 所有四条消息每秒传输一次。  内容

//! 消息是测试模式。  CAN 中断处理程序用于确认

//! 消息传输并计算已发送消息的数量。

//!

//! 此示例使用以下外设和 I/O 信号。  您必须执行的操作

//! 查看这些内容并根据您自己的董事会的需要进行更改:

//! - CAN1外设

//! - GPIO 端口 B 外设(用于 CAN1引脚)

//! - CAN1RX - PB0

//! - CAN1TX - PB1

//!

//! 以下 UART 信号仅配置为显示控制台

//! 消息。  CAN 的运行不需要这些参数。

//! - GPIO 端口 A 外设(用于 UART0引脚)

//! - UART0RX - PA0

//! - UART0TX - PA1

//!

//! 此示例使用以下中断处理程序。  来使用该示例

//! 在您自己的应用程序中、您必须将这些中断处理程序添加到

//! 矢量表。

//! - INT_CAN1 - CANIntHandler

//

//

//

//

//跟踪 TX 中断次数的计数器

//发生,它应与发送的 TX 消息数匹配。

//

//

volatile uint32_t g_ui32IntCount = 0;

//

//

//用于计算每个上的消息数的计数器

//本示例中使用的三个消息对象。

//

//

volatile uint32_t g_ui32Msg1Count = 0;

volatile uint32_t g_ui32Msg2Count = 0;

volatile uint32_t g_ui32Msg3Count = 0;

//

//

//指示 CAN 控制器报文对象3已发送报文的标志。

//

//

volatile bool g_bMsgObj3Sent = 0;

//

//

//指示发生了某些传输错误的标志。

//

//

volatile bool g_BErrFlag = 0;

//

//

//将保存单独 CAN 消息的 CAN 消息对象。  这些都可以

//也要在栈上分配,但要小心,因为这些结构

//每个大约需要20个字节。

//

//

tCANMsgObject g_sCANMsgObject1;

tCANMsgObject g_sCANMsgObject2;

tCANMsgObject g_sCANMsgObject3;

//

//

//保存4个不同消息内容的消息缓冲器

正被传输。  每个都是不同的长度。

//

//

uint8_t g_pui8Msg1[4]={1、3、5、7};

uint8_t g_pui8Msg2[5]={2、4、6、8、10};

uint8_t g_pui8Msg3[6]={3、6、9、12、15、 18};

uint8_t g_pui8Msg4[8]={4、8、12、16、20、 24、28、32 };

//

//

//此函数将 UART0设置为用于控制台显示信息

//因为示例正在运行。

//

//

无效

InitConsole (空)

  //

  //启用用于 UART0引脚的 GPIO 端口 A。

  // TODO:将其更改为您正在使用的 GPIO 端口。

  //

  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

  //

  //为端口 A0和 A1上的 UART0功能配置引脚复用。

  //如果您的器件不支持引脚复用、则无需执行此步骤。

  // TODO:更改此选项以选择您正在使用的端口/引脚。

  //

  GPIOPinConfigure (GPIO_PA0_U0RX);

  GPIOPinConfigure (GPIO_PA1_U0TX);

  //

  //启用 UART0以便我们可以配置时钟。

  //

  SysCtlPeripheralEnable (SYSCTL_Periph_UART0);

  //

  //使用内部16MHz 振荡器作为 UART 时钟源。

  //

  UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);

  //

  //为这些引脚选择替代(UART)功能。

  // TODO:更改此选项以选择您正在使用的端口/引脚。

  //

  GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);

  //

  //初始化控制台 I/O 的 UART

  //

  UARTStdioConfig (0、115200、16000000);

//

//

//此函数将有关 CAN 消息的一些信息打印到

//串行端口仅供参考。

//

//

无效

PrintCANMessageInfo (tCANMsgObject * psCANMsg、uint32_t ui32MsgObj)

  unsigned int uIdx;

  UARTprintf ("发送 msg:obj=%d Id=0x%04X msg=0x"、ui32MsgObj、

        psCANMsg->ui32MsgID);

  for (uIdx = 0;uIdx < psCANMsg->ui32MsgLen;uIdx++)

  {

    UARTprintf ("%02x "、psCANMsg->pui8MsgData[uIdx]);

  }

  UARTprintf ("\n");

//

//

//此函数使用简单的轮询方法提供1秒的延迟。

//

//

无效

SimpleDelay (空)

  //

  //延迟周期1秒

  //

  SysCtlDelay (16000000 / 3);

//

//

//此函数是 CAN 外设的中断处理程序。  它会进行检查

//查找中断原因,并保留所有消息的计数

//已传输。

//

//

无效

CANIntHandler (空)

  uint32_t ui32Status;

  //

  //读取 CAN 中断状态以查找中断原因

  //

  ui32Status = CANIntStatus (CAN1_base、CAN_INT_STS_CAUST);

  //

  //如果原因是控制器状态中断,则获取状态

  //

  if (ui32Status = CAN_INT_INTID_STATUS)

  {

    //

    //读取控制器状态。  这将返回状态字段

    //可以指示各种错误的错误位。  错误处理

    //本示例中不是为了简单起见。  请参阅

    // API 文档,了解有关错误状态位的详细信息。

    //读取此状态的操作将清除中断。  如果

    // CAN 外设未与其它 CAN 器件连接到 CAN 总线

    //存在,则会发生错误,并在中指示

    //控制器状态。

    //

    ui32Status = CANStatusGet (CAN1_base、CAN_STS_CONTROL);

    //

    //设置一个标志来指示可能发生的某些错误。

    //

    G_bErrFlag = 1;

  }

  //

  //检查原因是否为用于发送的消息对象1

  //消息1.

  //

  否则、如果(ui32Status = 1)

  {

    //

    //到达这一点意味着 TX 中断发生在上

    //消息对象1、消息 TX 完成。  清除

    //消息目标中断。

    //

    CANIntClear (CAN1_base、1);

    //

    //递增计数器以跟踪已有多少消息

    //已发送。  在实际应用中、这可用于将标志设置为

    //指示何时发送消息。

    //

    G_ui32Msg1Count++;

    //

    //由于消息已发送,请清除所有错误标志。

    //

    G_bErrFlag = 0;

  }

  //

  //检查原因是否是用于发送的消息对象2

  //消息2.

  //

  否则 if (ui32Status = 2)

  {

    //

    //到达这一点意味着 TX 中断发生在上

    //消息对象2、消息 TX 完成。  清除

    //消息目标中断。

    //

    CANIntClear (CAN1_base、2);

    //

    //递增计数器以跟踪已有多少消息

    //已发送。  在实际应用中、这可用于将标志设置为

    //指示何时发送消息。

    //

    G_ui32Msg2Count++;

    //

    //由于消息已发送,请清除所有错误标志。

    //

    G_bErrFlag = 0;

  }

  //

  //检查原因是否是用于发送的消息对象3

  //消息3和4。

  //

  否则 if (ui32Status = 3)

  {

    //

    //到达这一点意味着 TX 中断发生在上

    //消息对象3、消息 TX 完成。  清除

    //消息目标中断。

    //

    CANIntClear (CAN1_base、3);

    //

    //递增计数器以跟踪已有多少消息

    //已发送。  在实际应用中、这可用于将标志设置为

    //指示何时发送消息。

    //

    G_ui32Msg3Count++;

    //

    //设置指示使用消息发送消息的标志

    //对象3.  程序主循环使用此函数来知道何时发送

    //使用消息对象3的另一条消息。

    //

    G_bMsgObj3Sent = 1;

    //

    //由于消息已发送,请清除所有错误标志。

    //

    G_bErrFlag = 0;

  }

  //

  //否则,发生意外导致中断的情况。  这应该是

  //永远不会发生。

  //

  其他

  {

    //

    //可以在此处执行伪中断处理。

    //

  }

//

//

//配置 CAN 并输入循环以传输周期性 CAN 消息。

//

//

内部

main (空)

  uint32_t ui32SysClock;

  ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_16MHz |

                         SYSCTL_OSC_INT |

                         SYSCTL_USE_PLL |

                         SYSCTL_CFG_VCO_480)、120000000);

  //

  //设置用于显示消息的串行控制台。  这是

  //仅针对此示例程序,CAN 操作不需要。

  //

  InitConsole();

  //

  //对于此示例、CAN1与端口 B4和 B5上的 RX 和 TX 引脚一起使用。

  //您使用的实际端口和引脚可能有所不同,请参阅

  //数据表以了解更多信息。

  // GPIO 端口 B 需要启用、以便可以使用这些引脚。

  // TODO:将其更改为您正在使用的 GPIO 端口

  //

  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);

  //

  //配置 GPIO 引脚复用以选择这些引脚的 CAN1功能。

  //此步骤选择可用于这些引脚的替代功能。

  //如果您的器件支持 GPIO 引脚功能多路复用、这是必需的。

  //请查阅数据表以查看每个引脚分配的函数。

  // TODO:更改此选项以选择您正在使用的端口/引脚

  //

  GPIOPinConfigure (GPIO_PB0_CAN1RX);

  GPIOPinConfigure (GPIO_PB1_CAN1TX);

  //

  //启用 GPIO 引脚上的复用功能。  以上步骤选择

  //可用的备用功能。  此步骤实际上启用

  //这些引脚的替代功能、而不是 GPIO。

  //待办事项:更改此项以匹配您正在使用的端口/引脚

  //

  GPIOPinTypeCAN (GPIO_PORTB_BASE、GPIO_PIN_0 | GPIO_PIN_1);

  //

  //已为 CAN 设置 GPIO 端口和引脚。  CAN 外设

  //必须启用。

  //

  SysCtlPeripheralDisable (SYSCTL_Periph_CAN1);

  SysCtlPeripheralReset (SYSCTL_Periph_CAN1);

  SysCtlPeripheralEnable (SYSCTL_Periph_CAN1);

  //

  //初始化 CAN 控制器

  //

  CANInit (CAN1_base);

  //

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

  针对标称配置的//总线时序。  您可以实现更多控制

  //使用函数 CANBitTimingSet()代替 CAN 总线时序

  //如果需要。

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

  //对 SysCtlClockGet ()的调用用于确定该时钟速率

  //用于为 CAN 外设计时。  可将其替换为

  //固定值如果您知道系统时钟的值,则节省额外的值

  //函数调用。  对于某些器件、CAN 外设采用固定计时

  // 8MHz,无论在哪种情况下调用的系统时钟如何

  // SysCtlClockGet ()应替换为80000。  请查阅数据

  //表以了解有关 CAN 外设计时的更多信息。

  //

  CANBitRateSet (CAN1_base、ui32SysClock、50000);

  //

  //在 CAN 外设上启用中断。  此示例使用静态

  //分配中断处理程序,表示处理程序的名称

  //位于启动代码的矢量表中。  如果您想使用动态的

  //分配矢量表,然后还必须调用 CANIntRegister()

  //此处。

  //

  CANIntRegister (CAN1_base、CANIntHandler);// if using dynamic vectors

  //

  CANIntEnable (CAN1_base、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

  //

  //在处理器(NVIC)上启用 CAN 中断。

  //

  IntEnable (INT_CAN1);

  //

  //启用 CAN 以进行操作。

  //

  CANEnable (CAN1_base);

  //

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

  //消息。  消息将是包含一个递增的4个字节

  //值。  最初它将设置为0。

  //

  //

  //初始化报文对象1以能够发送 CAN 报文1。  这种情况

  //消息对象不是共享的,因此只需要初始化一个

  //时间,和可用于重复发送相同的消息 ID。

  //

  G_sCANMsgObject1.ui32MsgID = 0x1001;

  G_sCANMsgObject1.ui32MsgIDMask = 0;

  G_sCANMsgObject1.ui32Flags = MSG_OBJ_TX_INT_ENABLE;

  G_sCANMsgObject1.ui32MsgLen = sizeof (g_pui8Msg1);

  G_sCANMsgObject1.pui8MsgData = g_pui8Msg1;

  //

  //初始化报文对象2以便能够发送 CAN 报文2.  这种情况

  //消息对象不是共享的,因此只需要初始化一个

  //时间,和可用于重复发送相同的消息 ID。

  //

  G_sCANMsgObject2.ui32MsgID = 0x2001;

  G_sCANMsgObject2.ui32MsgIDMask = 0;

  G_sCANMsgObject2.ui32Flags = MSG_OBJ_TX_INT_ENABLE;

  G_sCANMsgObject2.ui32MsgLen = sizeof (g_pui8Msg2);

  G_sCANMsgObject2.pui8MsgData = g_pui8Msg2;

  //

  //输入循环以发送消息。  每个将发送四条消息一次

  //秒。  每次都将更改每条消息的内容。

  //

  for (;;)

  {

    //

    //使用 CAN 控制器报文对象1发送报文1。  这是

    //使用此消息对象发送的唯一消息。  。

    // CANMessageSet()函数将导致消息被正确发送

    //离开。

    //

    PrintCANMessageInfo (&g_sCANMsgObject1、1);

    CANMessageSet (CAN1_base、1、&g_sCANMsgObject1、MSG_OBJ_TYPE_TX);

    UARTprintf ("%d\n"、g_ui32Msg1Count);

    //

    //使用 CAN 控制器报文对象2发送报文2。  这是

    //使用此消息对象发送的唯一消息。  。

    // CANMessageSet()函数将导致消息被正确发送

    //离开。

    //

    PrintCANMessageInfo (&g_sCANMsgObject2、2);

    CANMessageSet (CAN1_base、2、&g_sCANMsgObject2、MSG_OBJ_TYPE_TX);

    UARTprintf ("%d\n"、g_ui32Msg2Count);

    //

    //加载带有消息3的消息对象3。  这需要逐一完成

    //时间,因为消息对象3共享两个不同的消息对象

    //消息。

    //

    G_sCANMsgObject3.ui32MsgID = 0x3001;

    G_sCANMsgObject3.ui32MsgIDMask = 0;

    G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;

    G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg3);

    G_sCANMsgObject3.pui8MsgData = g_pui8Msg3;

    //

    //清除指示消息3已发送的标志。  这种情况

    当一个消息已经被置位时、//标志将在中断处理程序中被置位

    //使用消息对象3发送。

    //

    G_bMsgObj3Sent = 0;

    //

    //现在使用 CAN 控制器报文对象3发送报文3。  这是

    //使用此消息对象发送的第一条消息。  。

    // CANMessageSet()函数将导致消息被正确发送

    //离开。

    //

    PrintCANMessageInfo (&g_sCANMsgObject3、3);

    CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);

    //

    //等待中断处理程序发出该消息的指示

    //对象3已完成,因为我们要将其重新用于另一条消息。

    //

     while (!g_bMsgObj3Sent)

    {

    }

     UARTprintf ("%d\n"、g_ui32Msg3Count);  

    //

    //加载带有消息4的消息对象3。  之所以需要这样做、是因为

    //消息对象3正在共享两个不同的消息。

    //

    G_sCANMsgObject3.ui32MsgID = 0x3002;

    G_sCANMsgObject3.ui32MsgIDMask = 0;

    G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;

    G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg4);

    G_sCANMsgObject3.pui8MsgData = g_pui8Msg4;

    //

    //现在使用 CAN 控制器报文对象3发送报文4。  这是

    //使用此消息对象发送的第二条消息。  。

    // CANMessageSet()函数将导致消息被正确发送

    //离开。

    //

    PrintCANMessageInfo (&g_sCANMsgObject3、3);

    CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);

  }

  //

  //返回无错误

  //

  //返回(0);

上述代码的结果为:  

请注意代码中以红色字体显示的行。

当  UARTprintf ("%d\n"、g_ui32Msg3Count)在  while (!g_bMsgObj3Sent){ }之后包含时、便会接收到上面的 putty 中的内容  

但是、如果我   在 while (!g_bMsgObj3Sent){ }之前包含 UARTprintf ("%d\n"、g_ui32Msg3Count)、 我将在 putty 中获得以下结果:  

因此程序执行似乎停留在 while 循环中: while (!g_bMsgObj3Sent){ }

该程序旨在 重复使用消息对象发送多个数据。

是否有任何补救措施?

// //// multi_TX.c -演示多个 CAN 消息的外设示例//        传输。///版权所有(c) 2010-2014德州仪器(TI)公司。  保留所有权利。//软件许可协议//// 重新分发和以源代码和二进制形式使用,无论是否 修改,只要 满足以下条件//://// 重新分发源代码必须保留上述版权// 声明, 本条件列表和以下免责声明。//// 二进制形式的再发行必须复制上述版权// 声明, // 文档和/或 随//分发提供的其他材料中的此条件列表和以下免责声明。//// 未经  特定的事先书面许可,不得使用德州仪器公司的名称或//其贡献者的名称来认可或推广源自此软件的产品。////本软件 由版权所有者和贡献者提供//"按原样"、不承认任何明示或暗示的保证、包括但不限于对适销性和对//特定用途适用性的暗示保证。 在任何情况下、版权//所有者或贡献者都不对任何直接、间接、意外、//特殊、示例或结果性损害(包括但不限于采购替代产品或服务;丧失使用能力//数据或利润)承担任何责任; 或业务中断)、以及任何责任理论、包括合同、严格责任、 或 TORT//(包括疏忽或其他原因)、以任何方式使用本软件引起、即使被告知可能会发生此类损坏。///这是 Tiva 固件开发包版本2.1.0.12573的一部分。//*********
#include #include #include "inc/hw_ca.h"#include "inc/hw_ints.h"#include "inc/hw_memmap.h"#include "driverlib/ca.h"#include "driverlib/gpio.h"#include "driverlib/interrupt.h"#include "driverlib/pin_map.h"dio#include "driverlib/utils/disdio.truarts.h"
// ////! addtogroup CAN_examples_list//!

多 CAN TX (MULTI_TX)

//!//! 此示例显示了如何设置 CAN 以发送多条消息。  //! CAN 外设配置为发送具有4个不同 CAN ID 的消息。//! 使用共享//!发送两条消息(具有不同的 CAN ID) 消息目标。  这显示了如何将消息对象重复用于 multiple/! 消息。  其他两条消息使用其自己的消息对象发送。//! 所有四条消息每秒传输一次。  每个//的内容! 消息是测试模式。  CAN 中断处理程序用于确认//! 消息传输并计算已发送的消息数。//!//! 此示例使用以下外设和 I/O 信号。  您必须//! 查看这些内容并根据您自己的董事会的需要进行更改://! - CAN1外设//! - GPIO 端口 B 外设(用于 CAN1引脚)//! - CAN1RX - PB0//! - CAN1TX - PB1//!//! 以下 UART 信号仅配置为显示 console//! 消息。  这些不是 CAN 操作所必需的。//! - GPIO 端口 A 外设(用于 UART0引脚)//! - UART0RX - PA0//! - UART0TX - PA1//!//! 此示例使用以下中断处理程序。  要使用此示例//! 在您自己的应用程序中、您必须将这些中断处理程序添加到您的//! 矢量表。//! - INT_CAN1 - CANIntHandler///*********
// ////一个跟踪 TX 中断次数的计数器//发生,该计数器应与发送的 TX 消息数相匹配。/// volatile uint32_t g_ui32IntCount = 0;
// ////用于计算每个//本示例中使用的三个消息对象上的消息数的计数器。/// volatile uint32_t g_ui32Msg1Count = 0;volatile uint32_t g_ui32Msg2Count = 0;volatile uint32_t g_ui32Msg3Count = 0;
// ////指示 CAN 控制器报文对象3已发送报文的标志。//********* volatile bool g_bMsgObj3Sent = 0;
// ////指示发生了某些传输错误的标志。//********* volatile bool g_BErrFlag = 0;
// ////将保存单独 CAN 消息的 CAN 消息对象。  这些也可以/也可以在堆栈上分配、但要小心、因为这些结构//每个都需要大约20字节。//********* tCANMsgObject g_sCANMsgObject1;tCANMsgObject g_sCANMsgObject2;tCANMsgObject g_sCANMsgObject3;
// ////保存正在发送的4个不同消息内容的消息缓冲器。  每个都是不同的长度。//********* uint8_t g_pui8Msg1[4]={1、3、5、7};uint8_t g_pui8Msg2[5]={2、4、6、8、10};uint8_t g_pui8Msg3[6]={3、6、9、12、15、 18};uint8_t g_pui8Msg4[8]={4、8、12、16、20、 24、28、32 };
// ////此函数将 UART0设置为用于控制台,以便在示例运行时显示信息//。//************* voidInitConsole (void){  //  //启用用于 UART0引脚的 GPIO 端口 A。   // TODO:将其更改为您正在使用的 GPIO 端口。   //  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
  //  //为端口 A0和 A1上的 UART0功能配置引脚复用。   //如果您的器件不支持引脚复用、则无需执行此步骤。   // TODO:更改此选项以选择您正在使用的端口/引脚。   //  GPIOPinConfigure (GPIO_PA0_U0RX);  GPIOPinConfigure (GPIO_PA1_U0TX);
  //  //启用 UART0,以便我们可以配置时钟。   //  SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
  //  //使用内部16MHz 振荡器作为 UART 时钟源。   //  UARTClockSourceSet (UART0_BASE、UART_CLOCK _PIOSC);
  //  //选择这些引脚的替代(UART)功能。   // TODO:更改此选项以选择您正在使用的端口/引脚。   //  GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
  //  //初始化控制台 I/O 的 UART   //  UARTStdioConfig (0、115200、16000000);}
// ////此函数将有关 CAN 消息的一些信息打印到//串行端口,仅供参考。//********* voidPrintCANMessageInfo (tCANMsgObject * psCANMsg、uint32_t ui32MsgObj){  unsigned int uIdx;
  UARTprintf ("发送 msg:obj=%d Id=0x%04X msg=0x"、ui32MsgObj、         psCANMsg->ui32MsgID);  for (uIdx = 0;uIdx < psCANMsg->ui32MsgLen;uIdx++)  {     UARTprintf ("%02x "、psCANMsg->pui8MsgData[uIdx]);  }  UARTprintf ("\n");}
// ////此函数使用简单的轮询方法提供1秒的延迟。/// voidSimpleDelay (void){  //  //延迟周期1秒  //  SysCtlDelay (16000000 / 3);}
// ////此函数是 CAN 外设的中断处理程序。  它检查中断原因、并对所有已发送的消息进行计数。/// voidCANIntHandler (void){  uint32_t ui32Status;
  //  //读取 CAN 中断状态以查找中断原因  //  ui32Status = CANIntStatus (CAN1_base、CAN_INT_STS_CAUST);
  //  //如果原因是控制器状态中断,则获取状态  //  if (ui32Status == CAN_INT_INTID_STATUS)  {     //     //读取控制器状态。  这将返回状态字段     //可以指示各种错误的错误位。  错误处理     //本示例中不是为了简单起见。  请参阅     // API 文档,了解有关错误状态位的详细信息。     //读取此状态的操作将清除中断。  如果     // CAN 外设未与其它 CAN 器件连接到 CAN 总线     //存在,则会发生错误,并在中指示     //控制器状态。     //     ui32Status = CANStatusGet (CAN1_base、CAN_STS_CONTROL);
    //     //设置一个标志来指示可能发生的某些错误。     //     G_bErrFlag = 1;  }
  //  //检查原因是否为用于发送  //消息1的消息对象1。   //  否则 if (ui32Status = 1)  {     //     //到达这一点意味着 TX 中断发生在上     //消息对象1、消息 TX 完成。  清除     //消息目标中断。     //     CANIntClear (CAN1_base、1);
    //     //递增计数器以跟踪已有多少消息     //已发送。  在实际应用中、这可用于将标志设置为     //指示何时发送消息。     //     G_ui32Msg1Count++;
    //     //由于消息已发送,请清除所有错误标志。     //     G_bErrFlag = 0;  }
  //  //检查原因是否是用于发送  //消息2的消息对象2。   //  否则 if (ui32Status = 2)  {     //     //到达这一点意味着 TX 中断发生在上     //消息对象2、消息 TX 完成。  清除     //消息目标中断。     //     CANIntClear (CAN1_base、2);
    //     //递增计数器以跟踪已有多少消息     //已发送。  在实际应用中、这可用于将标志设置为     //指示何时发送消息。     //     G_ui32Msg2Count++;
    //     //由于消息已发送,请清除所有错误标志。     //     G_bErrFlag = 0;  }
  //  //检查原因是否是用于发送  //消息3和4的消息对象3。   //  否则 if (ui32Status = 3)  {     //     //到达这一点意味着 TX 中断发生在上     //消息对象3、消息 TX 完成。  清除     //消息目标中断。     //     CANIntClear (CAN1_base、3);
    //     //递增计数器以跟踪已有多少消息     //已发送。  在实际应用中、这可用于将标志设置为     //指示何时发送消息。     //     G_ui32Msg3Count++;
    //     //设置指示使用消息发送消息的标志     //对象3.  程序主循环使用此函数来知道何时发送     //使用消息对象3的另一条消息。     //     G_bMsgObj3Sent = 1;
    //     //由于消息已发送,请清除所有错误标志。     //     G_bErrFlag = 0;  }
  //  //否则,意外的情况导致中断。  这应该  //永远不会发生。   //  否则  {     //     //可以在此处执行伪中断处理。     //  }
// ////配置 CAN 并输入循环以传输周期性 CAN 消息。///********* intmain (void){  uint32_t ui32SysClock;
  ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_16MHz |                          SYSCTL_OSC_INT |                          SYSCTL_USE_PLL |                          SYSCTL_CFG_VCO_480)、120000000);  //  设置串行控制台以用于显示消息。  这只是  针对这个示例程序的//、而 CAN 操作不需要。   //  InitConsole();
  //  //对于此示例、CAN1与端口 B4和 B5上的 RX 和 TX 引脚一起使用。   //您的器件上使用的实际端口和引脚可能不同,请参阅  //数据表以了解更多信息。   // GPIO 端口 B 需要启用、以便可以使用这些引脚。   // TODO:将其更改为您使用的任何 GPIO 端口  //  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
  //  //配置 GPIO 引脚复用以选择这些引脚的 CAN1功能。   //此步骤选择可用于这些引脚的替代功能。   //如果您的器件支持 GPIO 引脚功能多路复用、这是必需的。   //请查阅数据表以查看每个引脚分配的函数。   // TODO:将此选项更改为选择您正在使用的端口/引脚  //  GPIOPinConfigure (GPIO_PB0_CAN1RX);  GPIOPinConfigure (GPIO_PB1_CAN1TX);
  //  //启用 GPIO 引脚上的复用功能。  以上步骤选择  //可用的备用功能。  这一步实际上启用  了这些引脚的//替代功能、而不是 GPIO。   // TODO:更改此项以匹配您正在使用的端口/引脚  //  GPIOPinTypeCAN (GPIO_PORTB_BASE、GPIO_PIN_0 | GPIO_PIN_1);
  //  //已为 CAN 设置 GPIO 端口和引脚。  必须  启用 CAN 外设//。   //  SysCtlPeripheralDisable (SYSCTL_Periph_CAN1);  SysCtlPeripheralReset (SYSCTL_Periph_CAN1);  SysCtlPeripheralEnable (SYSCTL_Periph_CAN1);
  //  //初始化 CAN 控制器  //  CANInit (CAN1_base);
  //  //设置 CAN 总线的位速率。  此函数为  标称配置设置 CAN //总线时序。  如果    需要,可以使用函数 CANBitTimingSet()代替这个函数//来实现对 CAN 总线时序的更多控制。   //在此示例中、CAN 总线设置为500kHz。  在下面的函数中、  //对 SysCtlClockGet ()的调用被用来确定//用来  为 CAN 外设计时的时钟速率。    如果您知道系统时钟的值、则可以将其替换为//固定值、从而节省额外  的//函数调用。  对于某些器    件、CAN 外设的时钟是固定的// 8MHz、与系统时钟无关、在这种情况下、对// SysCtlClockGet ()的调用应该被8000000取代。  有关  CAN 外设时钟的更多信息、请参阅数据//表。   //  CANBitRateSet (CAN1_base、ui32SysClock、50000);
  //  //在 CAN 外设上启用中断。  此示例使用静态  //分配中断处理程序、这意味着处理程序的名称  //位于启动代码的矢量表中。  如果要使用  矢量表的动态//分配,则还必须在  此处调用 CANIntRegister()//。   //  CANIntRegister (CAN1_base、CANIntHandler);//如果使用动态矢量  //  CANIntEnable (CAN1_base、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
  //  //启用处理器(NVIC)上的 CAN 中断。   //  IntEnable (INT_CAN1);
  //  //启用 CAN 以进行操作。   //  CANEnable (CAN1_base);
  //  //初始化将用于发送 CAN  //消息的消息对象。  消息将是包含一  个递增//值的4个字节。  最初它将设置为0。   //
  //  //初始化报文对象1,以便能够发送 CAN 报文1。  此  //消息对象不是共享的,因此只需要初始化一次  //,并且可以用于重复发送相同的消息 ID。   //  g_sCANMsgObject1.ui32MsgID = 0x1001;  g_sCANMsgObject1.ui32MsgIDMask = 0;  g_sCANMsgObject1.ui32Flags = MSG_OBJ_TX_INT_ENABLE;  g_sCANMsgObject1.ui32MsgLen = e8g_iData=e8g_i8g_iMsg1  ;gi8g_i_gi1


  //  //初始化报文对象2以便能够发送 CAN 报文2.  此  //消息对象不是共享的,因此只需要初始化一次  //,并且可以用于重复发送相同的消息 ID。   //  g_sCANMsgObject2.ui32MsgID = 0x2001;  g_sCANMsgObject2.ui32MsgIDMask = 0;  g_sCANMsgObject2.ui32Flags = MSG_OBJ_TX_INT_ENABLE;  g_sCANMsgObject2.ui32MsgLen = e8g_i2;  giMsg2 = e8gi2;
  //  //输入循环以发送消息。  每  //秒将发送四条消息。  每次都将更改每条消息的内容。   //  for (;;)  {     //     //使用 CAN 控制器报文对象1发送报文1。  这是     //使用此消息对象发送的唯一消息。  。     // CANMessageSet()函数将导致消息被正确发送     //离开。     //     PrintCANMessageInfo (&g_sCANMsgObject1、1);     CANMessageSet (CAN1_base、1、&g_sCANMsgObject1、MSG_OBJ_TYPE_TX);
    //     //使用 CAN 控制器报文对象2发送报文2。  这是     //使用此消息对象发送的唯一消息。  。     // CANMessageSet()函数将导致消息被正确发送     //离开。     //     PrintCANMessageInfo (&g_sCANMsgObject2、2);     CANMessageSet (CAN1_base、2、&g_sCANMsgObject2、MSG_OBJ_TYPE_TX);
    //     //加载带有消息3的消息对象3。  这需要逐一完成     //时间,因为消息对象3共享两个不同的消息对象     //消息。     //     G_sCANMsgObject3.ui32MsgID = 0x3001;     G_sCANMsgObject3.ui32MsgIDMask = 0;     G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;     G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg3);     G_sCANMsgObject3.pui8MsgData = g_pui8Msg3;
    //     //清除指示消息3已发送的标志。  这种情况     当一个消息已经被置位时、//标志将在中断处理程序中被置位     //使用消息对象3发送。     //     G_bMsgObj3Sent = 0;
    //     //现在使用 CAN 控制器报文对象3发送报文3。  这是     //使用此消息对象发送的第一条消息。  。     // CANMessageSet()函数将导致消息被正确发送     //离开。     //     PrintCANMessageInfo (&g_sCANMsgObject3、3);     CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);
    //     //等待中断处理程序发出该消息的指示     //对象3已完成,因为我们要将其重新用于另一条消息。     //     while (!g_bMsgObj3Sent)     {    }
    //     //加载带有消息4的消息对象3。  之所以需要这样做、是因为     //消息对象3正在共享两个不同的消息。     //     G_sCANMsgObject3.ui32MsgID = 0x3002;     G_sCANMsgObject3.ui32MsgIDMask = 0;     G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;     G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg4);     G_sCANMsgObject3.pui8MsgData = g_pui8Msg4;
    //     //现在使用 CAN 控制器报文对象3发送报文4。  这是     //使用此消息对象发送的第二条消息。  。     // CANMessageSet()函数将导致消息被正确发送     //离开。     //
    PrintCANMessageInfo (&g_sCANMsgObject3、3);     CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);



  }


  //  ////返回无错误  //  //// return (0);}

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

    尊敬的先生:

    请编辑您的原始帖子、以使其更清晰、并避免被忽略的风险。 几乎不可能在其中找到一个问题。

    -剪切代码,使用将其粘贴 格式栏的按钮。

    -擦除图形后面的数百条连续代码行

    可能只考虑过帐代码的相关部分

    谢谢你

    布鲁诺

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

    我正在尝试为 CAN Tx 侧调试以下代码。 我  已使用 USB 并使用 PuTTy 通过 UART 查看结果、将 EK-TM4C1294XL 板连接到 PC。

    我正在运行的代码如下:

    #include 
    #include 
    #include "inc/hw_ca.h"
    #include "volatile/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/ca.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    
    #include "driverlib/pintru32_itude_intru32"
    
    
    
    
    
    
    ;include "volatile dio_u32uitude_intru32u_uidu_u.u.ut
    = 32nuidi20_intru_u_u.u32u_intru_uidu_u32u_u.u.u.u.idu.u.u.u32ut = volt_u32uidu.u.u.u.u32uuuuuu.idu.u.u32u.u.u.u.u.u.u32u.uidio t = volatile u.uidi20_u.u.u.u.u.u.u.
    
    
    volatile bMsg_BMsgFlag = 0;
    
    
    tCANMsgObject g_sCANMsgObject1;
    tCANMsgObject g_sCANMsgObject2
    
    
    ;tCANMsgObject g_sCANMsgObject3;uint8_t g_pui8Msg1[4]={1、3、5、7};uint8_t 8、i8
    ={2、i8}
    uint8_t g_pui8Msg3[6]={3、6、9、12、15、 18};
    uint8_t g_pui8Msg4[8]={4、8、12、16、20、 24、28、32};
    
    void InitConsole (void)
    {
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig (0、115200、16000000);
    }
    
    
    void PrintCANMessageInfo (tCANMsgObject * psCANMsg、uint32_t ui32MsgObj)
    {
    unsigned int uIdx;
    UARTprintf ("发送 msg:obj=%d ID=0x%04X msg=0x"、ui32MsgObj、psCANMsg->ui32MsgID);
    
    for (uIdx = 0;uIdx < psCANMsg->ui32MsgLen;uIdx++)
    {
    UARTprintf ("%02x "、psCANMsg->pui8MsgData[uIdx]);
    }
    UARTprintf ("\n");
    }
    
    
    void SimpleDelay (void)
    {
    SysCtlDelay (16000000 / 3);
    
    }
    
    void CANIntHandler (void)
    {
    
    uint32_t ui32Status;
    
    ui32Status = CANIntStatus (CAN1_base、CAN_INT_STS_CAUST);
    
    if (ui32Status = CAN_INT_INTID_STATUS)
    {
    
    ui32Status = CANStatusGet (CAN1_base、CAN_STS_CONTROL);
    G_bErrFlag = 1;
    }
    
    否则、如果(ui32Status = 1)
    {
    CANIntClear (CAN1_base、1);
    G_ui32Msg1Count++;
    G_bErrFlag = 0;
    }
    
    否则 if (ui32Status = 2)
    {
    CANIntClear (CAN1_base、2);
    G_ui32Msg2Count++;
    G_bErrFlag = 0;
    }
    
    否则 if (ui32Status = 3)
    {
    
    CANIntClear (CAN1_base、3);
    G_ui32Msg3Count++;
    G_bMsgObj3Sent = 1;
    G_bErrFlag = 0;
    }
    
    }
    
    
    int main (void)
    {
    
    uint32_t ui32SysClock;
    ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_16MHz | SYSCTL_OSC_INT | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、120000000);
    
    InitConsole();
    
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
    GPIOPinConfigure (GPIO_PB0_CAN1RX);
    GPIOPinConfigure (GPIO_PB1_CAN1TX);
    GPIOPinTypeCAN (GPIO_PORTB_BASE、GPIO_PIN_0 | GPIO_PIN_1);
    SysCtlPeripheralDisable (SYSCTL_Periph_CAN1);
    SysCtlPeripheralReset (SYSCTL_Periph_CAN1);
    SysCtlPeripheralEnable (SYSCTL_Periph_CAN1);
    CANInit (CAN1_base);
    CANBitRateSet (CAN1_base、ui32SysClock、50000);
    CANIntRegister (CAN1_base、CANIntHandler);
    CANIntEnable (CAN1_base、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    IntEnable (INT_CAN1);
    CANEnable (CAN1_base);
    
    G_sCANMsgObject1.ui32MsgID = 0x1001;
    G_sCANMsgObject1.ui32MsgIDMask = 0;
    G_sCANMsgObject1.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    G_sCANMsgObject1.ui32MsgLen = sizeof (g_pui8Msg1);
    G_sCANMsgObject1.pui8MsgData = g_pui8Msg1;
    
    G_sCANMsgObject2.ui32MsgID = 0x2001;
    G_sCANMsgObject2.ui32MsgIDMask = 0;
    G_sCANMsgObject2.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    G_sCANMsgObject2.ui32MsgLen = sizeof (g_pui8Msg2);
    G_sCANMsgObject2.pui8MsgData = g_pui8Msg2;
    
    for (;;)
    {
    PrintCANMessageInfo (&g_sCANMsgObject1、1);
    CANMessageSet (CAN1_base、1、&g_sCANMsgObject1、MSG_OBJ_TYPE_TX);
    UARTprintf ("%d\n"、g_ui32Msg1Count);
    
    PrintCANMessageInfo (&g_sCANMsgObject2、2);
    CANMessageSet (CAN1_base、2、&g_sCANMsgObject2、MSG_OBJ_TYPE_TX);
    UARTprintf ("%d\n"、g_ui32Msg2Count);
    
    G_sCANMsgObject3.ui32MsgID = 0x3001;
    G_sCANMsgObject3.ui32MsgIDMask = 0;
    G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg3);
    G_sCANMsgObject3.pui8MsgData = g_pui8Msg3;
    
    G_bMsgObj3Sent = 0;
    
    PrintCANMessageInfo (&g_sCANMsgObject3、3);
    CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);
    
    while (!g_bMsgObj3Sent)
    {
    }
    
    UARTprintf ("%d\n"、g_ui32Msg3Count);
    
    G_sCANMsgObject3.ui32MsgID = 0x3002;
    G_sCANMsgObject3.ui32MsgIDMask = 0;
    G_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    G_sCANMsgObject3.ui32MsgLen = sizeof (g_pui8Msg4);
    G_sCANMsgObject3.pui8MsgData = g_pui8Msg4;
    
    PrintCANMessageInfo (&g_sCANMsgObject3、3);
    
    CANMessageSet (CAN1_base、3、&g_sCANMsgObject3、MSG_OBJ_TYPE_TX);
    }
    
    } 

    当  UARTprintf ("%d\n"、g_ui32Msg3Count)在   while (!g_bMsgObj3Sent){之后包含时,将接收到 Putty 中的上述内容  。

    但是、如果我   在 while (!g_bMsgObj3Sent){ }之前包含 UARTprintf ("%d\n"、g_ui32Msg3Count)、  我将在 Putty 中获得以下结果:  

    因此程序执行似乎停留在 while 循环中: while (!g_bMsgObj3Sent){ }

    for 循环不会无限执行。 什么是补救措施?

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

    两个屏幕盖 都提供(仅)~10%的可用数据(对比度非常差!) -休息是无用的。   (这掩盖了您的关键发现-这是不好的!) 您可以通过在屏幕保护盖上执行"第二次操作"来纠正这种情况-(将其编辑为基本功能-巨大的死区/"黑"空间不提供任何价值!)   并选择对比度更高/更明亮(即可读)的屏幕颜色。

    请记住、(许多)海报在此处出现"寻求帮助"-您必须(部分)努力"推销您的帖子"、以便它得到足够的关注...   (可读性确实很重要!)

    [引用用户="Jayakrishnan Krishna Prasad"]

    因此程序执行似乎停留在 while 循环中: while (!g_bMsgObj3Sent){ }

    for 循环不会无限执行。   什么是补救措施?

    [/报价]

    至于您的代码审核-我发现"while loop"-但没有(包含)"for loop"-您建议它存在不是(完全)执行!