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.

[参考译文] TMS570LS1227:运行具有中断的 I2C 主发送器模式的示例代码

Guru**** 2949600 points

Other Parts Discussed in Thread: HALCOGEN

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt

器件型号:TMS570LS1227
主题中讨论的其他器件:HALCOGEN

你(们)好。

我正在寻找一个基于 Halcogen 生成的 API 的从器件发送和接收的示例代码。  以下是我的初稿。  请注意、这是假设接线和硬件按预期工作、因此不会捕获错误。

 

/* In high level driver */

IO_I2C_ret_E IO_I2C_transceive(const uint8_t * txBuffer,
                               const uint16_t txLength,
                               const uint8_t * rxBuffer,
                               const uint16_t rxLength)
{
    IO_I2C_ret_E ret = IO_I2C_RET_ERROR;
    
    /* Set direction to Transmitter */
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
    
    /* Configure Data count */
    i2cSetCount(i2cREG1, (uint32_t) txLength);
    
    /* Configure address of Slave to talk to */
    i2cSetSlaveAdd(i2cREG1, Slave_Add);
    
    /* Start transmit*/
    IO_I2C_semaphoneTake();  // take semaphore to be returned by isr
    i2cSetStart(i2cREG1); // Start the transmission:
    
    /* send data */
    IO_I2C_semaphoneTake();  // take semaphore to be returned by isr
    i2cSend(i2cREG1, (uint32_t) txLength, txBuffer);

    if (rxLength > 0)
    {
        /* Set direction to Transmitter */
        i2cSetDirection(i2cREG1, I2C_RECEIVER);
        
        /* Configure Data count */
        i2cSetCount(i2cREG1, (uint32_t) rxLength); 
        
        /* Start transmit*/
        IO_I2C_semaphoneTake();  // take semaphore to be returned by isr
        i2cSetStart(i2cREG1); // Start the transmission:
        
        /* receive data */
        IO_I2C_semaphoneTake();  // take semaphore to be returned by isr
        i2cSend(i2cREG1, (uint32_t) rxLength, rxBuffer);
    }
    /* set stop */
    i2cSetStop(i2cREG1);

    ret = IO_I2C_RET_SUCCESS;

    return ret;
}

/* In Halcogen generated notification.c */

#pragma WEAK(i2cNotification)
void i2cNotification(i2cBASE_t *i2c, uint32 flags)      
{
/*  enter user code between the USER CODE BEGIN and USER CODE END. */
/* USER CODE BEGIN (21) */
    if( (i2cREG1 == i2c))
    {
        IO_I2C_semaphoreGive();
    }
/* USER CODE END */
}

如果有一个类似的参考代码、我可以参考、那将会很好。  下面是我的问题列表:

问题1:在论坛的另一个主题中,您的 Guru 提到 i32cSetStart()将发送#1开始条件、#2从器件地址和#3 R/W 位。  它是否仍然是真的?

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master/3807094?tisearch=e2e-sitesearch&keymatch=sample%252525252520i2c%252525252520master#3807094

Q2: i32cSetStart()是否也在中断模式下运行?  这意味着该函数会立即返回、并在发送从器件地址时生成中断?

Q3:在 i2cSend()和 i2cReceive()中,我将它们称为 API 函数,有使用中断的实现。  在中断实现中、它使用静态结构 g_i2cTransfer_t 来保持数据指针和长度。  但是 、API 函数仅将初始值分配给结构体并退出、但我看不到任何循环的代码、也看不到在中断通知中调用的 API 函数。  我缺少什么吗?  或者是否有一个 DMA 机制自动处理多字节读取/写入、这样一个调用如下:

i2cSend (i2cREG1、10、&data);

 是否会在传输全部10个字节后调用 i2cNotification()?

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

    此外,在我找到的 GitHub 链接之一中,它具有 i2cInterrupt()实现,这对我来说是非常有意义的。  但是、该函数在我的 Halcogen 生成的 i2c.c 中不可用

    GitHub 链接: https://github.com/satellogic/canopus/blob/master/src/conf.d/halcogen/Torino1500/TMS570LS3137PGE/source/i2c.c

    我的 Halcogen 的屏幕截图。  请注意、I2C 中断位于一个奇怪的位置、它不可点击。  我使用的是 Halcogen 04.07.01。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="501565" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt/3889559 #3889559"]请注意、I2C 中断位于一个奇怪的位置、不可点击。 [/报价]

    要使 HALCoGen 在 Windows 10下正确显示、请尝试将 Display "Scale and layout"(显示"比例和布局")设置为100%。

    请参阅 HALcogen Software 似乎被处理。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="501565" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt/3889559 #3889559]Halcogen 的屏幕截图。  请注意、I2C 中断位于一个奇怪的位置、它不可点击。  我使用的是 Halcogen 04.07.01。

    e2e.ti.com/.../3867770

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="501565" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt "]

    问题1:在论坛的另一个主题中,您的 Guru 提到 i32cSetStart()将发送#1开始条件、#2从器件地址和#3 R/W 位。  它是否仍然是真的?

    [/报价]

    是的

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="501565" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt: i32cSetStart()是否也在中断模式下运行?  这意味着该函数会立即返回、并在发送从器件地址时生成中断?

    否、仅 当 I2C 已识别其自身的从器件地址时才会产生 AAS 中断。

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

    QJ 感谢您的回复。  让我澄清一下我的问题、因为我不是在询问 AAS 中断。  根据您对 Q1的响应,当我调用 i2cSetSart()时,它将发送起始位、从地址和 R/W 位。  i2cSetSrart()将 立即返回。  在调用 i2cSend()之前,是否必须在 i2cSetSart()之后等待 Tx 就绪中断?

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

    Chester 感谢您的回复。  我在 Mac 上运行的是并行桌面(带有 Windows 10的虚拟机)、这是一个永远无法修复的错误。  因此,让我们不要专注于修复 GUI。

    查看 GitHub 链接中 i2cInterrupt()的内容,我认为使用该函数对于使代码正常运行至关重要。  Halcogen 是否生成函数?  如果 Halcogen 能够生成函数,但由于我无法单击 GUI 而无法为我生成函数,您能否给我指出我可以修改 DIL 文件中的哪个标志以使其正常工作?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="501565" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1051367/tms570ls1227-sample-code-for-running-i2c-master-transmitter-mode-with-interrupt/3889925 #3889925"] 如果 Halcogen 能够生成函数,但由于我无法单击 GUI 而无法生成函数,您能否指向我可以修改 DIL 文件中的哪个标志以使其正常工作?

    在 Windows 10上运行 HALCoGen v04.07.01的情况下、更改 了 TMS570LS1227PGE GUI 中的 I2C 选项、以查看.DIL 文件中哪些选项会影响生成的代码。

    控制 i2cInterrupt()函数是否生成的 GUI 选项是 VIM 通道64-95选项卡上的中断分配"66:IC2中断":

     当.DIL 文件包含以下内容时,会生成 i2cInterrupt()函数:

    DRIVER.SYSTEM.VAR.VIM_CHANNEL_66_INT_ENABLE.VALUE=1

    I2C 驱动程序选项卡上的中断控制 由生成 的 i2cInit()函数写入 i2cREG1->IMR 中断使能寄存器的值:

    其中、已启用的 IC2中断到.DIL 文件参数的映射为:

    HALCoGen GUI 上的中断名称 在 GUI 中启用中断时设置为1的.DIL 文件参数名称
    AL INT DRIVER.I2C.VAR.I2C_ALINTENA.VALUE
    NACK INT DRIVER.I2C.VAR.I2C_NACKINTENA.VALUE
    Ardy INT DRIVER.I2C.VAR.I2C_ARDYINTENA.VALUE
    ICRRDY DRIVER.I2C.VAR.I2C_ICRRDYINTENA.VALUE
    ICXRDY DRIVER.I2C.VAR.I2C_ICXRDYINTENA.VALUE
    SCD 内部 DRIVER.I2C.VAR.I2C_SCD.VALUE
    AAS 集成 DRIVER.I2C.VAR.I2C_AAS.VALUE
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢切斯特。  我能够通过 Halcogen GUI 启用 I2C 中断 IRQ 通道66、并查看所需的更改、包括正在生成的 i2cInterrupt()函数。  我相信这已解决了我的问题,并附上了律政司司长的答覆。  我将确认问题在接下来的两天内是否已解决。

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

    您好、Chuo、

    如果问题已解决、请告知我们或关闭主题。 谢谢

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

    QJ、您好、由于硬件故障、我在验证中断方法时遇到问题。  不过、这会带来另一个问题。  我将 MCU 配置为 I2C 主发送器。  如果我有一个故障的 I2C 从器件无法 ACK、那么我似乎没有得到 NACK 中断。  请注意、我为 I2C 和 NACK INT 启用了 VIM 通道66。  您是否知道我是否应该在开始条件、从器件地址和 R/W 位之后立即获得 NACK 中断?

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

    您好、Chuo、

    I2C 协议从起始位开始、后跟从器件地址(7位地址+ 1位用于读取/写入)。 发送从器件地址后、主器件释放数据总线(SDA 线)、将线路置于高阻抗状态、让从器件驱动线路。

    如果地址与从器件地址相匹配、从器件会将该线路拉低以用于 ACK。 如果线路没有被任何从器件拉低、那么主器件会将其视为 NACK 并在下一个时钟脉冲中发送停止位或重复起始位以终止或重新启动通信。

    I2C SDA 和 SCK 线路需要外部上拉。 MCU 内部上拉电阻对于 I2C 而言太弱。  

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

    BTW 、NACK 中断不是在开始字节后通过无确认生成的。 在主器件起始字节模式中、第一个字节(全为零的地址)接收一个 NACK、但不清除停止位。

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

    您好 QJ、

    我收到了返工板、并确认可以在轮询模式下传输。  但是、我无法使中断模式工作。  考虑以下代码:

                uint8_t txLength = 2;
                uint8_t txBuffer[2] = {0x00,0x11};
                
                /* Configure address of Slave to talk to */
                i2cSetSlaveAdd(i2cREG1, SLAVE_DEVICE_ADDRESS);
                /* Set direction to Transmitter */
                i2cSetDirection(i2cREG1, (uint32_t) I2C_TRANSMITTER);
                /* Configure Data count */
                i2cSetCount(i2cREG1, (uint32_t) txLength);
                /* Set mode as Master */
                i2cSetMode(i2cREG1, I2C_MASTER);
                /* set stop */
                i2cSetStop(i2cREG1);
                /* Start transmit*/
                i2cSetStart(i2cREG1); // Start the transmission:
                /* send data */
                i2cSend(i2cREG1, (uint32_t) txLength, txBuffer);

    器件配置为 I2C 主发送器、并启用重复模式、以及 RX、TX、NACK 和 SCD 的中断。  此外、I2CInterrupt 的 VIM 通道66被启用。  它应该传输两个字节的数据。  但是、在发出停止条件之前、主器件只发送从器件地址/RW 字节和一个数据字节(0x00)。  似乎从未触发中断。  你有什么想法吗?

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

    启用了哪个 I2C 中断? 您是否启用了 IRQ 中断? 复位或上电后、默认情况下 IRQ 和 FIQ 处于禁用状态。

    _enable_IRQ ();-->启用 IRQ 中断

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

    您好 QJ、

    我只想更新它、进一步深入研究参考文档并禁用重复启动、我使其适用于 TX 和 RX。  我建议大家在以下部分中添加更多详细信息:  

    31.2.5.3重复起始条件

    [建议添加]在重复模式下、当 TX/RX 字节计数达到 I2CCNT 时、不会自动生成停止条件。  用户必须手动设置停止条件。  更多详细信息、请参阅31.6.10 I2C 模式寄存器(I2CMDR)。

    原因是在重复模式下、硬件不会自动生成停止条件、因此查找 SCD 条件不会产生任何结果。  这也是轮询方法。

    随附的是工作的 Halcogen 设置:

    已删除代码:

    bool IO_I2C_transceive(const uint8_t deviceAddr,
                           uint8_t * txBuffer,
                           const uint16_t txLength,
                           uint8_t * rxBuffer,
                           const uint16_t rxLength)
    {
        bool ret = false;
        
        // Obtain transmission line semaphore.  Timeout in 10ms
        ret = SEMAPHORE_TAKE(10);
    
        if (ret)
        {
            //
            // Transmit START condition, slave device addr, and R/W bit (read)
            //
            /* clear Previous I2C stop condition */
            i2cClearSCD(i2cREG1);
            /* Configure address of Slave to talk to */
            i2cSetSlaveAdd(i2cREG1, deviceAddr);
            /* Set direction to Transmitter */
            i2cSetDirection(i2cREG1, (uint32_t) I2C_TRANSMITTER);
            /* Configure Data count */
            i2cSetCount(i2cREG1, (uint32_t) txLength);
            /* Set mode as Master */
            i2cSetMode(i2cREG1, I2C_MASTER);
            /* set stop */
            i2cSetStop(i2cREG1);
            /* Start transmit*/
            i2cSetStart(i2cREG1); // Start the transmission:
            /* send data */
            i2cSend(i2cREG1, (uint32_t) txLength, txBuffer);
            
            ret = SEMAPHORE_TAKE(1); // timeout in 1ms
            /* Clear the Stop condition */
            i2cClearSCD(i2cREG1);
        }
    
        if (ret)
        {
            //
            // Transmit START condition, slave device addr, and R/W bit (read)
            //
    
            /* Configure address of Slave to talk to */
            i2cSetSlaveAdd(i2cREG1, deviceAddr);
            /* Set direction to Transmitter */
            i2cSetDirection(i2cREG1, (uint32_t) I2C_RECEIVER);
            /* Configure Data count */
            i2cSetCount(i2cREG1, (uint32_t) rxLength); 
            /* Set mode as Master */
            i2cSetMode(i2cREG1, I2C_MASTER);
            /* set stop */
            i2cSetStop(i2cREG1);
            /* Start transmit*/
            i2cSetStart(i2cREG1); // Start the transmission:
            /* receive data */
            i2cReceive(i2cREG1, (uint32_t) rxLength, rxBuffer);
            
            ret = SEMAPHORE_TAKE(1); // timeout in 1ms
            /* Clear the Stop condition */
            i2cClearSCD(i2cREG1);
        }
        // return transmission line semaphore
        SEMAPHORE_GIVE();
    
        return ret;
    }
    
    /* In notification.c */
    void i2cNotification(i2cBASE_t *i2c, uint32 flags)
    {
        SEMAPHORE_GIVE_FROM_ISR();
    }