I2C not working

I2C not working

Postby Bonsai » Sun Jul 24, 2016 10:05 pm

Hello,

i tried to get the I2C on my pic16f18857 @ 3V3 running but i do not see anything with my logicanalyzer. when i drive the lines via the Latch registers, i see changing potentials (so no hardware stuff at this point). With the I2C i cant see any data and the debugger/the pic hands with the pending flag:
Code: Select all
while(status == I2C_MESSAGE_PENDING);


Overview:
- SCL: RC5
- SDA: RC6
- Both pulled to 3,3V with 2k2
- the pic should be a I2C Master @ 400khz
- Adress of Slave: 0x80

Here is my config generated in MCC 3.15 (ported to the pic16f18857 from
the generated pic16f18854 files):

i2c1.c:
Code: Select all
/**
  I2C1 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c1.c

  @Summary
    This is the generated header file for the I2C1 driver using MPLAB(c) Code Configurator

  @Description
    This header file provides APIs for driver for I2C1.
    Generation Information :
        Product Revision : MPLAB(c) Code Configurator - 3.15.0
        Device : PIC16F18854
        Driver Version : 2.00
    The generated drivers are tested against the following:
        Compiler : XC8 1.35
        MPLAB : MPLAB X 3.20
*/

/*
    (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    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, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    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.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS.
*/

/**
  Section: Included Files
*/

#include "i2c1.h"

/**
  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
    I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list; // pointer to the trb list
    I2C1_MESSAGE_STATUS *pTrFlag; // set with the error of the last trb sent.
                                                        // if all trb's are sent successfully,
                                                        // then this is I2C1_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 I2C1 */

#ifndef I2C1_CONFIG_TR_QUEUE_LENGTH
        #define I2C1_CONFIG_TR_QUEUE_LENGTH 1
#endif

#define I2C1_TRANSMIT_REG SSP1BUF // Defines the transmit register used to send data.
#define I2C1_RECEIVE_REG SSP1BUF // 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 I2C1_WRITE_COLLISION_STATUS_BIT SSP1CON1bits.WCOL // Defines the write collision status bit.
#define I2C1_MODE_SELECT_BITS SSP1CON1bits.SSPM // I2C Master Mode control bit.
#define I2C1_MASTER_ENABLE_CONTROL_BITS SSP1CON1bits.SSPEN // I2C port enable control bit.

#define I2C1_START_CONDITION_ENABLE_BIT SSP1CON2bits.SEN // I2C START control bit.
#define I2C1_REPEAT_START_CONDITION_ENABLE_BIT SSP1CON2bits.RSEN // I2C Repeated START control bit.
#define I2C1_RECEIVE_ENABLE_BIT SSP1CON2bits.RCEN // I2C Receive enable control bit.
#define I2C1_STOP_CONDITION_ENABLE_BIT SSP1CON2bits.PEN // I2C STOP control bit.
#define I2C1_ACKNOWLEDGE_ENABLE_BIT SSP1CON2bits.ACKEN // I2C ACK start control bit.
#define I2C1_ACKNOWLEDGE_DATA_BIT SSP1CON2bits.ACKDT // I2C ACK data control bit.
#define I2C1_ACKNOWLEDGE_STATUS_BIT SSP1CON2bits.ACKSTAT // I2C ACK status bit.

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

void I2C1_FunctionComplete(void);
void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code);

/**
 Section: Local Variables
*/

static I2C_TR_QUEUE_ENTRY i2c1_tr_queue[I2C1_CONFIG_TR_QUEUE_LENGTH];
static I2C_OBJECT i2c1_object;
static I2C_MASTER_STATES i2c1_state = S_MASTER_IDLE;
static uint8_t i2c1_trb_count = 0;

static I2C1_TRANSACTION_REQUEST_BLOCK *p_i2c1_trb_current = NULL;
static I2C_TR_QUEUE_ENTRY *p_i2c1_current = NULL;


/**
  Section: Driver Interface
*/


void I2C1_Initialize(void)
{
    i2c1_object.pTrHead = i2c1_tr_queue;
    i2c1_object.pTrTail = i2c1_tr_queue;
    i2c1_object.trStatus.s.empty = true;
    i2c1_object.trStatus.s.full = false;

    i2c1_object.i2cErrors = 0;

    // SMP High Speed; CKE disabled;
    SSP1STAT = 0x00;
    // SSPEN enabled; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD_I2C;
    SSP1CON1 = 0x28;
    // SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled;
    SSP1CON3 = 0x00;
    // Baud Rate Generator Value: SSPADD 3;
    //SSP1ADD = 0x03;
    SSP1ADD = 0x19;
   
    // clear the master interrupt flag
    PIR3bits.SSP1IF = 0;
    // enable the master interrupt
    PIE3bits.SSP1IE = 1;
   
}

       
uint8_t I2C1_ErrorCountGet(void)
{
    uint8_t ret;

    ret = i2c1_object.i2cErrors;
    return ret;
}

void I2C1_ISR ( void )
{
 
    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.SSP1IF = 0;

    // Check first if there was a collision.
    // If we have a Write Collision, reset and go to idle state */
    if(I2C1_WRITE_COLLISION_STATUS_BIT)
    {
        // clear the Write colision
        I2C1_WRITE_COLLISION_STATUS_BIT = 0;
        i2c1_state = S_MASTER_IDLE;
        *(p_i2c1_current->pTrFlag) = I2C1_MESSAGE_FAIL;

        // reset the buffer pointer
        p_i2c1_current = NULL;

        return;
    }

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

            if(i2c1_object.trStatus.s.empty != true)
            {
                // grab the item pointed by the head
                p_i2c1_current = i2c1_object.pTrHead;
                i2c1_trb_count = i2c1_object.pTrHead->count;
                p_i2c1_trb_current = i2c1_object.pTrHead->ptrb_list;

                i2c1_object.pTrHead++;

                // check if the end of the array is reached
                if(i2c1_object.pTrHead == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH))
                {
                    // adjust to restart at the beginning of the array
                    i2c1_object.pTrHead = i2c1_tr_queue;
                }

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

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

                // send the start condition
                I2C1_START_CONDITION_ENABLE_BIT = 1;
               
                // start the i2c request
                i2c1_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_RESTART:

            /* check for pending i2c Request */

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

            // start the i2c request
            i2c1_state = S_MASTER_SEND_ADDR;

            break;

        case S_MASTER_SEND_ADDR_10BIT_LSB:

            if(I2C1_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c1_object.i2cErrors++;
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // Remove bit 0 as R/W is never sent here
                I2C1_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
                    i2c1_state = S_MASTER_10BIT_RESTART;
                }
                else
                {
                    // this is a write continue writing data
                    i2c1_state = S_MASTER_SEND_DATA;
                }
            }

            break;

        case S_MASTER_10BIT_RESTART:

            if(I2C1_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c1_object.i2cErrors++;
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // ACK Status is good
                // restart the bus
                I2C1_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
                i2c1_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_SEND_ADDR:

            /* 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_i2c1_trb_current->address;
                pi2c_buf_ptr = p_i2c1_trb_current->pbuffer;
                i2c_bytes_left = p_i2c1_trb_current->length;
            }

            // check for 10-bit address
            if(!I2C1_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
                    I2C1_TRANSMIT_REG = 0xF0 | ((i2c_address >> 8) & 0x0006);
                    i2c1_state = S_MASTER_SEND_ADDR_10BIT_LSB;
                }
                else
                {
                    // resending address bits<9:8> to trigger read
                    I2C1_TRANSMIT_REG = i2c_address;
                    i2c1_state = S_MASTER_ACK_ADDR;
                    // reset the flag so the next access is ok
                    i2c_10bit_address_restart = 0;
                }
            }
            else
            {
                // Transmit the address
                I2C1_TRANSMIT_REG = i2c_address;
                if(i2c_address & 0x01)
                {
                    // Next state is to wait for address to be acked
                    i2c1_state = S_MASTER_ACK_ADDR;
                }
                else
                {
                    // Next state is transmit
                    i2c1_state = S_MASTER_SEND_DATA;
                }
            }
            break;

        case S_MASTER_SEND_DATA:

            // Make sure the previous byte was acknowledged
            if(I2C1_ACKNOWLEDGE_STATUS_BIT)
            {
                // Transmission was not acknowledged
                i2c1_object.i2cErrors++;

                // Reset the Ack flag
                I2C1_ACKNOWLEDGE_STATUS_BIT = 0;

                // Send a stop flag and go back to idle
                I2C1_Stop(I2C1_DATA_NO_ACK);

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

                    // update the trb pointer
                    p_i2c1_trb_current++;

                    // are we done with this string of requests?
                    if(--i2c1_trb_count == 0)
                    {
                        I2C1_Stop(I2C1_MESSAGE_COMPLETE);
                    }
                    else
                    {
                        // no!, there are more TRB to be sent.
                        //I2C1_START_CONDITION_ENABLE_BIT = 1;

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

                        // start the i2c request
                        i2c1_state = S_MASTER_SEND_ADDR;

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

        case S_MASTER_ACK_ADDR:

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

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

                // Send a stop flag and go back to idle
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);

                // Reset the Ack flag
                I2C1_ACKNOWLEDGE_STATUS_BIT = 0;
            }
            else
            {
                I2C1_RECEIVE_ENABLE_BIT = 1;
                i2c1_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
            i2c1_state = S_MASTER_ACK_RCV_DATA;

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

            break;

        case S_MASTER_ACK_RCV_DATA:

            // Grab the byte of data received and acknowledge it
            *pi2c_buf_ptr++ = I2C1_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
                I2C1_ACKNOWLEDGE_DATA_BIT = 0;

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

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

                I2C1_FunctionComplete();
            }

            // Initiate the acknowledge
            I2C1_ACKNOWLEDGE_ENABLE_BIT = 1;
            break;

        case S_MASTER_RCV_STOP:
        case S_MASTER_SEND_STOP:

            // Send the stop flag
            I2C1_Stop(I2C1_MESSAGE_COMPLETE);
            break;

        default:

            // This case should not happen, if it does then
            // terminate the transfer
            i2c1_object.i2cErrors++;
            I2C1_Stop(I2C1_LOST_STATE);
            break;

    }
}

void I2C1_FunctionComplete(void)
{

    // update the trb pointer
    p_i2c1_trb_current++;

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

}

void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code)
{
    // then send a stop
    I2C1_STOP_CONDITION_ENABLE_BIT = 1;

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

    // Done, back to idle
    i2c1_state = S_MASTER_IDLE;
   
}

void I2C1_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C1_MESSAGE_STATUS *pflag)
{
    static I2C1_TRANSACTION_REQUEST_BLOCK trBlock;

    // check if there is space in the queue
    if (i2c1_object.trStatus.s.full != true)
    {
        I2C1_MasterWriteTRBBuild(&trBlock, pdata, length, address);
        I2C1_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

}

void I2C1_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C1_MESSAGE_STATUS *pflag)
{
    static I2C1_TRANSACTION_REQUEST_BLOCK trBlock;


    // check if there is space in the queue
    if (i2c1_object.trStatus.s.full != true)
    {
        I2C1_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C1_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

}

void I2C1_MasterTRBInsert(
                                uint8_t count,
                                I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C1_MESSAGE_STATUS *pflag)
{

    // check if there is space in the queue
    if (i2c1_object.trStatus.s.full != true)
    {
        *pflag = I2C1_MESSAGE_PENDING;

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

        // check if the end of the array is reached
        if (i2c1_object.pTrTail == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH))
        {
            // adjust to restart at the beginning of the array
            i2c1_object.pTrTail = i2c1_tr_queue;
        }

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

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

    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

    // for interrupt based
    if (*pflag == I2C1_MESSAGE_PENDING)
    {
        while(i2c1_state != S_MASTER_IDLE);
        {
            // force the task to run since we know that the queue has
            // something that needs to be sent
            PIR3bits.SSP1IF = true;
        }
    } // block until request is complete

}

void I2C1_MasterReadTRBBuild(
                                I2C1_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 I2C1_MasterWriteTRBBuild(
                                I2C1_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address = address << 1;
    ptrb->length = length;
    ptrb->pbuffer = pdata;
}

bool I2C1_MasterQueueIsEmpty(void)
{
    return(i2c1_object.trStatus.s.empty);
}

bool I2C1_MasterQueueIsFull(void)
{
    return(i2c1_object.trStatus.s.full);
}
       
void I2C1_BusCollisionISR( void )
{
    // enter bus collision handling code here
}
       
       
/**
 End of File
*/


Pinmanager:
Code: Select all
void PIN_MANAGER_Initialize(void)
{
    LATB = 0x0;
    WPUE = 0x0;
    LATA = 0x0;
    LATC = 0x0;
    WPUA = 0x0;
    WPUB = 0x0;
    WPUC = 0x0;
    ANSELA = 0xE7;
    ANSELB = 0xC8;
    ANSELC = 0x7;
    //TRISB = 0xF3;
    TRISB = 0xF7;
    //TRISC = 0x72;
    TRISC = 0x70;
    TRISA = 0x27;
   
   // enable interrupt-on-change individually
 IOCBNbits.IOCBN1 = 1; // Pin : RB1
 IOCBPbits.IOCBP1 = 1; // Pin : RB1
 IOCBNbits.IOCBN2 = 1; // Pin : RB2
   

    // enable interrupt-on-change globally
    PIE0bits.IOCIE = 1;

    bool state = GIE;
    GIE = 0;
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS

    T2AINPPSbits.T2AINPPS = 0x13; //RC3->TMR2:T2IN;
   
    //SSP1CLKPPSbits.SSP1CLKPPS = 0x15; //RC5->MSSP1:SCL1;
    //SSP1DATPPSbits.SSP1DATPPS = 0x16; //RC6->MSSP1:SDA1;
    SSP1CLKPPS = 0x15; //RC5->MSSP1:SCL1;
    SSP1DATPPS = 0x16; //RC6->MSSP1:SDA1;
   
    T3CKIPPSbits.T3CKIPPS = 0x10; //RC0->TMR3:T3CKI;
    RC3PPS = 0x17; //RC3->MSSP2:SDO2;
    ADCACTPPS = 0x0C; //RB4->ADCC:ADCACT;
    RC2PPS = 0x16; //RC2->MSSP2:SCK2;
    RC5PPS = 0x14; //RC5->MSSP1:SCL1;
    RC6PPS = 0x15; //RC6->MSSP1:SDA1;
   
    //Test
    RC1PPS = 0x0E; //RC1->PWM6OUT;
   
    //SSP2DATPPSbits.SSP2DATPPS = 0x14; //RC4->MSSP2:SDI2;
    SSP2DATPPS = 0x14; //RC4->MSSP2:SDI2;

    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS

    GIE = state;


}

Writing is done by: (e.g. with data 0x12, 0x24)

In .h: #define IC_ADDR 0x80
Code: Select all
writeBuffer[0] = 0x12;
    writeBuffer[1] = 0x24;
   
    while(status != I2C1_MESSAGE_FAIL) {
        // write one byte to EEPROM (2 is the count of bytes to write)
        I2C1_MasterWrite(writeBuffer, 2, IC_ADDR, &status);

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

        if (status == I2C1_MESSAGE_COMPLETE)
            break;

        // if status is I2C1_MESSAGE_ADDRESS_NO_ACK,
        // or I2C1_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 == IC_RETRY_MAX)
            break;
        else
            timeOut++;



Thanks!
Bonsai
 
Posts: 4
Joined: Sun Jul 24, 2016 10:01 pm

Re: I2C not working

Postby ric » Sun Jul 24, 2016 11:37 pm

Yuk, that mess of code reminds me why I want nothing to do with MCC.
It's always hard to tell what's going on when you only post snippets of the complete program. Have you called the function to initialise the I2C driver?
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 not working

Postby vloki » Mon Jul 25, 2016 9:32 am

https://www.mikrocontroller.net/topic/401962#new

I think this is correct. You can not map the I2C functions to every pin.
You have to stay with the default pins or choose any of the one shown in
TABLE 2: 28-PIN ALLOCATION TABLE (PIC16(L)F18857) of the data sheet.


Did you check this?
vloki
Verified identity
 
Posts: 186
Joined: Wed May 28, 2014 8:42 am
Location: Germany
PIC experience: Professional 5+ years with MCHP products

Re: I2C not working

Postby Bonsai » Mon Jul 25, 2016 8:40 pm

I remapped the SPI2 Module to RC2 (SCK) and RC3(MOSI) - these aren't the standard pins as well, so why shouldnt that work for I2C too?

btw, the PPS feature might be quite useless without the ability to remap the pins.

Did u find any exact hints, like the one you quoted? cant find it in the sheet.

Also mcc allows the selection of these bits - i cant find any restriction :(
Bonsai
 
Posts: 4
Joined: Sun Jul 24, 2016 10:01 pm

Re: I2C not working

Postby ric » Mon Jul 25, 2016 9:15 pm

Bonsai, you have not responded to this question:
ric wrote: Have you called the function to initialise the I2C driver?
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 not working

Postby Bonsai » Mon Jul 25, 2016 10:01 pm

Oh sorry! That was so clear for me.

Code: Select all
void SYSTEM_Initialize(void)
{
   
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
    I2C1_Initialize();
    SPI2_Initialize();
    PWM6_Initialize();
    ADCC_Initialize();
    TMR3_Initialize();
    TMR2_Initialize();
}


Is called as from the MCC generated.

Here information for the mapping:
2.PNG
2.PNG (33.53 KiB) Viewed 8645 times
Bonsai
 
Posts: 4
Joined: Sun Jul 24, 2016 10:01 pm

Re: I2C not working

Postby vloki » Tue Jul 26, 2016 8:08 am

Notes:
Table 13.3
2: Each specific input signal may only be mapped to a subset of these I/O pins, as shown in Table 13-2.
Attempting to map an input signal to a non-supported I/O pin will result in undefined behavior.


Table 13.2
Note 1: Only a few of the values in this column are valid for any given
signal.


Table 2
4: These pins are configured for I2C logic levels.; The SCLx/SDAx signals may be assigned to any of the RB1/RB2/RC3/RC4 pins. PPS assignments to the other pins (e.g., RA5) will operate, but input
logic levels will be standard TTL/ST, as selected by the INLVL register, instead of the I2C specific or SMbus input buffer thresholds.


Did you try to use the default pins and see if that works?
If that works you may take the next step...
vloki
Verified identity
 
Posts: 186
Joined: Wed May 28, 2014 8:42 am
Location: Germany
PIC experience: Professional 5+ years with MCHP products

Re: I2C not working

Postby Bonsai » Tue Jul 26, 2016 8:25 pm

damn working now! hat one wrong number in the pin manager assignment... grr

Thanks!!
Bonsai
 
Posts: 4
Joined: Sun Jul 24, 2016 10:01 pm


Return to SSP (IIC, SPI)

Who is online

Users browsing this forum: No registered users and 8 guests

cron