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.

[参考译文] TM4C123GH6PM:使用 FIFO 的 CAN

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/886550/tm4c123gh6pm-can-using-fifo

n´t、我想将´sn´t 与 FIFO 缓冲区一起使用、但我不知道如何处理它。我从 Tiva 用户指南中获取了这个示例、并且我无法完全理解数据的读取方式、最后一行使用指向 MsgObjectRx 的 CANMessageGet、 它是否应该将缓冲区传递给 MsgObjectRx 的对象n´t´s 数据成员。我还可以使用其他示例吗?

tCANBitClkParms CANBitClk;
tCANMsgObject sMsgObjectRx;
tCANMsgObject sMsgObjectTx;
uint8_t pui8BufferIn[8];
uint8_t pui8BufferOut[8];
//
//启用 CAN0模块。
//
SysCtlPeripheralEnable (SYSCTL_Periph_CAN0);
//
//等待 CAN0模块准备就绪。
//
while (!SysCtlPeripheralReady (SYSCTL_Periph_CAN0)){}
//
//启用 CAN1模块。
//
SysCtlPeripheralEnable (SYSCTL_Periph_CAN1);
//
//等待 CAN1模块准备就绪。
//
while (!SysCtlPeripheralReady (SYSCTL_Periph_CAN1)){}
//
//将所有消息对象的状态和 CAN
//模块的状态重置为已知状态。
//
CANInit (CAN0_BASE);
CANInit (CAN1_BASE);
//
将控制器配置为1Mbit 运行。
//
CANSetBitTiming (CAN1_base、&CANBitClk);
//
//使 CAN0器件退出初始化状态。
//
CANEnable (CAN0_BASE);
CANEnable (CAN1_BASE);
//
//配置接收对象。
//
sMsgObjectRx.ulMsgID =(0x400);
sMsgObjectRx.ulMsgIDMask = 0x7f8;
sMsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER | MSG_OBJ_FIFO;
//
前三个消息对象将 MSG_OBJ_FIFO 设置为指示
//它们是 FIFO 的一部分。
//
CANMessageSet (CAN0_BASE、1、&sMsgObjectRx、MSG_OBJ_TYPE_RX);
CANMessageSet (CAN0_BASE、 2、sMsgObjectRx、MSG_OBJ_TYPE_RX);
CANMessageSet (CAN0_BASE、3、 sMsgObjectRx、MSG_obj_type_RX);
//
最后一个消息对象没有设置 MSG_obj_FIFO 来指示
//这是最后一个消息。
//
sMsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER;
CANMessageSet (CAN0_BASE、4、&sMsgObjectRx、MSG_OBJ_TYPE_RX);
//
//配置并开始发送消息对象。
//
sMsgObjectTx.ulMsgID = 0x400;
sMsgObjectTx.ulFlags = 0;
sMsgObjectTx.ulMsgLen = 8;
sMsgObjectTx.pucMsgData = pui8BufferOut;
CANMessageSet (CAN0_BASE、 2、&sMsgObjectTx、MSG_OBJ_TYPE_TX);
//
//等待新数据变为可用。
//
while ((CANStatusGet (CAN1_base、CAN_STS_NEWDAT)& 1)=0){
//
//从报文对象中读取报文。
//

CANMessageGet (CAN1_base、1、&sMsgObjectRx、true);
}
//

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

    首先、让我指出、正如数据表中所述、在使用 FIFO 模式时、无法保证收到消息的顺序。 如果这很重要、我建议您改用单个消息缓冲器和高优先级中断将消息缓冲器读入软件 FIFO。

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

    要从 FIFO 缓冲区中读取消息对象、应遵循 数据表第1059页给出的流程图。  

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

    我不´m 收到的消息的顺序、也不是我的项目的问题、 但我对数据在 sMsgObjectTx.pucMsgData 示例中的 CANMessageGet 函数 Beacuse 之后的存储位置有疑问、就像用于传输"sMsgObjectTx.pucMsgData = pui8BufferOut;"那样、它缺少该步骤的示例?

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

    很抱歉、我刚刚在驱动程序库用户指南的第6.4节中查看了该示例。 该示例有几个问题。 我需要花一些时间来纠正它、然后我将发布一个更好的示例。 更具体地说,函数 CANMessageGET()将只读取其中一个消息对象中接收到的数据。 当使用 FIFO 模式时、必须循环浏览属于 FIFO 的报文对象、并读取每个包含新数据的报文对象。 显然、示例代码不是这样做的。

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

    是的、除其他问题外、这个示例缺少输入缓冲器到接收 CAN 消息目标结构的分配。 它需要如下行:

    sMsgObjectRx.pui8MsgData = pui8BufferIn;
    

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

    好的、我也会编写一些代码、如果 您能解决它、请告诉我!

    感谢你的帮助。

    此致

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

    这是我编写并测试的中断例程、它从4消息缓冲 FIFO 中读取值。 该例程从 CAN 消息邮箱中读取数据并将数据存储到循环缓冲区中。

    //用于接收 CAN 帧
    的循环缓冲器#define buffer_size 1024
    volatile uint64_t g_pui64Array[buffer_size];
    volatile bool G_bErrFlag;
    volatile bool G_bTxFlag;
    易失性 bool G_bRXFlag;
    volatile uint32_t g_ui32MsgCount;
    volatile uint32_t g_ui32RxMsgCount;
    volatile uint32_t g_ui32ArrayHead;
    static uint32_t g_ui32ArrayTail;
    
    void CAN0IntHandler (void)
    {
    uint32_t ui32Status、i;
    tCANMsgObject sMsgObjectRx;
    
    GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_7、GPIO_PIN_7);
    
    //
    //读取 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;
    }
    
    //
    //检查原因是否是接收消息对象
    //
    否则、如果((ui32Status > 0)&(ui32Status < 5))
    {
    for (i = ui32Status;i < 5;i++)
    {
    //
    //达到此点意味着发生了 RX 中断。
    //读取消息,清除中断
    sMsgObjectRx.ui32Flags = MSG_OBJ_NO_FLAGS;
    sMsgObjectRx.pui8MsgData =(void *)&(g_pui64Array[g_ui32ArrayHead]);
    CANMessageGet (CAN0_BASE、I、sMsgObjectRx、TRUE);
    if ((sMsgObjectRx.ui32Flags & MSG_OBJ_NEW_DATA)== MSG_OBJ_NEW_DATA)
    {
    //增加循环缓冲头
    G_ui32ArrayHead++;
    G_ui32ArrayHead = g_ui32ArrayHead % buffer_size;
    //
    //递增计数器以跟踪已有多少消息
    //已收到。 在实际应用中、这可用于将标志设置为
    //指示何时接收到消息。
    //
    G_ui32RxMsgCount++;
    }
    其他
    {
    中断;
    }
    }
    
    //
    //否则,发生意外导致中断的情况。 这应该是
    //永远不会发生。
    //
    其他
    {
    //
    //可以在此处执行伪中断处理。
    //
    }
    }
    

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

    谢谢!