I'm trying to read out a hall effect sensor via I2C. I've based my code on the driverlib example i2c_ex5_master_slave_interrupt.c, example 2.
I can see on my Saleae logic analyzer that the writes are correct. However, when I try to read, the sensor address is put on the bus correctly, but the register address is not. It is left high, while the clock is pulsed.
The following code generates this sequence:
#include "driverlib.h" #include "device.h" #include "board.h" #include "i2cLib_FIFO_master_slave_interrupt.h" // // Defines // #define I2CA_SENSORADDRESS 0x35 #define I2CA_ADDRESS 0x30 #define I2CB_ADDRESS 0x40 // // Globals // uint16_t status = 0; struct I2CHandle I2CA; struct I2CHandle I2CB; // // Function Prototypes // __interrupt void i2cAISR(void); __interrupt void i2cAFIFOISR(void); __interrupt void i2cBISR(void); __interrupt void i2cBFIFOISR(void); uint16_t AvailableI2C_slaves[MAX_I2C_IN_NETWORK]; uint16_t I2CA_TXdata[MAX_BUFFER_SIZE]; uint16_t I2CB_TXdata[MAX_BUFFER_SIZE]; uint16_t I2CA_RXdata[MAX_BUFFER_SIZE]; uint16_t I2CB_RXdata[MAX_BUFFER_SIZE]; uint32_t I2CA_ControlAddr; uint32_t I2CB_ControlAddr; uint16_t status; // // Main // void i2c_test(void) { // // Board initialization // I2C_GPIO_init(); // // 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(); I2Cinit(); // Board_init(); I2C_setOwnSlaveAddress(I2CA_BASE, I2CA_ADDRESS); I2C_setOwnSlaveAddress(I2CB_BASE, I2CB_ADDRESS); //I2Cs connected to I2CA will be found in AvailableI2C_slaves buffer //after you run I2CBusScan function. //When you run I2C BusScan you need to disable I2C interrupts and clear //the flag set during I2CBusScan // uint16_t i; // // for(i=0;i<MAX_I2C_IN_NETWORK;i++) // { // AvailableI2C_slaves[i] = 0; // } // // I2C_disableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); // I2C_disableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); // // uint16_t *pAvailableI2C_slaves = AvailableI2C_slaves; // status = I2CBusScan(I2CA_BASE, pAvailableI2C_slaves); // // I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); // I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); // // ESTOP0; // I2C_disableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); // I2C_disableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); // // status = I2CBusScan(I2CB_BASE, pAvailableI2C_slaves); // // I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); // I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION); I2C_enableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); I2C_enableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK)); // // Set I2C use, initializing it for FIFO mode // Interrupt_register(INT_I2CA, &i2cAISR); Interrupt_enable(INT_I2CA); Interrupt_register(INT_I2CB, &i2cBISR); Interrupt_enable(INT_I2CB); Interrupt_register(INT_I2CA_FIFO, &i2cAFIFOISR); Interrupt_enable(INT_I2CA_FIFO); Interrupt_register(INT_I2CB_FIFO, &i2cBFIFOISR); Interrupt_enable(INT_I2CB_FIFO); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; uint16_t i; for(i=0;i<MAX_BUFFER_SIZE;i++) { I2CA_TXdata[i] = 0; I2CA_RXdata[i] = 0; I2CB_TXdata[i] = 0; I2CB_RXdata[i] = 0; } I2CA.currentHandlePtr = &I2CA; I2CA.base = I2CA_BASE; I2CA.SlaveAddr = I2CA_SENSORADDRESS; I2CA.pControlAddr = &I2CA_ControlAddr; I2CA.NumOfAddrBytes = 1; I2CA.pTX_MsgBuffer = I2CA_TXdata; I2CA.pRX_MsgBuffer = I2CA_RXdata; I2CA.NumOfDataBytes = 64; I2CB.currentHandlePtr = &I2CB; I2CB.base = I2CB_BASE; I2CB.SlaveAddr = I2CB_ADDRESS; I2CB.NumOfAddrBytes = 4; I2CB.pControlAddr = (uint32_t *)0; I2CB.pTX_MsgBuffer = (uint16_t *)0; I2CB.pRX_MsgBuffer = (uint16_t *)0; I2CA.pTX_MsgBuffer[0] = 0x00; I2CA.SlaveAddr = 0x00; I2CA.NumOfDataBytes = 1; I2CA_ControlAddr = 0x10; status = I2C_MasterTransmitter(&I2CA); // Wait for I2CA to be complete transmission of data while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY); I2CA.SlaveAddr = I2CA_SENSORADDRESS; // I2CA.pTX_MsgBuffer[0] = 0x10; // register address I2CA.pTX_MsgBuffer[0] = 0b00000000; // set config register - all channels, full range, odd CP parity = 0x I2CA.pTX_MsgBuffer[1] = 0b10001001; // MOD1 register: master controlled mode, one byte read command, enabled interrupt, no collision avoidance, odd FP parity I2CA.NumOfDataBytes = 2; status = I2C_MasterTransmitter(&I2CA); // Wait for I2CA to be complete transmission of data while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY); I2CA_ControlAddr = 0x00 | 0b00100000; // I2CA.pTX_MsgBuffer[0] = 0b00100000; // trigger after I2c write frame is finished I2CA.NumOfDataBytes = 0; status = I2C_MasterTransmitter(&I2CA); // Wait for I2CA to be complete transmission of data while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY); SysCtl_delay(5000); //Adding delay for sensor conversion I2CA.NumOfDataBytes = 0; I2CA.pTX_MsgBuffer[0] = 0b00000000; // reset tx data I2CA_ControlAddr = 0b00000000; status = I2C_MasterReceiver(&I2CA); // Wait for I2CA to be complete transmission of data while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY); ESTOP0; }
I did have to change the I2C_MasterReceiver() Code (creating and calling a I2C_TransmitSlaveAddress_ControlBytes_MasterReadBit() Method which sets I2C_MASTER_RECEIVE_MODE instead of I2C_MASTER_SEND_MODE) to send the read bit high, as the write bit was hardcoded, which did work.
I'm expecting 0x0 + ACK on the bus, but I get OxFF + NACK. The readout should look like this: