我正在尝试为 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);}



