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:CAN 至 USB 通信

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/611195/tm4c123gh6pm-can-to-usb-communication

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

我正在处理一个项目、在该项目中、我将通过 USB 将传入的 CAN 数据传输到 PC。

CAN 数据将每1ms 从外部硬件接收一次、此数据将复制到 USB 环形缓冲器中。 USB 缓冲器中的每20ms 数据将传输到 PC。我正在使用批量传输模式。 我基于批量传输示例程序开发了我的 USB 应用程序。我正在使用 TI 的 PC 工具(USB_BULK_example)来检查 PC 上接收到的数据量。

我的通信链路与下图类似

CANDATASOURCE (1)------ 可以------------ >TM4C123(2) USB -------- >PC(3)


在这里、我面临2个问题

1) 1) CANDATASOURCE 和 TM4C123 (CAN 总线)之间的数据丢失
示例:当以1000msgs/second 的速率进行传输时、每50000条消息平均丢失300条消息。
如果消息传输频率小于(例如200msgs/second)、则损耗非常小(少于5条消息、而不是300条消息)。
发送器和接收器都处于相同的采样点(80%)和波特率(1mbps)。

下面给出了我用于计算采样点(80%)和波特率(1mbps)的值
时钟= 80MHz
GetBittime.ui32SyncPropPhase1Seg=15;
GetBittime.ui32Phase2Seg=4;
GetBittime.ui32SJW=3;
GetBittime.ui32QuantumPrescaler=4;

我应该怎么做才能在这个速率(1000 msgs/second)下实现零数据丢失?

2)接收到的 CAN 数据、我将在报文对象结构(tCANMsgObject)内复制。
CANMessageGet (CAN0_BASE、2、&sMsgObjectRx、0);

然后、我将使用 dma.gven 将这个对象结构复制到 USB 环形缓冲器中、下面是执行该操作的函数。

void UsbcopyDataToUSB (uint8_t * pui8Data、uint32_t ui32NumBytes)//此函数在 CAN RX ISR 内部调用

uint32_t ui32Loop、ui32Space;
uint32_t ui32WriteIndex;
tUSBRingBufObject sTxRing;

//
//获取当前缓冲区信息,以便我们直接写入
//发送缓冲区(我们已经从中获得了足够的信息
//直接访问接收缓冲区的参数)。
//
USBBufferInfoGet (&g_sTxBuffer、&sTxRing);

//
//传输缓冲区中有多少空间?
//
ui32Space = USBBufferSpaceAvailable (&g_sTxBuffer);

//
//我们可以处理这一整段时间的字符数?
//
ui32Loop =(ui32Space < ui32NumBytes)? ui32Space:ui32NumBytes;
UsbDataTxBufferCount += ui32Loop;

ui32WriteIndex = sTxRing.ui32WriteIndex;

uDmaInitSWTransfer (((void*) pui8Data、(void*) g_pui8USBTxBuffer[ui32WriteIndex]、ui32Loop);


 上面提到的所有内容都发生在 CAN 接收器中断内部。


每20ms、我就会将数据传输到 PC (此时、环形缓冲器内部可能会出现20条 CAN 消息)。  TX 环形缓冲区大小为2K。
我有一个计数器来跟踪通过 USB 传输的数据字节的数量、下面给出了通过 USB 传输数据的函数。

空 UsbTransmitDataIfAny()//此函数每20ms 调用一次

if (UsbDataTxBufferCount)

USBBufferDataWritten (&g_sTxBuffer、UsbDataTxBufferCount);
UsbDataTransmitCount += UsbDataTxBufferCount;//通过 USB 以字节为单位进行总数据传输
UsbDataTxBufferCount = 0;



在 PC 端、我使用-e 选项运行 USB_bulk_example。我还在该应用程序中进行了一些编辑、以检查接收到的数据量。
在较低频率 (CAN 消息传输频率为200msgs/second)时、总传输数据数之间的差异通常很小
总接收数据在 PC 端进行计数。
示例:传输的总数据(MCU 侧)= 100050B
接收到的总数据(PC 端)= 100000B 现在 PC 计数器小于50B。
此时、如果我从 MCU 再向 PC 发送一个数据包(考虑1个数据包= 10字节)、
然后总数据传输(MCU 端)变为100060B、这是新数据包大小的增量。
但接收到的总数据(PC 端)变为100060B、增量为60B (旧差+新数据包大小)。
为什么会发生这种情况?

在较高的频率下(CAN 消息传输频率为1000msgs/second)、这2个计数显示的差异约为250B。与前一个发送单个数据包后的情况不同、差异仍然相同。MCU 直接连接到 PC、因此如果我调用 USBBufferDataWritten()、我是否可以假设 USB 库将发送该数据?  如果是、为什么它不能到达 PC。
或者 PC 端是否有任何问题?请帮助我?

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

    Jibin、您好!
    由于 CPU 尚未处理/读取前一条消息、您将丢失消息。 我认为您可能会在您的 CAN 接收 ISR 中花费过多时间。 您当前正在尝试将接收到的 CAN 数据复制到 USB 环形缓冲区。 如果您可以在 ISR 外部执行此项操作、我认为它会有所改进。