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.

[参考译文] TMS320F280025C:CANbus 消息传输

Guru**** 2445670 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1527735/tms320f280025c-canbus-message-transferring

器件型号:TMS320F280025C
主题:C2000WARE 中讨论的其他器件

工具/软件:

大家好、
我在利用 TX 中断线路传输 CAN 总线消息时遇到了一些问题。

问题如下:
为了传输一些信息、我将邮箱设置为 8 字节长 (DLC = 8)。
然后、在一个简单的 while 循环中、我希望发送 5-6 条连续的 CAN 总线消息、每个消息都包含不同的数据。

通过使用 CAN 分析仪嗅探总线、我注意到第一条消息发送时的 DLC 等于 8、而所有后续消息都有 DLC = 2。
我不能真正理解它(我粘贴在屏幕截图下面)。

我附加了一个代码片段、供您深入探究。

如果您有任何线索、请告诉我。
谢谢





Elia

            // WHILE LOOP
            // I receive a serial message and based on it I decide which message I want to send
            
            // WritePkt has as arguments (in order):
            // - canbus message to be sent
            // - serial message from which information is retrieved
            // - length of the canbus message (in order to know which mailbox I should use)
            // - pointer to the serial buffer, in order to be aligned with the information I want to extract
            
            
            while(serial_Rx[ptr_rx] != '\r'){    // indica la fine del messaggio seriale (completo)
                if(serial_Rx[ptr_rx] == '\n'){   // indica l'inizio del sottomessaggio seriale (pacchetto)

                    pkt_id = serial_Rx[ptr_rx+1];
                    switch(pkt_id){

                    case WRITE_MULTIPLE_REGS:
                        WritePkt(WR_multiple, serial_Rx, sizeof(WR_multiple), &ptr_rx);
                        break;

                    case WRITE_PART_NUMBER_1:
                        WritePkt(part_number1, serial_Rx, sizeof(part_number1), &ptr_rx);
                        break;

                    case WRITE_PART_NUMBER_2:
                        WritePkt(part_number2, serial_Rx, sizeof(part_number2), &ptr_rx);
                        break;

                    case WRITE_PART_NUMBER_3:
                        WritePkt(part_number3, serial_Rx, sizeof(part_number3), &ptr_rx);
                        break;

                    case WRITE_PART_NUMBER_4:
                        WritePkt(part_number4, serial_Rx, sizeof(part_number4), &ptr_rx);
                        break;

                    case WRITE_PART_NUMBER_5:
                        WritePkt(part_number5, serial_Rx, sizeof(part_number5), &ptr_rx);
                        break;
                    }
                    DELAY_US(200);
                }
            }
            
            // WRITE PKT
            
            void WritePkt(char *buffer_can, char *buffer_serial, uint16_t size_buffer_can, uint16_t *ptr){

    //uint16_t messageObj;
    // funzione che prende in ingresso i due buffer e restituisce il ptr_rx aggiornato
    // uint16_t CAN_pkt(buffer_can, buffer_serial);
    buffer_can[0] = buffer_serial[*ptr+1];
    buffer_can[1] = buffer_serial[*ptr+2] + ADDR_OFFSET;

    // 6 byte per data
    memcpy(&buffer_can[2], &buffer_serial[*ptr+3], (size_buffer_can/(sizeof(buffer_can[0]))-2));

    // capisco quale tipo di messaggio inviare dalla DLC (ovvero la lunghezza del buffer in ingresso)
    switch(size_buffer_can){
    case DLC_2:
        sendCANMessage(CAN_TX_READ, buffer_can);
        //messageObj = CAN_TX_READ;
        break;

    case DLC_4:
        sendCANMessage(CAN_TX_FEED, buffer_can);
        //messageObj = CAN_TX_FEED;
        break;

    case DLC_8:
        sendCANMessage(CAN_TX_WRITE, buffer_can);
        //messageObj = CAN_TX_WRITE;
        break;
    }

    *ptr += 1 + size_buffer_can/(sizeof(buffer_can[0]));
    //return messageObj;

}
            
            
            
            // ISR TX CANBUS
            
            // Devo riuscire a farlo funzionare!
__interrupt void cana_tx_isr(void){

    dbg.can_tx++;

    while(CanaRegs.CAN_IF1CMD.bit.Busy){}


    // LOCK FEEDER
    if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_LOCK-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_LOCK)){
        GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;

    }
    // WRITE HANDLING
    else if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_WRITE-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_WRITE)){
        GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;

    }
    // READ HANDLING
    else if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_READ-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_READ)){
        GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;

    }
    // FEED HANDLING
    else if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_FEED-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_FEED)){
        GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;

    }

    CanaRegs.CAN_IF1CMD.bit.Control = 1;
    CanaRegs.CAN_IF1CMD.bit.TXRQST = 0;

    //CanaRegs.CAN_IF1CMD.bit.ClrIntPnd = 1;

    CanaRegs.CAN_GLB_INT_CLR.bit.INT1_FLG_CLR = 1;
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

}
            
            

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

    您好 Elia、

    我的第一项建议是检查寄存器 CAN_ES(错误寄存器)、以查看传输过程中是否发生了任何错误。  遗憾的是、我们调试此自定义代码且不使用 C2000Ware 中发布的 API 并不简单、因为这涉及重写和重新创建您的问题、会占用大量带宽。 我的另一个建议是研究我们的 driverlib 示例是如何用 C2000Ware 编写的(我相信我在我之前的文章中向您提到了这一点)。

    在 C2000Ware 中的 CAN 测试示例中、可以看到使用 API can_setupMessafeObject () 可以完成消息对象的设置。  通过此函数调用、您可以定义 32 个消息对象(TX 和 RX 的组合)。  要发送消息对象,可以使用 API can_sendMessage() 并指定要发送的消息对象。  您也可以使用 API can_readMessage() 来读取 CAN 帧。 这些 API 会设置您可能未在例程中正确设置的所有寄存器字段、因此我建议您首先检查这些不同的函数以了解 CAN 寄存器的设置方式。

    此致、

    Joseph

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

    您好、Joseph:
    感谢您的回答!  
    我知道 driverlib 的可能性、但我通常更喜欢自己编写我需要的所有内容(这是了解我正在做什么的最佳方法)。
    Driverlib 当然是更有效和紧凑,但它们是难以吸引,如果你不完美地管理你正在处理的主题(在我看来)。

    但我将按照您的建议进行操作、查看 driverlib 函数以查看是否出现了不同的情况。
    不管怎样,我所面对的错误是很奇怪的,我不记得有任何不寻常的 can_es 寄存器。

    我会让您随时更新进度
    祝你度过美好的一天!

    Elia

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

    您好、Joseph:
    我能够解决我保留位域配置的问题。
    通过尝试不同的策略(例如上网,通过代码编写器和示波器进行调试)、我可以找到一种方法。
    每次调用发送函数时、我都会强制 DLC 位达到所需的总线上发送的字节数。

    我被以前的经验和不好的知识所偏倚,在那里我只在设置功能中指定 DLC。

    我会将您的最后一封邮件标记为解决邮件。

    让我感谢你的时间和建议。
    希望将来能有所帮助!

    Elia