【问题标题】:I2C interface on Tiva 2Tiva 2 上的 I2C 接口
【发布时间】:2014-07-17 12:41:39
【问题描述】:

在 Tiva(Texas Instruments Cortex M4F ARM)TM4C129XNCZAD 上,I2C 接口有另一个问题。我在 I2C 模块 4 到端口 K 上使用了一个主机,在 I2C 模块 6 到端口 B 上使用了一个从机。我已经互连了两个 I2C 模块。使用德州仪器驱动程序库,主机在“主机发送”模式下向从机发送 3 个字节作为请求,然后主机切换到“主机接收”模式,主机从从机接收 3 个字节。到目前为止,一切看起来都很好,但是有一个问题。主机从从机接收数据后,尽管主机在 I2C MCS 寄存器中设置了一个 STOP 位,但主机模块仍保持在“主机接收”模式,并且 I2C MCS 寄存器轮询指示 I2C 总线繁忙。因此,无法设置新的从机地址并进入新的周期。有人知道如何解决这个问题吗?

这是我的代码:

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"

#define SLAVE_ADDRESS 0x2C
#define NUM_I2C_DATA 3

#define RUN     1 
#define START   2
#define STOP    4
#define ACK     8
#define QCCMD   0x20
#define BURST   0x40

uint32_t  ui32Index;
uint32_t pui32DataRx[NUM_I2C_DATA];
uint32_t pui32DataTx[NUM_I2C_DATA];

int test(void)
{
    while(1)
    {
        for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
        {
                pui32DataRx[ui32Index] = 0;
                pui32DataTx[ui32Index] = 0;                 
        }
        while(I2CMasterBusBusy(I2C4_BASE));             
        I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, false);         
/*-------------------------------------------------------------*/
        I2CMasterDataPut(I2C4_BASE, '1');
        I2CMasterControl(I2C4_BASE, START | RUN);   // I2C_MASTER_CMD_BURST_SEND_START);
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ)); // Wait until the slave has received and acknowledged the data.           
        pui32DataRx[0] = I2CSlaveDataGet(I2C6_BASE);  // Read the data from the slave.
        while(I2CMasterBusy(I2C4_BASE));            
/*-------------------------------------------------------------*/           
        I2CMasterDataPut(I2C4_BASE, '2');
        I2CMasterControl(I2C4_BASE, RUN);   // I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));           
        pui32DataRx[1] = I2CSlaveDataGet(I2C6_BASE);
        while(I2CMasterBusy(I2C4_BASE));                
/*-------------------------------------------------------------*/   
        I2CMasterDataPut(I2C4_BASE, '3');
        I2CMasterControl(I2C4_BASE, STOP | RUN);    //I2C_MASTER_CMD_BURST_SEND_FINISH);
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));           
        pui32DataRx[2] = I2CSlaveDataGet(I2C6_BASE);
        while(I2CMasterBusy(I2C4_BASE));                            
/*-------------------------------------------------------------*/               
        I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, true);
/*-------------------------------------------------------------*/                   
        I2CMasterControl(I2C4_BASE, RUN | START | ACK); // I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
        I2CSlaveDataPut(I2C6_BASE, 'A');
        while(I2CMasterBusy(I2C4_BASE));    
        pui32DataTx[0] = I2CMasterDataGet(I2C4_BASE);
/*-------------------------------------------------------------*/       
        I2CSlaveDataPut(I2C6_BASE, 'B');
        I2CMasterControl(I2C4_BASE, RUN | ACK);//I2C_MASTER_CMD_BURST_RECEIVE_CONT);
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
        while(I2CMasterBusy(I2C4_BASE));    
        pui32DataTx[1] = I2CMasterDataGet(I2C4_BASE);
/*-------------------------------------------------------------*/
        I2CSlaveDataPut(I2C6_BASE, 'C');
        I2CMasterControl(I2C4_BASE, RUN | ACK); // I2C_MASTER_CMD_BURST_RECEIVE_CONT);
// Missing an ACK causing I2CSlaveStatus stays clear.               
        while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
        while(I2CMasterBusy(I2C4_BASE));    
        pui32DataTx[2] = I2CMasterDataGet(I2C4_BASE);
/*
When the I2C module operates in Master receiver mode, the ACK bit is normally
set, causing the I2C bus controller to transmit an acknowledge automatically after each byte. This
bit must be cleared when the I2C bus controller requires no further data to be transmitted from the
slave transmitter.

b. In Master Receive mode, a STOP condition should be generated only after a Data Negative Acknowledge executed by
the master or an Address Negative Acknowledge executed by the slave.
*/
        I2CMasterControl(I2C4_BASE, STOP);  // I2C_MASTER_CMD_BURST_SEND_STOP);
        while(I2CMasterBusy(I2C4_BASE));
    }
}

【问题讨论】:

    标签: c embedded arm


    【解决方案1】:

    @马可波罗

    我查看了您的代码,但我很难按照流程进行操作。但我能够让 I2C 在 TIVA Launchpad TM4C123GH6PM 上工作。我使用了 Tivaware 库。我创建了 3 个函数,init、read 和 write。以下是函数。

    初始化

    void initI2C0(void)
    {
       SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
       //reset I2C module
       SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
    
       //enable GPIO peripheral that contains I2C
       SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
       // Configure the pin muxing for I2C0 functions on port B2 and B3.
       GPIOPinConfigure(GPIO_PB2_I2C0SCL);
       GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    
       // Select the I2C function for these pins.
       GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
       GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
       // Enable and initialize the I2C0 master module.  Use the system clock for
       // the I2C0 module.  The last parameter sets the I2C data transfer rate.
       // If false the data rate is set to 100kbps and if true the data rate will
       // be set to 400kbps.
       I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
    
       //clear I2C FIFOs
       HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;
    }
    

    I2C 读取功能

    uint8_t readI2C0(uint16_t device_address, uint16_t device_register)
    {
       //specify that we want to communicate to device address with an intended write to bus
       I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
    
       //the register to be read
       I2CMasterDataPut(I2C0_BASE, device_register);
    
       //send control byte and register address byte to slave device
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    
       //wait for MCU to complete send transaction
       while(I2CMasterBusy(I2C0_BASE));
    
       //read from the specified slave device
       I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
    
       //send control byte and read from the register from the MCU
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    
       //wait while checking for MCU to complete the transaction
       while(I2CMasterBusy(I2C0_BASE));
    
       //Get the data from the MCU register and return to caller
       return( I2CMasterDataGet(I2C0_BASE));
     }
    

    I2C 写入函数

    void writeI2C0(uint16_t device_address, uint16_t device_register, uint8_t device_data)
    {
       //specify that we want to communicate to device address with an intended write to bus
       I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
    
       //register to be read
       I2CMasterDataPut(I2C0_BASE, device_register);
    
       //send control byte and register address byte to slave device
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    
       //wait for MCU to finish transaction
       while(I2CMasterBusy(I2C0_BASE));
    
       I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
    
       //specify data to be written to the above mentioned device_register
       I2CMasterDataPut(I2C0_BASE, device_data);
    
       //wait while checking for MCU to complete the transaction
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
       //wait for MCU & device to complete transaction
       while(I2CMasterBusy(I2C0_BASE));
    }
    

    我会在网上发布完整的代码以帮助理解应用程序。

    更新: TIVA + I2C 的完整代码可以在here找到。

    参考

    【讨论】:

      【解决方案2】:

      仅供参考...I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, false); 是您要写入的时间,I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, true); 是您要从 I2C 总线读取的时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-16
        • 2019-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 2018-04-08
        • 1970-01-01
        相关资源
        最近更新 更多