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.

Reading 2bytes as I2c Slave

Other Parts Discussed in Thread: MOTORWARE

Hi all,

I have custom instaspin controllers on a PX4 quad using I2C... Everything works for a single byte set-point protocol but I want to use 2 bytes for better resolution. When I simply read two bytes successively I get the same byte read twice - I need something to wait in between the bytes but I cannot figure it out-OR something to tell the master to wait??? I found a few resources which basically say while !stop bit keep reading data in - but in the case below I will usually see 0x1 or 0xA for both the high and low byte- they toggle around and seem to get confused... -I'm using the wrappers Michael Jordan posted here: http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/238353.aspx   

Basically, what are the steps that are required to read two bytes of data over I2C?

Thanks

  • Patrick,

    Cool application!  I'm actually designing my own quadcopter right now:

    http://forum.43oh.com/topic/5345-quadcopter-boosterpack/

    Ok, back to your question.  This sounds like FIFO garbage.  If you don't initialize the FIFOs exactly as we have in the example applications, I've seen them spit out some bogus data initially.  Are you using FIFOs?  If so try turning them off and doing the while !stop bit thing and see if the behavior improves.

    BR,

  • Great minds... but mine's bigger! :-p

    coincidentally i had seen your boosterpack-FOC-copter a few times before - maybe a TI staff comp video or something? & definitely saw it over on hackaday recently- Very Nice!

    *What series Launchpad are you aiming this at (c2000/msp/etc)- assuming your'e going to provide sample code for the 'brain' Launchpad?

    -Have you done any 'relative' efficiency testing against commercial six-step controllers with your setup? I did some steady-state bus current comparisons with my controllers and some low-mid range commercial options.. -Basically, I spun the motors up to 1000, 1200,1400... 5000 rpm using the different controllers and measured the bus current. Found about 25-30% less bus current for the FOC controllers. -Tests were repeatable but this is obviously too much to be valid (I think - still went in my paper:) )... Anyway, if you have any figures I'd be interested to hear?

    Re the I2C- 

    No I am not using FIFO and at the time of my first post I was just polling the I2C outside of the InstaSPIN mainISR - wasn't interrupt driven...

    Now I have it interrupt driven (motorware guys really dropped the ball with I2C - had to add all the PIE stuff for I2C - why I took a while to respond) which is running really nicely for reading in a single byte at a time...

    This will have to suffice for the time being as I want a video for a presentation next week (-FOC esc was my undergrad project)... i.e no technical questions at the moment, but I am going to keep trying with the two bytes read in next week so i'll leave the thread un-answered and might resuscitate it next week.

    Thanks

  • :-D Nice Quad!!

    Ya, I've been working on drumming up some press for the project the past year so its been in various videos.  Initially I'm working on supporting the C2000 LP as the brain, but I suspect it will be ported to the other LPs over time.

    The quality of the ESCs out there varies wildly.  FOC is certainly a more efficient technology, but we typically see about 10-15% efficiency gains.

    Can you post your i2c.c and i2c.h files? I'll see if I can get it to behave with some of the stuff I have here.

    BR,

  • Thanks Trey...

    Quad just had its first successful flight with my FOC controllers on I2C!!! Still only using a single byte I2C driver... Would post a vid but the size restrictions are too tight/

    Not sure if you've played with a 3DR PixHawk at all, but on the off chance you have, i'm running the I2C driver by microkoper - mkblctrl pretty much raw...

    I2C headers are attached - can't remember if I changed anything from Michael Jordans, been playing with it on/off for a few months now.

    Setup in my main.c (itself a hybrid lab 5a/b instaspin mix)...

     

      // i2cHandle = I2C_init(&i2c,sizeof(i2c));
      i2cHandle = I2C_init((void *)I2CA_BASE_ADDR,sizeof(I2C_Obj));
    
      i2cgpio_Handle = GPIO_init((void *)GPIO_BASE_ADDR,sizeof(GPIO_Obj));
    
    
      GPIO_setPullUp(i2cgpio_Handle,GPIO_Number_32,GPIO_PullUp_Disable);
      GPIO_setPullUp(i2cgpio_Handle,GPIO_Number_32,GPIO_PullUp_Disable);
    
      GPIO_setQualification(i2cgpio_Handle,GPIO_Number_32,GPIO_Qual_ASync);
      GPIO_setQualification(i2cgpio_Handle,GPIO_Number_33,GPIO_Qual_ASync);
    
      GPIO_setMode(i2cgpio_Handle,GPIO_Number_32,GPIO_32_Mode_SDAA);
      GPIO_setMode(i2cgpio_Handle,GPIO_Number_33,GPIO_33_Mode_SCLA);
    
    HAL_enableI2CInts(halHandle); //Init I2c interrupts
    
      /* SLAVE SETUP*/
       I2C_setSlaveAddress(i2cHandle, 0x2a);
       I2C_setupClock(i2cHandle, 9, 10, 5);
       I2C_setDataCount(i2cHandle,1);
       I2C_set7BitAddress(i2cHandle);
       I2C_enableInt(i2cHandle, I2C_IntEn_Tx_Rdy | I2C_IntEn_Rx_Rdy);
       //I2C_enableInt(i2cHandle, I2C_IntEn_Rx_Rdy);
       I2C_enable(i2cHandle); //0x0020;
    
      OutData[0] = 10;
      OutData[1] = 100;
      OutData[2] = 30;
    

    Pull-ups disabled as they are on on the PX4 side...

    changes to HAL

    //////////////////////////PF////////////////////////////////////
    void HAL_enableI2CInts(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // enable the PIE interrupts associated with the ADC interrupts
      PIE_enableI2CInt(obj->pieHandle);
    
    
      // enable the cpu interrupt for ADC interrupts
      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_8);
    
      return;
    } // end of HAL_enableAdcInts() function
    ///////////////////////////////////////////////////////////////
    
    

    HAL.h

    interrupt void i2c_int1a_isr(void); //PF
    
    ///////////////////////////////////////////////PF/////////////////////////////////////////////////
    static inline void HAL_acqI2CInt(HAL_Handle handle)//,const ADC_IntNumber_e intNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // clear the ADC interrupt flag
      //ADC_clearIntFlag(obj->adcHandle,intNumber);
    
    
      // Acknowledge interrupt from PIE group 10
      PIE_clearInt(obj->pieHandle,PIE_GroupNumber_8);
    
      return;
    } // end of HAL_acqAdcInt() function
    
    ////////////////////////////////////////////PF//////////////////////////////////////////////////////
    
    extern void HAL_enableI2CInts(HAL_Handle handle);//PF
    
      pie->I2CINT1A = &i2c_int1a_isr;//PF

    pie.c

    /////////////////////////////////PF/////////////////////////////////////
    void PIE_enableI2CInt(PIE_Handle pieHandle)
    {
        PIE_Obj *pie = (PIE_Obj *)pieHandle;
       // uint16_t index;
       // uint16_t setValue;
    
        // set the value
        pie->PIEIER_PIEIFR[7].IER |= 1;
    
        return;
    } // end of PIE_enableAdcInt() function
    ///////////////////////////////////////////////////////////////////////

    add extern void for above in pie.h

    extern void PIE_enableI2CInt(PIE_Handle pieHandle);//PF

    ***************************I2C ISR***********************************************

    interrupt void i2c_int1a_isr(void)
     { int temp =0;
     temp = I2C_getIntSource(i2cHandle);
    
    	  if(temp ==0x04)
    	  {
    		  ReqID = I2C_getData(i2cHandle);
    		  
    	  }
     if(temp==0x05)
    	 	  {
    		  	 //for(i=0; i<3; i++)
    		  	  //{
    		  if(i >2)// Keep index
    		  	  {i=0;}
    		  		  I2C_putData(i2cHandle,OutData[i]);
    		  		  i++;
    		  	 // }
    		  //	txcnt++;
    	 	  }
    		
    	    	 
    	    								
    
    	  HAL_acqI2CInt(halHandle);
    
     }

    This is a slimmed down I2C routine - mine has some set-point management stuff in it as-well, but this is the crux of it...

    As mentioned, this setup is flawless when I use it for a single byte read in. It doesn't work with a two byte protocol (logic pic from OP) - in that case I just read in the data (ReqID) twice... as in ReqID[0] = I2C_getData(i2cHandle); then immediately ReqID[1] = I2C_getData(i2cHandle); ... I have also tried reading in RegID[] on each interrupt and keeping an index to track... after first read, stay in interrupt until SCD bit/ bus busy bit/ and every other combination I could think of...

    *This is my first play with I2C (conceptually more difficult than SCI/SPI IMO) so it is entirely possible I am missing something fundamental for a multi-byte read in protocol... Not sure, most examples/explanations are for the master side which as I understand it should handle all the nuts and bolts of it and I (slave) should just wait for data and read/send accordingly?

    Thanks, hope that made some sense - hard to explain where I'm at with this.

    Edit: Just realised that the 1/2byte read in may not make sense without mkblctrl context. Basically, microkopter release two versions of esc's that use I2C. Version one is an 8bit set-point and version 2 is 11bit. The drivers on the PX4 side are setup to allow use of both versions of esc by looking at the slave 'PWM' feedback... I basically emulate this on the TI side which allows me to switch between 8bit and 11bit or revision 1 or 2... With the code as above, version 1 runs perfectly but version 2 will get confused between the high and low bytes - its not spurious data, the high and low bytes are read in, just in a sporadic order as in ReqID[0] will bounce between the high and low byte randomly as with ReqID[1].

    //#############################################################################
    //
    //! \file   f2802x_common/source/i2c.c
    //!
    //! \brief  Contains the various functions related to the inter-integrated
    //!         circuit (I2C) object
    //
    //  Group:          C2000
    //  Target Device:  TMS320F2802x
    //
    //  (C) Copyright 2012, Texas Instruments, Inc.
    //#############################################################################
    // $TI Release: f2802x Support Library v210 $
    // $Release Date: Mon Sep 17 09:13:31 CDT 2012 $
    //#############################################################################
    
    //*****************************************************************************
    //! \addtogroup i2c_api
    //! @{
    //*****************************************************************************
    
    //#include "DSP28x_Project.h"
    //#include "F2807x_Device.h"
    #include "i2c.h"
    
    I2C_Handle I2C_init(void *pMemory, const size_t num_bytes)
    {
        I2C_Handle i2cHandle;
        if (num_bytes < sizeof(I2C_Obj)) return ((I2C_Handle)NULL);
        // assign the handle
        i2cHandle = (I2C_Handle)pMemory;
        return (i2cHandle);
    } // end of I2C_init() function
    
    //Note final clock must be between 7 and 12MHz for propper I2C operation
    void I2C_setupClock(I2C_Handle i2cHandle, const uint16_t preScalar,
                        const  uint16_t bitTimeLow, const uint16_t bitTimeHigh)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        i2c->I2CPSC = (preScalar - 1) & I2C_I2CPSC_IPSC_BITS;
        i2c->I2CCLKL = bitTimeLow;
        i2c->I2CCLKH = bitTimeHigh;
    }
    
    void I2C_set10BitAddress(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_XA_BIT;
    }
    
    void I2C_set7BitAddress(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_XA_BIT;
    }
    
    
    void I2C_setMode(I2C_Handle i2cHandle, unsigned int bitMask)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CMDR = bitMask;
        return;
    }
    
    void I2C_setRptMode(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_RM_BIT;
    }
    
    void I2C_clearRptMode(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_RM_BIT;
    }
    
    void I2C_setDigitalLoopback(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_DLB_BIT;
    }
    
    void I2C_clearDigitalLoopback(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_DLB_BIT;
    }
    
    int I2C_getBusBusy(I2C_Handle i2cHandle)
    {
        int BB_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        BB_state = i2c->I2CSTR & I2C_I2CSTR_BB_BITS;
        BB_state >>= 12;
        return BB_state;
    }
    
    int I2C_getRxReady(I2C_Handle i2cHandle)
    {
        int RRDY_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Get the RRDY status
        RRDY_state = i2c->I2CSTR & I2C_I2CSTR_RRDY_BITS;
        RRDY_state >>= 3;
        return RRDY_state;
    }
    
    int I2C_getAss(I2C_Handle i2cHandle) //PF
    {
        int Ass_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Get the RRDY status
        Ass_state = i2c->I2CSTR & I2C_I2CIER_AAS_BITS;
        Ass_state >>= 6;
        return Ass_state;
    }
    
    int I2C_getRsfull(I2C_Handle i2cHandle) //PF
    {
        int Rsfull_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Get the RRDY status
        Rsfull_state = i2c->I2CSTR & I2C_I2CSTR_RSFULL_BITS;
        Rsfull_state >>= 11;
        return Rsfull_state;
    }
    
    int I2C_getTxReady(I2C_Handle i2cHandle)
    {
        int XRDY_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Get the RRDY status
        XRDY_state = i2c->I2CSTR & I2C_I2CSTR_XRDY_BITS;
        XRDY_state >>= 4;
        return XRDY_state;
    }
    
    int I2C_getStopCondition(I2C_Handle i2cHandle)
    {
        int STP_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Retrieve the STP stop condition bit status.
        // The caller will need to call this function to see if this bit is cleared
        // from any previous master communication.
        // Clearing of this bit by the module is delayed until after the SCD bit is
        // set. If this bit is not checked prior to initiating a new message, the
        // I2C could get confused.
        STP_state = i2c->I2CMDR & I2C_I2CMDR_STP_BIT;
        STP_state >>= 11;
        return STP_state;
    }
    
    int I2C_getStopCondDetected(I2C_Handle i2cHandle)
    {
        int SCD_state;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        SCD_state = i2c->I2CSTR & I2C_I2CSTR_SCD_BITS;
        SCD_state >>= 5;
        return SCD_state;
    }
    
    void I2C_clearModuleReset(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_IRS_BIT;
    }
    
    void I2C_setModuleReset(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_IRS_BIT;
    }
    
    void I2C_setExtendedStart(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_STB_BIT;
    }
    
    void I2C_setNormalStart(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_STB_BIT;
    }
    
    void I2C_setFreeDataFormat(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_FDF_BIT;
    }
    
    void I2C_clearFreeDataFormat(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_FDF_BIT;
    }
    
    void I2C_setTransmit(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_TRX_BIT;
    }
    
    void I2C_setReceive(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_TRX_BIT;
    }
    
    void I2C_setStop(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_STP_BIT;
    }
    
    void I2C_clearStop(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_STP_BIT;
    }
    
    void I2C_setStart(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_STT_BIT;
    }
    
    void I2C_clearStart(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_STT_BIT;
    }
    
    void I2C_setDataCount(I2C_Handle i2cHandle, int dcount)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CCNT = dcount;
    }
    
    //*****************************************************************************
    //! Disable the I2C Master block.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! This will disable operation of the I2C Master block.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_disable(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the I2C peripheral
        i2c->I2CMDR &= ~I2C_I2CMDR_IRS_BIT;
    }
    
    //*****************************************************************************
    //! Enables the I2C Master block.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! This will enable operation of the I2C Master block.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_enable(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Enable the I2C peripheral
        i2c->I2CMDR |= I2C_I2CMDR_IRS_BIT;
    }
    
    //*****************************************************************************
    //! Enables the I2C Master block.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! This will enable operation of the I2C Master block.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_setMaster(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Enable the master block.
        i2c->I2CMDR |= I2C_I2CMDR_MST_BIT;
    }
    
    //*****************************************************************************
    //! Enables the I2C Slave block.
    //!
    //! \param ulBase is the base address of the I2C Slave module.
    //!
    //! This will enable operation of the I2C Slave block.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_setSlave(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Enable the slave.
        i2c->I2CMDR &= ~I2C_I2CMDR_MST_BIT;
    }
    
    //*****************************************************************************
    //! Enables the I2C interrupts
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! Enables the I2C Master interrupt source.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_enableInt(I2C_Handle i2cHandle, const I2C_IntEnable_e interrupts)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable all interrupt bits first
        i2c->I2CIER &= ~0x7F;
        // Enable selected interrupt bits
        i2c->I2CIER |= interrupts;
    }
    
    void I2C_enableFifo(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Enable the fifo
        i2c->I2CFFTX |= I2C_I2CFFTX_FFEN_BIT;
    }
    
    void I2C_clearTxFifoInt(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the FIFO interrupt
        i2c->I2CFFTX |= I2C_I2CFFTX_TXFFINTCLR_BIT;
    }
    
    void I2C_clearRxFifoInt(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the FIFO interrupt
        i2c->I2CFFRX |= I2C_I2CFFRX_RXFFINTCLR_BIT;
    }
    
    void I2C_disableFifo(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable the fifo
        i2c->I2CFFTX &= ~I2C_I2CFFTX_FFEN_BIT;
    }
    
    void I2C_resetTxFifo(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Reset the TX FIFO
        i2c->I2CFFTX |= I2C_I2CFFTX_TXFFRST_BIT;
    }
    
    void I2C_resetRxFifo(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Reset the RX FIFO
        i2c->I2CFFRX |= I2C_I2CFFRX_RXFFRST_BIT;
    }
    
    
    //*****************************************************************************
    //! Disables the I2C Master interrupt.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! Disables the I2C Master interrupt source.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_disableInt(I2C_Handle i2cHandle, const I2C_IntEnable_e interrupts)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Disable interrupts
        i2c->I2CIER &= ~interrupts;
    }
    
    //*****************************************************************************
    //! Gets the current I2C interrupt source.
    //!
    //! \param ulBase is the base address of the I2C module.
    //! \param bMasked is false if the raw interrupt status is requested and
    //! true if the masked interrupt status is requested.
    //!
    //! This returns the interrupt source for the I2C module.  
    //!
    //! \return The current interrupt source as an INTCODE (I2C_IntSource_e enum value)
    //*****************************************************************************
    I2C_IntSource_e I2C_getIntSource(I2C_Handle i2cHandle)
    {
        I2C_IntSource_e retval;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Return the i2c status
        retval = (I2C_IntSource_e)(i2c->I2CISRC);
        return retval;
    }
    
    //*****************************************************************************
    //! Gets the current I2C Master interrupt status.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //! \param bMasked is false if the raw interrupt status is requested and
    //! true if the masked interrupt status is requested.
    //!
    //! This returns the interrupt status for the I2C Master module.  Either the
    //! raw interrupt status or the status of interrupts that are allowed to
    //! reflect to the processor can be returned.
    //!
    //! \return Current interrupt status as a bit mask (use I2C_I2CSTR_xxx_BITS to mask off)
    //*****************************************************************************
    uint16_t I2C_getStatus(I2C_Handle i2cHandle)
    {
        uint16_t retval;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Return the i2c status
        retval = i2c->I2CSTR;
        return retval;
    }
    
    void I2C_clearArbLost(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the status bit
        i2c->I2CSTR &= ~I2C_CLR_AL_BIT;
    }
    
    void I2C_clearNACK(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the status bit
        i2c->I2CSTR &= ~I2C_CLR_NACK_BIT;
    }
    
    void I2C_clearAccessReady(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the status bit
        i2c->I2CSTR &= ~I2C_CLR_ARDY_BIT;
    }
    
    void I2C_clearReceiveDataReady(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the status bit
        i2c->I2CSTR &= ~I2C_CLR_RRDY_BIT;
    }
    
    void I2C_clearStopCondDetected(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Clear the status bit
        i2c->I2CSTR &= ~I2C_CLR_SCD_BIT;
    }
    
    I2C_FifoStatus_e I2C_getTxFifoStatus(I2C_Handle i2cHandle)
    {
        I2C_FifoStatus_e retval;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Return the i2c status
        retval = (I2C_FifoStatus_e)((i2c->I2CFFTX) & 0x1F00);
        return retval;
    }
    
    I2C_FifoStatus_e I2C_getRxFifoStatus(I2C_Handle i2cHandle)
    {
        I2C_FifoStatus_e retval;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Return the i2c status
        retval = (I2C_FifoStatus_e)((i2c->I2CFFRX) & 0x1F00);
        return retval;
    }
    
    int I2C_getRxFifoInt(I2C_Handle i2cHandle)
    {
        int FFRX_cond;
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Get the RX FFINT condition
        FFRX_cond = i2c->I2CFFRX & I2C_I2CFFRX_RXFFINT_BIT;
        FFRX_cond >>= 7;
        return FFRX_cond;
    }
    
    //*****************************************************************************
    //! Initializes the I2C Slave block.
    //!
    //! \param ulBase is the base address of the I2C Slave module.
    //! \param ucSlaveAddr 7-bit slave address
    //!
    //! This function initializes operation of the I2C Slave block.  Upon
    //! successful initialization of the I2C blocks, this function will have set
    //! the slave address and have enabled the I2C Slave block.
    //!
    //! The parameter \e ucSlaveAddr is the value that will be compared against the
    //! slave address sent by an I2C master.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_setSlaveAddress(I2C_Handle i2cHandle, const uint16_t slaveAddress)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Must enable the device before doing anything else.
        I2C_enable(i2cHandle);
        // Set up the slave address.
        i2c->I2COAR = slaveAddress;
    }
    
    //*****************************************************************************
    //! Sets the address that the I2C Master will place on the bus.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //! \param ucSlaveAddr 7-bit slave address
    //! \param bReceive flag indicating the type of communication with the slave
    //!
    //! This function will set the address that the I2C Master will place on the
    //! bus when initiating a transaction.  When the \e bReceive parameter is set
    //! to \b true, the address will indicate that the I2C Master is initiating a
    //! read from the slave; otherwise the address will indicate that the I2C
    //! Master is initiating a write to the slave.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_setMasterSlaveAddr(I2C_Handle i2cHandle, const uint16_t slaveAddress)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Set the address of the slave with which the master will communicate.
        i2c->I2CSAR = slaveAddress;
    }
    
    //*****************************************************************************
    //! Indicates whether or not the I2C Master is busy.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! This function returns an indication of whether or not the I2C Master is
    //! busy transmitting or receiving data.
    //!
    //! \return Returns \b true if the I2C Master is busy; otherwise, returns
    //! \b false.
    //*****************************************************************************
    bool_t I2C_isMasterBusy(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Return the busy status.
        if (i2c->I2CSTR & I2C_I2CSTR_BB_BITS)
        {
            return (true);
        } else
        {
            return (false);
        }
    }
    
    void I2C_setNackmod(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Set the bit
        i2c->I2CMDR |= I2C_I2CMDR_NAKMOD_BIT;
    }
    
    void I2C_clearNackmod(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Set the bit
        i2c->I2CMDR &= ~I2C_I2CMDR_NAKMOD_BIT;
    }
    
    void I2C_setDebugFree(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Set the bit
        i2c->I2CMDR |= I2C_I2CMDR_FREE_BIT;
    }
    
    void I2C_clearDebugFree(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Set the bit
        i2c->I2CMDR &= (~I2C_I2CMDR_FREE_BIT);
    }
    
    //*****************************************************************************
    //! Transmits a byte from the I2C Master.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //! \param ucData data to be transmitted from the I2C Master
    //!
    //! This function will place the supplied data into I2C Master Data Register.
    //!
    //! \return None.
    //*****************************************************************************
    void I2C_putData(I2C_Handle i2cHandle, uint16_t data)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Write the byte.
        i2c->I2CDXR = data;
    }
    
    //*****************************************************************************
    //! Receives a byte that has been sent to the I2C Master.
    //!
    //! \param ulBase is the base address of the I2C Master module.
    //!
    //! This function reads a byte of data from the I2C Master Data Register.
    //!
    //! \return Returns the byte received from by the I2C Master, cast as an
    //! unsigned long.
    //*****************************************************************************
    uint16_t I2C_getData(I2C_Handle i2cHandle)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // Read the byte.
        return (i2c->I2CDRR);
    }
    
    void I2C_setRxFifoIntLevel(I2C_Handle i2cHandle, const I2C_FifoLevel_e fifoLevel)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFRX |= fifoLevel;
        return;
    }
    
    void I2C_setTxFifoIntLevel(I2C_Handle i2cHandle, const I2C_FifoLevel_e fifoLevel)
    {
        // Check the arguments.
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFTX |= fifoLevel;
        return;
    }
    
    void I2C_enableTxFifoInt(I2C_Handle i2cHandle)
    {
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFTX |= I2C_I2CFFTX_TXFFIENA_BIT;
        return;
    } // end of I2C_enableTxFifoInt() function
    
    void I2C_disableTxFifoInt(I2C_Handle i2cHandle)
    {
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFTX &= ~I2C_I2CFFTX_TXFFIENA_BIT;
        return;
    } // end of I2C_enableTxFifoInt() function
    
    void I2C_enableRxFifoInt(I2C_Handle i2cHandle)
    {
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFRX |= I2C_I2CFFRX_RXFFIENA_BIT;
        return;
    } // end of I2C_enableRxFifoInt() function
    
    void I2C_disableRxFifoInt(I2C_Handle i2cHandle)
    {
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CFFRX &= ~I2C_I2CFFRX_RXFFIENA_BIT;
        return;
    } // end of I2C_enableRxFifoInt() function
    
    void I2C_setCharLength(I2C_Handle i2cHandle, const I2C_BitCount_e charLength)
    {
        I2C_Obj *i2c = (I2C_Obj * )i2cHandle;
        // set the bits
        i2c->I2CMDR = charLength;
        return;
    } // SCI_setCharLength() function
    
    //*****************************************************************************
    // Close the Doxygen group.
    //! @}
    //*****************************************************************************
    
    
    
    2330.i2c.h

  • Patrick,

    I haven't played with the PixHawk, but I think I have an understanding of your system.

    You're completely right that I2c is a little more tricky than SPI or UART.  I2c adds a layer of protocol on top of the physical communications layer that these other serial peripherals don't have.  On top of that, I've found that our I2c peripheral isn't the easiest to use.

    I'm working right now on developing an I2c driver that makes use of the FIFOs and interrupts, but its proving more difficult than I originally thought.  Give me another day or two to see if I can get it working, and if I do I'll post it here for you.

    BR,