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.

[参考译文] TMS320F28P659DK-Q1:TMS320F28P659DK:仅限 LIN 接头

Guru**** 2805935 points

Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1598454/tms320f28p659dk-q1-tms320f28p659dk-lin-header-only

器件型号: TMS320F28P659DK-Q1
主题: C2000WARE 中讨论的其他器件

我尝试使用 TMS320F28P659DK LIN 外设、但遇到了一些问题。 我能够运行 C2000Ware 示例 lin_ex1_loopback_interrupts、并且可以正常运行、因为我看到 Rx 数据等于 Tx 数据、中断计数器按预期上升。 然后、我以这个示例并注释掉了 lin_enableIntLoopback 行、这样就可以使用示波器从外部观察 Tx 引脚。 我能够看到 LIN 数据包的标头、但没有数据。 它似乎也一直在等待 Tx 缓冲区为空、这似乎是问题的一个症状。 就我读取的数据而言、LIN_setIDByte 应发送出标头和数据、但这似乎没有发生。 任何人都能对这里的情况提供见解吗? 我将 CCS 12.8.1 与 C2000Ware 6.0.0.0 搭配使用。

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

    以下是修改后的示例代码。 我注释掉了所有中断配置、读取检查并将发送序列置于无限 for 循环中。 使用 while(!lin_isTxBufferEmpty (Lina_base)) 行;未注释、我只获得一次标头、软件处于该 while 循环中、因为 Tx 缓冲区没有被清空。 注释掉该行后、我只能重复标题。 示例代码中的注释指出 LIN_sendData 会写入 Tx 缓冲区、但不会启动传输、然后 LINsetIDByte 会启动标头、然后进行数据传输。 在 TRM 中、指出在 LINID 寄存器中写入 IDBYTE 会启动标头传输、向 LINTD0 寄存器中的 TD0 写入将启动传输。 似乎有点冲突。

    通过调试器查看 LinaRegs 寄存器时也会出现一些情况。 看起来所有 32 位 LIN 寄存器都可以镜像高 16 位和低 16 位。 例如、 软件中的 LINTD0 寄存器被设置为 0x11345678、但寄存器查看器中的值为 0x5678568、我无法手动更改该值以使高 16 位和低 16 位不相同。 尽管我使用的是最新版本 CCS 中的 GEL 文件、但这看起来应该是调试器端的问题。 这使我无法手动调整寄存器来尝试通过标头传输数据。

    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    #define FRAME_LENGTH    0x8
    #define LIN_PASS        0xABCD
    #define LIN_FAIL        0xFFFF
    
    //
    // Globals
    //
    volatile uint32_t level0Count = 0;
    volatile uint32_t level1Count = 0;
    volatile uint32_t vectorOffset = 0;
    uint16_t result;
    uint16_t txData[8] = {0x11, 0x34, 0x56, 0x78, 0x9A, 0xAB, 0xCD, 0xEF};
    uint16_t rxData[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    
    //
    // Function Prototypes
    //
    __interrupt void level0ISR(void);
    __interrupt void level1ISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        uint32_t i, dataIndex;
        uint16_t txID, error;
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Initialize GPIO and configure GPIO pins for LINTX/LINRX
        //
        Device_initGPIO();
        GPIO_setPinConfig(DEVICE_GPIO_CFG_LINTXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_LINRXA);
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
        EINT;
        ERTM;
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        // This registers the interrupt handler in PIE vector table.
        //
        //Interrupt_register(INT_LINA_0, &level0ISR);
        //Interrupt_register(INT_LINA_1, &level1ISR);
    
        //
        // Enable the LIN interrupt signals
        //
        //Interrupt_enable(INT_LINA_0);
        //Interrupt_enable(INT_LINA_1);
    
        //
        // Initialize the LIN module
        //
        LIN_initModule(LINA_BASE);
    
        //
        // Enable Internal Loopback mode
        //
        //LIN_enableIntLoopback(LINA_BASE);
    
        //
        // Enable interrupts for when an header identifier is received
        //
        //LIN_enableInterrupt(LINA_BASE, LIN_INT_ID);
    
        //
        // Set the interrupt priority line
        // Default is set to Interrupt line 0 (high priority)
        // Comment out "LIN_setInterruptLevel0" and uncomment
        // "LIN_setInterruptLevel1" to change to interrupt line 1 (low priority)
        //
        //LIN_setInterruptLevel0(LINA_BASE, LIN_INT_ALL);
        //LIN_setInterruptLevel1(LINA_BASE, LIN_INT_ALL);
    
        //
        // Enable parity check
        //
        LIN_enableParity(LINA_BASE);
    
        //
        // Enable global interrupt lines and clear status to known value
        //
        //LIN_enableGlobalInterrupt(LINA_BASE, LIN_INTERRUPT_LINE0);
        //LIN_enableGlobalInterrupt(LINA_BASE, LIN_INTERRUPT_LINE1);
        //LIN_clearGlobalInterruptStatus(LINA_BASE, LIN_INTERRUPT_LINE0);
        //LIN_clearGlobalInterruptStatus(LINA_BASE, LIN_INTERRUPT_LINE1);
    
        //
        // Perform 8 data transmissions with different transmit IDs and varying
        // number of bytes transmitted. Received data is checked for correctness.
        //
        for(;;)
        //for(i = 1 ; i <= FRAME_LENGTH; i++)
        {
            vectorOffset = 0;
    
            //
            // Create a new transmit ID and update with parity bits
            //
            txID = (0x10 + i);
            txID = LIN_generateParityID(txID);
    
            //
            // Increment the value of the first 8-bits of the transmitted
            // message data
            //
            //txData[0]++;
    
            //
            // Reset values in receive buffer array
            //
            for(dataIndex=0; dataIndex < 8; dataIndex++)
            {
                rxData[dataIndex] = 0xFF;
            }
    
            //
            // Set the frame length (number of bytes to be transmitted)
            //
            LIN_setFrameLength(LINA_BASE, 8);
    
            //
            // This places data into the transmit buffer.
            // No ID or data is placed on the bus and transmitted yet.
            //
            LIN_sendData(LINA_BASE, txData);
    
            //
            // Set the message ID to initiate a header transmission.
            // This causes the ID to be written to the bus followed by the
            // data in the transmit buffers.
            //
            LIN_setIDByte(LINA_BASE, txID);
    
            //
            // Wait for ISR to trigger and run upon reception of the ID header
            //
            //while(vectorOffset != LIN_VECT_ID);
    
            //
            // Wait until Transmit buffer is empty and has completed transmission
            //
            //while(!LIN_isTxBufferEmpty(LINA_BASE));
    
            //
            // Read the received data in the receive buffers
            //
            LIN_getData(LINA_BASE, rxData);
    
            //
            // Verify the transmitted data matches the received data
            //
            /*
            for (dataIndex=0; dataIndex < i; dataIndex++)
            {
                if (rxData[dataIndex] != txData[dataIndex])
                {
                    error++;
                }
            }
            */
        }
    
        //
        // Check if any data errors occurred
        //
        if(error == 0)
        {
            result = LIN_PASS;
        }
        else
        {
          result = LIN_FAIL;
        }
    
        //
        // Example completed. Check "result" variable for completion status.
        //
        asm("   ESTOP0");
    }

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

    尊敬的 Matt:

    请参阅以下线程、了解需要配置一个额外字段、以便在同一 C2000 上的两个实例之间执行外部环回。

    (+) LAUNCHXL-F280039C:lin_ex7_external_loopback - C2000 微控制器论坛 — C2000TM μ︎ 微控制器 — TI E2E 支持论坛

    此致、

    Delaney

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

    谢谢 Delaney。 它现在似乎正按预期工作。 我有点困惑、因为我没有使用两个 LIN 外设来运行环回测试。 我只使用 LINA 作为指挥官并通过示波器观察 TX 引脚。 您能否解释一下为什么启用外部环回会使单个 LIN 外设发送标头+数据、而禁用外部环回会使单个 LIN 外设仅发送标头?

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

    尊敬的 Matt:

    我看,我误解了你的原始消息,我的道歉。 本质上、LIN 需要在总线上连接一个响应器才能将数据帧发送出去。 在这种情况下、应该只看到标头。 您能否尝试从不同器件将响应器连接到总线并确定信号范围? 在这种情况下、您应该会看到数据(或者如果使用了外部环回并按照另一个线程中的说明进行设置)。

    所有 32 位 LIN 寄存器看起来都镜像高 16 位和低 16 位。 例如、 软件中的 LINTD0 寄存器被设置为 0x11345678、但寄存器查看器中的值为 0x5678568、我无法手动更改该值以使高 16 位和低 16 位不相同。 [/报价]

    这是由于 LIN 是字节外设、请参阅 此处的文档。 在本例中、CCS 显示相同的数据两次、因为 C28x CPU 可寻址 16 位。  

    此致、

    Delaney

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

    Delaney、

    我无法在线找到任何信息、或者不明白为什么 LIN 主器件需要任何其他器件位于同一物理总线上、以便主器件能够在标头之后发送数据。 可能相反、LIN 外设需要连接一个收发器才能发送数据、这在功能上可能相当于启用了外部环回? 在 LAUNCHXL-28P65X 上、没有 LIN 收发器、除非启用外部环回、否则主器件无法发送数据。 我们的开发硬件上有一个 LIN 收发器、主器件能够在不启用外部环回的情况下发送标头+数据。

    就寄存器视图而言、这是 CCS 的已知短路吗? 例如、SCIGCR1 在寄存器查看器中显示 0x1CE41CE4(高 16 位和低 16 位镜像)、但当我使用 HWREG_BP 进行读取时、我得到了 0x03021CE4、这就是我期望看到的结果。 所有 32 位 LIN 寄存器似乎都存在这种差异。   

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

    尊敬的 Matt:

    让我咨询一位其他专家、然后返回给您。

    此致、

    Delaney

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

    尊敬的 Matt:

    对延迟深表歉意。 你是对的、我之前的说法不正确。 我认为、您的问题实际上是 TX 和 RX 线路没有环回、因此指挥官器件只会发送报头。 收发器应在内部进行该环回、因此您不会看到问题。

    本质上、LIN 要求将发送线路环回到接收线路、以便将数据帧发送出去(以及连接到接收器件)。 LIN 命令器仅在发现总线上有一个报头告诉它时才会发送数据帧 — 它需要在 RX 引脚上接收自己的报头才能发出数据。  

    这不一定是 CCS 本身的缺点 — 但 C2000 器件的架构与 LIN 外设之间存在差异。  在 CCS 中调试具有 16 位处理器的器件(例如 C28x)时、内存浏览器将 显示每个值(假设使用 16 位字)。 CCS 无法 改变其显示存储器的方式、具体取决于所显示的特定外设寄存器、它假定所有存储器均为 16 位系统。 对于 LIN 等字节外设:  “ 16 位数据的偶数和奇数地址均映射到字节外设上的同一数据元素。“ 该器件本身从技术上讲会将 LIN 中的同一物理实体映射到两个不同的 C28x 地址、因此 CCS 显示这两个地址处的数据、这是相同的。

     HWREG_BP 使用编译器来处理这种差异。 我不确定编译器如何执行此操作、但它可能会以某种方式丢弃镜像的值。

    此致、

    Delaney

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

    感谢您对此进行后续跟进。