简体   繁体   English

Tiva 2上的I2C接口

[英]I2C interface on Tiva 2

On a Tiva (Texas Instruments Cortex M4F ARM) TM4C129XNCZAD I have another problem with I2C interface. 在Tiva(Texas Instruments Cortex M4F ARM)TM4C129XNCZAD上,我还有另一个I2C接口问题。 I have employed both a master on I2C module 4 thru port K and a slave on I2C module 6 thru port B. I have interconnected both I2C modules. 我既通过端口K在I2C模块4上使用了主机,也通过端口B在I2C模块6上使用了从机。我已经将两个I2C模块互连。 Using Texas Instruments driver library the master sends 3 bytes to the slave within "Master Send" mode as a request and then the master switches into "Master Receive" mode and the master receives 3 bytes from the slave. 主机使用德州仪器(TI)驱动程序库以请求的方式在“主机发送”模式下将3个字节发送到从机,然后主机切换到“主机接收”模式,主机从从机接收3个字节。 Till now everything looks to be OKay, but there is an issue. 到现在为止一切似乎还可以,但是有一个问题。 After the master receives data from the slave, in spite of the master sets a STOP bit within an I2C MCS register, the master module persists in the "Master Receive" mode and the I2C MCS register polling indicates the I2C bus is busy. 主机从从机接收数据后,尽管主机将I2C MCS寄存器中的STOP位置1,主机模块仍保持“主机接收”模式,并且I2C MCS寄存器轮询表明I2C总线忙。 Because of that there is impossible to set a new slave address and to enter to new cycle. 因此,无法设置新的从站地址并进入新的周期。 Has anybody any idea how to fix this issue? 有谁知道如何解决此问题?

There is my code: 有我的代码:

#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));
    }
}

@MarcoPolo @马可波罗

I look at your code and it hard for me to follow the flow. 我查看了您的代码,使我很难遵循流程。 But I was able to get I2C working on TIVA Launchpad TM4C123GH6PM. 但是我能够在TIVA Launchpad TM4C123GH6PM上使用I2C。 I used the the Tivaware library. 我使用了Tivaware库。 I created 3 functions, init, read and write. 我创建了3个函数,init,读取和写入。 Here are the functions. 这里是功能。

Initialization 初始化

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 Read Function 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 Write Function 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));
}

I will post the complete code online to help understand the application. 我将在网上发布完整的代码,以帮助理解该应用程序。

Update: Complete code for TIVA + I2C can be found here . 更新:可以在此处找到TIVA + I2C的完整代码。

Reference 参考

FYI... I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, false); 仅供参考... I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, false); is when you want to write and I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, true); 是要编写I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, true); is when you want to read from I2C bus. 是您要从I2C总线读取的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM