i2c sometime will stop question?

i2c sometime will stop question?

Postby jlian168 » Wed Oct 07, 2020 10:58 am

Dear All :

void I2C2_MasterTRBInsert(
uint8_t count,
I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list,
I2C2_MESSAGE_STATUS *pflag)
{

// check if there is space in the queue
if (i2c2_object.trStatus.s.full != true)
{
//LATD = ~0x88; //test
*pflag = I2C2_MESSAGE_PENDING;

i2c2_object.pTrTail->ptrb_list = ptrb_list;
i2c2_object.pTrTail->count = count;
i2c2_object.pTrTail->pTrFlag = pflag;
i2c2_object.pTrTail++;

//LATD = ~ptrb_list->address;
NOP();
// check if the end of the array is reached
if (i2c2_object.pTrTail == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
{
// adjust to restart at the beginning of the array
i2c2_object.pTrTail = i2c2_tr_queue;
}

// since we added one item to be processed, we know
// it is not empty, so set the empty status to false
i2c2_object.trStatus.s.empty = false;

// check if full
if (i2c2_object.pTrHead == i2c2_object.pTrTail)
{
// it is full, set the full status to true
i2c2_object.trStatus.s.full = true;
}

}
else
{
*pflag = I2C2_MESSAGE_FAIL;
}

// for interrupt based
if (*pflag == I2C2_MESSAGE_PENDING)
{
I2C2_WaitForLastPacketToComplete();

// The state machine has to be started manually because it runs only in the ISR.
// If we called the ISR function here function duplication would double the code size
// because this function would be called both from interrupt and from mainline code.
PIR3bits.SSP2IF = true;
//LATD = ~0x99; //test
} // block until request is complete
NOP();
}
/**/
Cause the i2c2_object.trStatus.s.full is full so cant set SSP2IE again,
How ca i solve it?

Thank u so much...
jlian168
 
Posts: 5
Joined: Mon Jun 16, 2014 8:49 am

Re: i2c sometime will stop question?

Postby ric » Sun Oct 18, 2020 9:45 am

Is this your code?
Here, you have created a pointer variable, but have not initialised it to point to anything yet
Code: Select all
*pflag = I2C2_MESSAGE_PENDING;


Here, you are copying a local variable (count), that has not been initialised yet.
Code: Select all
i2c2_object.pTrTail->count = count;
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 659
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: i2c sometime will stop question?

Postby jlian168 » Sun Oct 18, 2020 2:49 pm

Dear Sir:

I2C2_MasterWrite(&Measure_Temperature,1,SI006_ADDRESS,&status);

I hv initial the value.
Do u hv complete code?
Can u send it to me?
Cause i dont know why the SSP2IF is cant set again?

Thank u.
jlian168
 
Posts: 5
Joined: Mon Jun 16, 2014 8:49 am

Re: i2c sometime will stop question?

Postby jlian168 » Sun Oct 18, 2020 4:22 pm

Dear Sir :

Code: Select all
void I2C2_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterWriteTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
       
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }
    NOP();
}

void I2C2_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;


    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }

}


inline void I2C2_WaitForLastPacketToComplete()
{
    while(i2c2_state != S_MASTER_IDLE)
    {
        // If your code gets stuck here it is because the last packet is never completing
        // Most likely cause is that your interrupt is not firing as it should. Check if you have
        //   correctly enabled all MSSP, Peripheral and GIE interrupt settings.
        NOP();
        CLRWDT();
    }
}

void I2C2_MasterTRBInsert(
                                uint8_t count,
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C2_MESSAGE_STATUS *pflag)
{

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {   
        //LATD = ~0x88; //test
        *pflag = I2C2_MESSAGE_PENDING;

        i2c2_object.pTrTail->ptrb_list = ptrb_list;
        i2c2_object.pTrTail->count     = count;
        i2c2_object.pTrTail->pTrFlag   = pflag;
        i2c2_object.pTrTail++;
       
//LATD = ~ptrb_list->address;
        NOP();
        // check if the end of the array is reached
        if (i2c2_object.pTrTail == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
        {
            // adjust to restart at the beginning of the array
            i2c2_object.pTrTail = i2c2_tr_queue;
        }

        // since we added one item to be processed, we know
        // it is not empty, so set the empty status to false
        i2c2_object.trStatus.s.empty = false;

        // check if full
        if (i2c2_object.pTrHead == i2c2_object.pTrTail)
        {
            // it is full, set the full status to true
            i2c2_object.trStatus.s.full = true;
        }

    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }

    // for interrupt based
    if (*pflag == I2C2_MESSAGE_PENDING)
    {
        I2C2_WaitForLastPacketToComplete();
       
        // The state machine has to be started manually because it runs only in the ISR.
        // If we called the ISR function here function duplication would double the code size
        //    because this function would be called both from interrupt and from mainline code.
        PIR3bits.SSP2IF = true;
        //LATD = ~0x99; //test
    }   // block until request is complete
    NOP();
}]


/***************************************************************************************/
My mean is if *pflag = I2C2_MESSAGE_FAIL; is happened then how to do?

Thank u.
Last edited by ric on Sun Oct 18, 2020 8:12 pm, edited 1 time in total.
Reason: Fixed the opening "code" tag
jlian168
 
Posts: 5
Joined: Mon Jun 16, 2014 8:49 am

Re: i2c sometime will stop question?

Postby ric » Sun Oct 18, 2020 8:13 pm

jlian168 wrote:Dear Sir:

I2C2_MasterWrite(&Measure_Temperature,1,SI006_ADDRESS,&status);

I hv initial the value.

Where?
Neither of the values I queried are ever initialised in the code you posted here.
Do u hv complete code?

No. What makes you think I would have code to solve your problem?
Did you write this code, or are you tryuing to see how it works?
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 659
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: i2c sometime will stop question?

Postby jlian168 » Mon Oct 19, 2020 2:45 am

Dear Sir :
1. i2c2.h
Code: Select all
/**
  MSSP2 Generated Driver API Header File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c2.h

  @Summary
    This is the generated header file for the MSSP2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This header file provides APIs for driver for I2C2.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.77
        Device            :  PIC18F66K40
        Driver Version    :  2.02
    The generated drivers are tested against the following:
        Compiler          :  XC8 2.05 and above
        MPLAB              :  MPLAB X 5.20
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries.
   
    Subject to your compliance with these terms, you may use Microchip software and any
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party
    license terms applicable to your use of third party software (including open source software) that
    may accompany Microchip software.
   
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
    FOR A PARTICULAR PURPOSE.
   
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
    SOFTWARE.
*/

#ifndef _I2C2_H
#define _I2C2_H

/**
  Section: Included Files
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <xc.h>

#warning "This version of the I2C driver will be removed soon and the correct driver to use is the Foundation Services Library driver"




extern volatile uint8_t     i2c2_read_Table[2];
extern volatile uint8_t     i2c2_readRH_Table[2];
extern volatile uint8_t     i2c2_readTVOC_Table[9];

#ifdef __cplusplus  // Provide C++ Compatibility

    extern "C" {

#endif

/**
 Section: Data Type Definitions
*/

/**
  I2C Driver Message Status Type Enumeration

  @Summary
    Defines the different message status when processing
    TRBs.

  @Description
    This type enumeration specifies the different types of status
    that an i2c request will have. For every submission of an i2c
    transaction, the status of that transaction is available.
    Based on the status, new transactions can be requested to the
    driver or a recovery can be performed to resend the transaction.

 */

typedef enum
{
    I2C2_MESSAGE_COMPLETE,
    I2C2_MESSAGE_FAIL,
    I2C2_MESSAGE_PENDING,
    I2C2_STUCK_START,
    I2C2_MESSAGE_ADDRESS_NO_ACK,
    I2C2_DATA_NO_ACK,
    I2C2_LOST_STATE
} I2C2_MESSAGE_STATUS;

/**
  I2C Driver Transaction Request Block (TRB) type definition.

  @Summary
    This defines the Transaction Request Block (TRB) used by the
    i2c master in sending/receiving data to the i2c bus.

  @Description
    This data type is the i2c Transaction Request Block (TRB) that
    the needs to be built and sent to the driver to handle each i2c requests.
    Using the TRB, simple to complex i2c transactions can be constructed
    and sent to the i2c bus. This data type is only used by the master mode.

 */
typedef struct
{
    uint16_t  address;          // Bits <10:1> are the 10 bit address.
                                // Bits <7:1> are the 7 bit address
                                // Bit 0 is R/W (1 for read)
    uint8_t   length;           // the # of bytes in the buffer
    uint8_t   *pbuffer;         // a pointer to a buffer of length bytes
} I2C2_TRANSACTION_REQUEST_BLOCK;
       
/**
  Section: Interface Routines
*/
/**
  @Summary
    Initializes the MSSP instance : 2

  @Description
    This routine initializes the i2c2 driver instance for : 2
    index, making it ready for clients to open and use it.
    This routine must be called before any other I2C2 routine is called.
    This routine should only be called once during system initialization.

  @Preconditions
    None.

  @Param
    None.

  @Returns
    None.

  @Example
    <code>
        #define SLAVE_I2C_GENERIC_RETRY_MAX     100
 
        // initialize the module
        I2C2_Initialize();

        // write to an EEPROM Device
       
        uint16_t        dataAddress;
        uint8_t         sourceData[16] = {  0xA0, 0xA1, 0xA2, 0xA3,
                                            0xA4, 0xA5, 0xA6, 0xA7,
                                            0xA8, 0xA9, 0xAA, 0xAB,
                                            0xAC, 0xAD, 0xAE, 0xAF };
        uint8_t         *pData;
        uint16_t        nCount;

        uint8_t         writeBuffer[3];
        uint8_t         *pD;
        uint16_t        counter, timeOut;

        I2C2_MESSAGE_STATUS status = I2C2_MESSAGE_PENDING;

        dataAddress = 0x10;             // starting EEPROM address
        pD = sourceData;                // initialize the source of the data
        nCount = 16;                    // number of bytes to write

        for (counter = 0; counter < nCount; counter++)
        {

            // build the write buffer first
            // starting address of the EEPROM memory
            writeBuffer[0] = (dataAddress >> 8);                // high address
            writeBuffer[1] = (uint8_t)(dataAddress);            // low low address

            // data to be written
            writeBuffer[2] = *pD++;

            // Now it is possible that the slave device will be slow.
            // As a work around on these slaves, the application can
            // retry sending the transaction
            timeOut = 0;
            while(status != I2C2_MESSAGE_FAIL)
            {
                // write one byte to EEPROM (3 is the number of bytes to write)
                I2C2_MasterWrite(  writeBuffer,
                                        3,
                                        slaveDeviceAddress,
                                        &status);

                // wait for the message to be sent or status has changed.
                while(status == I2C2_MESSAGE_PENDING);

                if (status == I2C2_MESSAGE_COMPLETE)
                    break;

                // if status is  I2C2_MESSAGE_ADDRESS_NO_ACK,
                //               or I2C2_DATA_NO_ACK,
                // The device may be busy and needs more time for the last
                // write so we can retry writing the data, this is why we
                // use a while loop here

                // check for max retry and skip this byte
                if (timeOut == SLAVE_I2C_GENERIC_RETRY_MAX)
                    break;
                else
                    timeOut++;
            }

            if (status == I2C2_MESSAGE_FAIL)
            {
                break;
            }
            dataAddress++;

        }

    </code>

*/
       
void I2C2_Initialize(void);

/**
    @Summary
        Handles one i2c master write transaction with the
        supplied parameters.

    @Description
        This function prepares a TRB, then inserts it on the i2c queue.
        Finally, it waits for the transaction to complete and returns
        the result.

    @Preconditions
        None

    @Param
        address - The address of the i2c peripheral to be accessed

    @Param
        length - The length of the data block to be sent
   
    @Param
        *pdata - A pointer to the block of data to be sent
   
    @Param
        *pstatus - A pointer to the status variable that the i2c driver
            updates during the execution of the message.

    @Returns
        I2C2_MESSAGE_STATUS

     @Example
        <code>
            Refer to I2C2_Initialize() and
            I2C2_MasterRead() for an examples   
        </code>

*/

void I2C2_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pstatus);

/**
    @Summary
        Handles one i2c master read transaction with the
        supplied parameters.

    @Description
        This function prepares a TRB, then inserts it on the i2c queue.
        Finally, it waits for the transaction to complete and returns
        the result.

    @Preconditions
        None

    @Param
        address - The address of the i2c peripheral to be accessed
   
    @Param
        length - The length of the data block to be sent
   
    @Param
        *pdata - A pointer to the memory location where received data will
                 be stored

    @Param
        *pstatus - A pointer to the status variable that the i2c driver
            updates during the execution of the message.

    @Returns
        I2C2_MESSAGE_STATUS

    @Example
        <code>
 
            #define MCHP24AA512_RETRY_MAX  100  // define the retry count
            #define MCHP24AA512_ADDRESS    0x50 // slave device address

            uint8_t MCHP24AA512_Read(
                                            uint16_t address,
                                            uint8_t *pData,
                                            uint16_t nCount)
            {
                I2C2_MESSAGE_STATUS status;
                uint8_t     writeBuffer[3];
                uint16_t    timeOut;
                uint16_t    counter;
                uint8_t     *pD, ret;

                pD = pData;

                for (counter = 0; counter < nCount; counter++)
                {

                    // build the write buffer first
                    // starting address of the EEPROM memory
                    writeBuffer[0] = (address >> 8);                // high address
                    writeBuffer[1] = (uint8_t)(address);            // low low address

                    // Now it is possible that the slave device will be slow.
                    // As a work around on these slaves, the application can
                    // retry sending the transaction
                    timeOut = 0;
                    while(status != I2C2_MESSAGE_FAIL)
                    {
                        // write one byte to EEPROM (2 is the count of bytes to write)
                        I2C2_MasterWrite(   writeBuffer,
                                                2,
                                                MCHP24AA512_ADDRESS,
                                                &status);

                        // wait for the message to be sent or status has changed.
                        while(status == I2C2_MESSAGE_PENDING);

                        if (status == I2C2_MESSAGE_COMPLETE)
                            break;

                        // if status is  I2C2_MESSAGE_ADDRESS_NO_ACK,
                        //               or I2C2_DATA_NO_ACK,
                        // The device may be busy and needs more time for the last
                        // write so we can retry writing the data, this is why we
                        // use a while loop here

                        // check for max retry and skip this byte
                        if (timeOut == MCHP24AA512_RETRY_MAX)
                            break;
                        else
                            timeOut++;
                    }

                    if (status == I2C2_MESSAGE_COMPLETE)
                    {

                        // this portion will read the byte from the memory location.
                        timeOut = 0;
                        while(status != I2C2_MESSAGE_FAIL)
                        {
                            // write one byte to EEPROM (2 is the count of bytes to write)
                            I2C2_MasterRead(    pD,
                                                    1,
                                                    MCHP24AA512_ADDRESS,
                                                    &status);

                            // wait for the message to be sent or status has changed.
                            while(status == I2C2_MESSAGE_PENDING);

                            if (status == I2C2_MESSAGE_COMPLETE)
                                break;

                            // if status is  I2C2_MESSAGE_ADDRESS_NO_ACK,
                            //               or I2C2_DATA_NO_ACK,
                            // The device may be busy and needs more time for the last
                            // write so we can retry writing the data, this is why we
                            // use a while loop here

                            // check for max retry and skip this byte
                            if (timeOut == MCHP24AA512_RETRY_MAX)
                                break;
                            else
                                timeOut++;
                        }
                    }

                    // exit if the last transaction failed
                    if (status == I2C2_MESSAGE_FAIL)
                    {
                        ret = 0;
                        break;
                    }

                    pD++;
                    address++;

                }
                return (ret);

            }
   
 
        </code>

*/

void I2C2_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pstatus);

/**
    @Summary
        Inserts a list of i2c transaction requests into the i2c
        transaction queue.

    @Description
        The i2c processes lists of transaction requests.  Each transaction
        list is handled as a string of i2c restarts.  When the list of
        transactions is complete, an i2c stop is produced, the flag is set
        with the correct condition code and the next list is processed
        from the queue.

        This function inserts lists of requests prepared by the user
        application into the queue along with a pointer to the completion
        flag.

        The transaction is inserted into the list only if there is space
        in the list. If there is no space, the function exits with the
        flag set to I2C2_MESSAGE_FAIL.

    @Preconditions
        None

    @Param
        count - The numer of transaction requests in the trb_list.

    @Param
        *ptrb_list - A pointer to an array of transaction requests (TRB).
            See I2C2_TRANSACTION_REQUEST_BLOCK definition for details.
   
    @Param
        *pflag - A pointer to a completion flag.

    @Returns
        None

    @Example
        <code>

 
            void EMULATED_EEPROM_Read(
                                           uint16_t slaveDeviceAddress,
                                           uint16_t dataAddress,
                                           uint8_t *pData,
                                           uint16_t nCount)
            {
                I2C2_MESSAGE_STATUS status;
                I2C2_TRANSACTION_REQUEST_BLOCK readTRB[2];
                uint8_t     writeBuffer[3];
                uint16_t    timeOut;

                // this initial value is important
                status = I2C2_MESSAGE_PENDING;

                // build the write buffer first
                // starting address of the EEPROM memory
                writeBuffer[0] = (dataAddress >> 8);                        // high address
                writeBuffer[1] = (uint8_t)(dataAddress);                    // low low address

                // we need to create the TRBs for a random read sequence to the EEPROM
                // Build TRB for sending address
                I2C2_MasterWriteTRBBuild(   &readTRB[0],
                                                writeBuffer,
                                                2,
                                                slaveDeviceAddress);
                // Build TRB for receiving data
                I2C2_MasterReadTRBBuild(    &readTRB[1],
                                                pData,
                                                nCount,
                                                slaveDeviceAddress);

                timeOut = 0;

                while(status != I2C2_MESSAGE_FAIL)
                {
                    // now send the transactions
                    I2C2_MasterTRBInsert(2, readTRB, &status);

                    // wait for the message to be sent or status has changed.
                    while(status == I2C2_MESSAGE_PENDING);

                    if (status == I2C2_MESSAGE_COMPLETE)
                        break;

                    // if status is  I2C2_MESSAGE_ADDRESS_NO_ACK,
                    //               or I2C2_DATA_NO_ACK,
                    // The device may be busy and needs more time for the last
                    // write so we can retry writing the data, this is why we
                    // use a while loop here

                    // check for max retry and skip this byte
                    if (timeOut == SLAVE_I2C_GENERIC_RETRY_MAX)
                        break;
                    else
                        timeOut++;

                }

            }   
 
        </code>

*/

void I2C2_MasterTRBInsert(
                                uint8_t count,
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C2_MESSAGE_STATUS *pflag);

/**
    @Summary
        This function populates a trb supplied by the calling function
        with the parameters supplied by the calling function.

    @Description
        All i2c requests are in the form of TRB's. This helper function
        takes standard parameters and correctly formats the TRB. The R/W
        bit is set to ensure that the resulting TRB describes an i2c read
        operation.

        This function does not send the transaction. To send the transaction,
        the TRB insert function (I2C2_MasterTRBInsert()) must be called.

    @Preconditions
        None

    @Param
        *ptrb - A pointer to a caller supplied TRB.

    @Param
        *pdata - A pointer to the block of data to be received

    @Param
        length - The length of the data block to be received

    @Param
        address - The address of the i2c peripheral to be accessed

    @Returns
        None

    @Example
        <code>
            Refer to I2C2_MasterTRBInsert() for an example   
        </code>

*/

void I2C2_MasterReadTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address);

/**
    @Summary
        This function populates a trb supplied by the calling function
        with the parameters supplied by the calling function.

    @Description
        All i2c requests are in the form of TRB's.  This helper function
        takes standard parameters and correctly formats the TRB. The R/W
        bit is cleared to ensure that the resulting TRB describes an i2c
        write operation.

        This function does not send the transaction. To send the transaction,
        the TRB insert function (I2C2_MasterTRBInsert()) must be called.

    @Preconditions
        None

    @Param
        *ptrb - A pointer to a caller supplied TRB.

    @Param
        *pdata - A pointer to the block of data to be sent

    @Param
        length - The length of the data block to be sent

    @Param
        address - The address of the i2c peripheral to be accessed

    @Returns
        None

    @Example
        <code>
            Refer to I2C2_MasterTRBInsert() for an example   
        </code>

*/

void I2C2_MasterWriteTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address);

/**
    @Summary
        This function returns the empty status of the Master
        queue.

    @Description
        This function returns the empty status of the Master
        queue. Use this function to check if the queue is empty.
        This can verify if the Master is currently idle.

    @Preconditions
        None

    @Param
        None

    @Returns
        True if the queue is empty and false if the queue is not empty.

    @Example
        <code>
            #define MCHP24AA512_ADDRESS    0x50 // slave device address

            // check until queue is empty
            while(I2C2_MasterQueueIsEmpty() == false);
           
            // now send more data (assume readBuffer is initialized)
            I2C2_MasterRead(   readBuffer,
                                    3,
                                    MCHP24AA512_ADDRESS,
                                    &status);   
 
        </code>

*/

bool I2C2_MasterQueueIsEmpty(void);

/**
    @Summary
        This function returns the full status of the Master
        queue.

    @Description
        This function returns the full status of the Master
        queue. Use this function to check if the queue is full.
        This can verify if the Master will not be able to accept
        addition transactions.

    @Preconditions
        None

    @Param
        None

    @Returns
        True if the queue is full and false if the queue is not full.

    @Example
        <code>
            #define MCHP24AA512_ADDRESS    0x50 // slave device address
 
            // check until queue has space
            while(I2C2_MasterQueueIsFull() == true);
           
            // now send more data (assume readBuffer is initialized)
            I2C2_MasterRead(   readBuffer,
                                    3,
                                    MCHP24AA512_ADDRESS,
                                    &status);
        </code>

*/

bool I2C2_MasterQueueIsFull(void);

void I2C2_BusCollisionISR( void );
void I2C2_ISR ( void );


#ifdef __cplusplus  // Provide C++ Compatibility

    }

#endif

#endif //_I2C2_H
   
/**
 End of File
*/


2. i2c2.c
Code: Select all
/**
  MSSP2 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c2.c

  @Summary
    This is the generated header file for the MSSP2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This header file provides APIs for driver for I2C2.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.77
        Device            :  PIC18F66K40
        Driver Version    :  2.02
    The generated drivers are tested against the following:
        Compiler          :  XC8 2.05 and above
        MPLAB              :  MPLAB X 5.20   
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries.
   
    Subject to your compliance with these terms, you may use Microchip software and any
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party
    license terms applicable to your use of third party software (including open source software) that
    may accompany Microchip software.
   
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
    FOR A PARTICULAR PURPOSE.
   
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
    SOFTWARE.
*/

/**
  Section: Included Files
*/

#include "i2c2.h"


volatile uint8_t    i2c2_read_Table[2] = {0};
volatile uint8_t    i2c2_readRH_Table[2] = {0};
volatile uint8_t    i2c2_readTVOC_Table[9] = {0};
/**
  I2C Driver Queue Status Type

  @Summary
    Defines the type used for the transaction queue status.

  @Description
    This defines type used to keep track of the queue status.
 */

typedef union
{
    struct
    {
            uint8_t full:1;
            uint8_t empty:1;
            uint8_t reserved:6;
    }s;
    uint8_t status;
}I2C_TR_QUEUE_STATUS;

/**
  I2C Driver Queue Entry Type

  @Summary
    Defines the object used for an entry in the i2c queue items.

  @Description
    This defines the object in the i2c queue. Each entry is a composed
    of a list of TRBs, the number of the TRBs and the status of the
    currently processed TRB.
 */
typedef struct
{
    uint8_t                             count;          // a count of trb's in the trb list
    I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list;     // pointer to the trb list
    I2C2_MESSAGE_STATUS            *pTrFlag;       // set with the error of the last trb sent.
                                                        // if all trb's are sent successfully,
                                                        // then this is I2C2_MESSAGE_COMPLETE
} I2C_TR_QUEUE_ENTRY;

/**
  I2C Master Driver Object Type

  @Summary
    Defines the object that manages the i2c master.

  @Description
    This defines the object that manages the sending and receiving of
    i2c master transactions.
  */

typedef struct
{
    /* Read/Write Queue */
    I2C_TR_QUEUE_ENTRY          *pTrTail;       // tail of the queue
    I2C_TR_QUEUE_ENTRY          *pTrHead;       // head of the queue
    I2C_TR_QUEUE_STATUS         trStatus;       // status of the last transaction
    uint8_t                         i2cDoneFlag;    // flag to indicate the current
                                                    // transaction is done
    uint8_t                         i2cErrors;      // keeps track of errors


} I2C_OBJECT ;

/**
  I2C Master Driver State Enumeration

  @Summary
    Defines the different states of the i2c master.

  @Description
    This defines the different states that the i2c master
    used to process transactions on the i2c bus.
*/

typedef enum
{
    S_MASTER_IDLE,
    S_MASTER_RESTART,
    S_MASTER_SEND_ADDR,
    S_MASTER_SEND_DATA,
    S_MASTER_SEND_STOP,
    S_MASTER_ACK_ADDR,
    S_MASTER_RCV_DATA,
    S_MASTER_RCV_STOP,
    S_MASTER_ACK_RCV_DATA,
    S_MASTER_NOACK_STOP,
    S_MASTER_SEND_ADDR_10BIT_LSB,
    S_MASTER_10BIT_RESTART,
   
} I2C_MASTER_STATES;

/**
 Section: Macro Definitions
*/

/* defined for I2C2 */

#ifndef I2C2_CONFIG_TR_QUEUE_LENGTH
        #define I2C2_CONFIG_TR_QUEUE_LENGTH 1
#endif

#define I2C2_TRANSMIT_REG                       SSP2BUF                 // Defines the transmit register used to send data.
#define I2C2_RECEIVE_REG                        SSP2BUF                 // Defines the receive register used to receive data.

// The following control bits are used in the I2C state machine to manage
// the I2C module and determine next states.
#define I2C2_WRITE_COLLISION_STATUS_BIT         SSP2CON1bits.WCOL     // Defines the write collision status bit.
#define I2C2_MODE_SELECT_BITS                   SSP2CON1bits.SSPM     // I2C Master Mode control bit.
#define I2C2_MASTER_ENABLE_CONTROL_BITS         SSP2CON1bits.SSPEN    // I2C port enable control bit.

#define I2C2_START_CONDITION_ENABLE_BIT         SSP2CON2bits.SEN      // I2C START control bit.
#define I2C2_REPEAT_START_CONDITION_ENABLE_BIT  SSP2CON2bits.RSEN     // I2C Repeated START control bit.
#define I2C2_RECEIVE_ENABLE_BIT                 SSP2CON2bits.RCEN     // I2C Receive enable control bit.
#define I2C2_STOP_CONDITION_ENABLE_BIT          SSP2CON2bits.PEN      // I2C STOP control bit.
#define I2C2_ACKNOWLEDGE_ENABLE_BIT             SSP2CON2bits.ACKEN    // I2C ACK start control bit.
#define I2C2_ACKNOWLEDGE_DATA_BIT               SSP2CON2bits.ACKDT    // I2C ACK data control bit.
#define I2C2_ACKNOWLEDGE_STATUS_BIT             SSP2CON2bits.ACKSTAT  // I2C ACK status bit.

#define I2C2_7bit    true
/**
 Section: Local Functions
*/

void I2C2_FunctionComplete(void);
void I2C2_Stop(I2C2_MESSAGE_STATUS completion_code);

/**
 Section: Local Variables
*/

static I2C_TR_QUEUE_ENTRY                  i2c2_tr_queue[I2C2_CONFIG_TR_QUEUE_LENGTH];
static I2C_OBJECT                          i2c2_object;
static I2C_MASTER_STATES                   i2c2_state = S_MASTER_IDLE;
static uint8_t                             i2c2_trb_count = 0;

static I2C2_TRANSACTION_REQUEST_BLOCK      *p_i2c2_trb_current = NULL;
static volatile I2C_TR_QUEUE_ENTRY         *p_i2c2_current = NULL;


/**
  Section: Driver Interface
*/

void I2C2_Initialize(void)
{
    i2c2_object.pTrHead = i2c2_tr_queue;
    i2c2_object.pTrTail = i2c2_tr_queue;
    i2c2_object.trStatus.s.empty = true;
    i2c2_object.trStatus.s.full = false;

    i2c2_object.i2cErrors = 0;

    // SMP High Speed; CKE disabled;
    //SSP2STAT = 0x00;// SMP High Speed
    SSP2STAT = 0x80;// SMP standard Speed
    // SSPEN enabled; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD_I2C;
    SSP2CON1 = 0x28;
    // SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled;
    SSP2CON3 = 0x00;
    // SSPADD 159;
    SSP2ADD = 0x9F;
   
    // clear the interrupt flags
    PIR3bits.SSP2IF = 0;
    PIR3bits.BCL2IF = 0;
   
    // enable the interrupts
    PIE3bits.SSP2IE = 1;
    PIE3bits.BCL2IE = 1;
   
}

       
uint8_t I2C2_ErrorCountGet(void)
{
    uint8_t ret;

    ret = i2c2_object.i2cErrors;
    return ret;
}

void I2C2_ISR ( void )
{
     //LATD = ~0x11; //test
     
    static uint8_t  *pi2c_buf_ptr;
    static uint16_t i2c_address         = 0;
    static uint8_t  i2c_bytes_left      = 0;
    static uint8_t  i2c_10bit_address_restart = 0;

    PIR3bits.SSP2IF = 0;
   
    // Check first if there was a collision.
    // If we have a Write Collision, reset and go to idle state */
    if(I2C2_WRITE_COLLISION_STATUS_BIT)
    {
        // clear the Write colision
        I2C2_WRITE_COLLISION_STATUS_BIT = 0;
        i2c2_state = S_MASTER_IDLE;
        *(p_i2c2_current->pTrFlag) = I2C2_MESSAGE_FAIL;

        // reset the buffer pointer
        p_i2c2_current = NULL;

        return;
    }

    /* Handle the correct i2c state */
    switch(i2c2_state)
    {
        case S_MASTER_IDLE:    /* In reset state, waiting for data to send */

           
            if(i2c2_object.trStatus.s.empty != true)
            {
                // grab the item pointed by the head
                p_i2c2_current     = i2c2_object.pTrHead;
                i2c2_trb_count     = i2c2_object.pTrHead->count;
                p_i2c2_trb_current = i2c2_object.pTrHead->ptrb_list;

//LATD = ~p_i2c2_trb_current->address;

NOP();
                i2c2_object.pTrHead++;

                // check if the end of the array is reached
                if(i2c2_object.pTrHead == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
                {
                    // adjust to restart at the beginning of the array
                    i2c2_object.pTrHead = i2c2_tr_queue;
                }

                // since we moved one item to be processed, we know
                // it is not full, so set the full status to false
                i2c2_object.trStatus.s.full = false;

                // check if the queue is empty
                if(i2c2_object.pTrHead == i2c2_object.pTrTail)
                {
                    // it is empty so set the empty status to true
                    i2c2_object.trStatus.s.empty = true;
                }

                // send the start condition
                I2C2_START_CONDITION_ENABLE_BIT = 1;
               
                // start the i2c request
                i2c2_state = S_MASTER_SEND_ADDR;
                //LATD = ~0x11; //test
            }

            break;

        case S_MASTER_RESTART:

            /* check for pending i2c Request */

            // ... trigger a REPEATED START
            I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

            // start the i2c request
            i2c2_state = S_MASTER_SEND_ADDR;

            break;

        case S_MASTER_SEND_ADDR_10BIT_LSB:

            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c2_object.i2cErrors++;
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // Remove bit 0 as R/W is never sent here
                I2C2_TRANSMIT_REG = (i2c_address >> 1) & 0x00FF;

                // determine the next state, check R/W
                if(i2c_address & 0x01)
                {
                    // if this is a read we must repeat start
                    // the bus to perform a read
                    i2c2_state = S_MASTER_10BIT_RESTART;
                }
                else
                {
                    // this is a write continue writing data
                    i2c2_state = S_MASTER_SEND_DATA;
                }
            }

            break;

        case S_MASTER_10BIT_RESTART:

            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c2_object.i2cErrors++;
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // ACK Status is good
                // restart the bus
                I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

                // fudge the address so S_MASTER_SEND_ADDR works correctly
                // we only do this on a 10-bit address resend
                i2c_address = 0x00F0 | ((i2c_address >> 8) & 0x0006);

                // set the R/W flag
                i2c_address |= 0x0001;

                // set the address restart flag so we do not change the address
                i2c_10bit_address_restart = 1;

                // Resend the address as a read
                i2c2_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_SEND_ADDR:
           
            //LATD = ~0x22; //test
            /* Start has been sent, send the address byte */

            /* Note:
                On a 10-bit address resend (done only during a 10-bit
                device read), the original i2c_address was modified in
                S_MASTER_10BIT_RESTART state. So the check if this is
                a 10-bit address will fail and a normal 7-bit address
                is sent with the R/W bit set to read. The flag
                i2c_10bit_address_restart prevents the  address to
                be re-written.
             */
            if(i2c_10bit_address_restart != 1)
            {
                // extract the information for this message
                i2c_address    = p_i2c2_trb_current->address;
                pi2c_buf_ptr   = p_i2c2_trb_current->pbuffer;
                i2c_bytes_left = p_i2c2_trb_current->length;
               
               /// LATD = i2c_address; //test
            }

            // check for 10-bit address
            if(!I2C2_7bit && (0x0 != i2c_address))
            { 
                if (0 == i2c_10bit_address_restart)
                {
                    // we have a 10 bit address
                    // send bits<9:8>
                    // mask bit 0 as this is always a write                   
                    I2C2_TRANSMIT_REG = 0xF0 | ((i2c_address >> 8) & 0x0006);
                    i2c2_state = S_MASTER_SEND_ADDR_10BIT_LSB;
                }
                else
                {
                    // resending address bits<9:8> to trigger read
                    I2C2_TRANSMIT_REG = i2c_address;
                    i2c2_state = S_MASTER_ACK_ADDR;
                    // reset the flag so the next access is ok
                    i2c_10bit_address_restart = 0;
                }
            }
            else    //  7-bit address
            {
                // Transmit the address
                I2C2_TRANSMIT_REG = i2c_address;
                //SSP2BUF = 0x80;
                //I2C2_TRANSMIT_REG = 0x80;
               // LATD = I2C2_TRANSMIT_REG; //test
                //LATD = ~0x33; //test
                NOP();
                if(i2c_address & 0x01) //read=1
                {
                    //LATD = ~0x44; //test
                    // Next state is to wait for address to be acked
                    i2c2_state = S_MASTER_ACK_ADDR;
                }
                else //write=0
                {
                    // Next state is transmit
                    i2c2_state = S_MASTER_SEND_DATA;
                    //LATD = ~0x55; //test
                }
            }
            break;

        case S_MASTER_SEND_DATA:
            //LATD = ~0x66; //test
            // Make sure the previous byte was acknowledged
            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                // Transmission was not acknowledged
                i2c2_object.i2cErrors++;

                // Reset the Ack flag
                I2C2_ACKNOWLEDGE_STATUS_BIT = 0;

                // Send a stop flag and go back to idle
                I2C2_Stop(I2C2_DATA_NO_ACK);

            }
            else
            {
                // Did we send them all ?
                if(i2c_bytes_left-- == 0U)
                {
                    // yup sent them all!

                    // update the trb pointer
                    p_i2c2_trb_current++;

                    // are we done with this string of requests?
                    if(--i2c2_trb_count == 0)
                    {
                        I2C2_Stop(I2C2_MESSAGE_COMPLETE);
                       
                    }
                    else
                    {
                        // no!, there are more TRB to be sent.
                        //I2C2_START_CONDITION_ENABLE_BIT = 1;

                        // In some cases, the slave may require
                        // a restart instead of a start. So use this one
                        // instead.
                        I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

                        // start the i2c request
                        i2c2_state = S_MASTER_SEND_ADDR;

                    }
                }
                else
                {
                    // Grab the next data to transmit
                    I2C2_TRANSMIT_REG = *pi2c_buf_ptr++;
                }
            }
            break;

        case S_MASTER_ACK_ADDR:

            /* Make sure the previous byte was acknowledged */
            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {

                // Transmission was not acknowledged
                i2c2_object.i2cErrors++;

                // Send a stop flag and go back to idle
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);

                // Reset the Ack flag
                I2C2_ACKNOWLEDGE_STATUS_BIT = 0;
            }
            else
            {
                I2C2_RECEIVE_ENABLE_BIT = 1;
                i2c2_state = S_MASTER_ACK_RCV_DATA;
            }
            break;

        case S_MASTER_RCV_DATA:

            /* Acknowledge is completed.  Time for more data */

            // Next thing is to ack the data
            i2c2_state = S_MASTER_ACK_RCV_DATA;

            // Set up to receive a byte of data
            I2C2_RECEIVE_ENABLE_BIT = 1;

            break;

        case S_MASTER_ACK_RCV_DATA:

            // Grab the byte of data received and acknowledge it
            *pi2c_buf_ptr++ = I2C2_RECEIVE_REG;

            // Check if we received them all?
            if(--i2c_bytes_left)
            {

                /* No, there's more to receive */

                // No, bit 7 is clear.  Data is ok
                // Set the flag to acknowledge the data
                I2C2_ACKNOWLEDGE_DATA_BIT = 0;

                // Wait for the acknowledge to complete, then get more
                i2c2_state = S_MASTER_RCV_DATA;
            }
            else
            {

                // Yes, it's the last byte.  Don't ack it
                // Flag that we will nak the data
                I2C2_ACKNOWLEDGE_DATA_BIT = 1;

                I2C2_FunctionComplete();
            }

            // Initiate the acknowledge
            I2C2_ACKNOWLEDGE_ENABLE_BIT = 1;
            break;

        case S_MASTER_RCV_STOP:               
        case S_MASTER_SEND_STOP:

            // Send the stop flag
            I2C2_Stop(I2C2_MESSAGE_COMPLETE);
            break;

        default:

            // This case should not happen, if it does then
            // terminate the transfer
            i2c2_object.i2cErrors++;
            I2C2_Stop(I2C2_LOST_STATE);
            //LATD = ~0x44; //test
            break;

           // LATD = ~0x44; //test
    }

}

void I2C2_FunctionComplete(void)
{

    // update the trb pointer
    p_i2c2_trb_current++;

    // are we done with this string of requests?
    if(--i2c2_trb_count == 0)
    {
        i2c2_state = S_MASTER_SEND_STOP;
    }
    else
    {
        i2c2_state = S_MASTER_RESTART;
    }

}

void I2C2_Stop(I2C2_MESSAGE_STATUS completion_code)
{
    // then send a stop
    I2C2_STOP_CONDITION_ENABLE_BIT = 1;

    // make sure the flag pointer is not NULL
    if (p_i2c2_current->pTrFlag != NULL)
    {
        // update the flag with the completion code
        *(p_i2c2_current->pTrFlag) = completion_code;
    }

    // Done, back to idle
    i2c2_state = S_MASTER_IDLE;
   
   /////////// PIR3bits.SSP2IF = 0;
}

void I2C2_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterWriteTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
       
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
        //PIR3bits.SSP2IF = true;     //
        //*pflag == I2C2_MESSAGE_PENDING;
    }
    NOP();
}

void I2C2_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;


    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
         //PIR3bits.SSP2IF = true;        //
        //*pflag == I2C2_MESSAGE_PENDING;
    }

}


inline void I2C2_WaitForLastPacketToComplete()
{
    while(i2c2_state != S_MASTER_IDLE)
    {
        // If your code gets stuck here it is because the last packet is never completing
        // Most likely cause is that your interrupt is not firing as it should. Check if you have
        //   correctly enabled all MSSP, Peripheral and GIE interrupt settings.
        NOP();
        CLRWDT();
    }
}

void I2C2_MasterTRBInsert(
                                uint8_t count,
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C2_MESSAGE_STATUS *pflag)
{

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {   
        //LATD = ~0x88; //test
        *pflag = I2C2_MESSAGE_PENDING;

        i2c2_object.pTrTail->ptrb_list = ptrb_list;
        i2c2_object.pTrTail->count     = count;
        i2c2_object.pTrTail->pTrFlag   = pflag;
        i2c2_object.pTrTail++;
       
//LATD = ~ptrb_list->address;
        NOP();
        // check if the end of the array is reached
        if (i2c2_object.pTrTail == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
        {
            // adjust to restart at the beginning of the array
            i2c2_object.pTrTail = i2c2_tr_queue;
        }

        // since we added one item to be processed, we know
        // it is not empty, so set the empty status to false
        i2c2_object.trStatus.s.empty = false;

        // check if full
        if (i2c2_object.pTrHead == i2c2_object.pTrTail)
        {
            // it is full, set the full status to true
            i2c2_object.trStatus.s.full = true;
        }

    }
    else
    {
        //*pflag = I2C2_MESSAGE_FAIL;
        //PIR3bits.SSP2IF = true;     //
        //*pflag == I2C2_MESSAGE_PENDING;
    }

    // for interrupt based
    if (*pflag == I2C2_MESSAGE_PENDING)
    {
        I2C2_WaitForLastPacketToComplete();
       
        // The state machine has to be started manually because it runs only in the ISR.
        // If we called the ISR function here function duplication would double the code size
        //    because this function would be called both from interrupt and from mainline code.
        PIR3bits.SSP2IF = true;
        //LATD = ~0x99; //test
    }   // block until request is complete
    /*else if (*pflag == I2C2_MESSAGE_FAIL)
    {
        PIR3bits.SSP2IF = true;
    }*/
    NOP();
}

void I2C2_MasterReadTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address  = address << 1;
    // make this a read
    ptrb->address |= 0x01;
    ptrb->length   = length;
    ptrb->pbuffer  = pdata;
}

void I2C2_MasterWriteTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address = address << 1;
    ptrb->length  = length;
    ptrb->pbuffer = pdata;
    //LATD = ~ptrb->address; //test
    NOP();
}

bool I2C2_MasterQueueIsEmpty(void)
{
    return(i2c2_object.trStatus.s.empty);
}

bool I2C2_MasterQueueIsFull(void)
{
    return(i2c2_object.trStatus.s.full);
}       
       
void I2C2_BusCollisionISR( void )
{
    // enter bus collision handling code here
   PIR3bits.BCL2IF = 0;
}       
 



//----------------------------------------------------------------------------------------------------------------------
 

   

       
/**
 End of File
*/
jlian168
 
Posts: 5
Joined: Mon Jun 16, 2014 8:49 am


Return to SSP (IIC, SPI)

Who is online

Users browsing this forum: No registered users and 13 guests

cron