CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PIC24 PCD compiler and MPLAB X compiler I2C?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
allenhuffman



Joined: 17 Jun 2019
Posts: 639
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PIC24 PCD compiler and MPLAB X compiler I2C?
PostPosted: Thu Oct 02, 2025 4:01 pm     Reply with quote

I have been trying to make common source files that work with our CCS PCD projects and a new one that is using the MPLAB X compiler.

I have been unable to find examples of this "Foundation Services Library" I2C code, and neither A.I. I have tried to use has produced code that fully works.

Original:

Code:
bool AD5272WriteCommandData (unsigned int address, uint8_t command, uint16_t data)
{
    bool status = false;
    uint16_t value = (((uint16_t)command & AD5272_CMD_MASK) << 10) | (data & AD5272_DATA_MASK);

    //AD5272_PRINTF ("AD5272WriteCommandData (0x%x, 0x%x, 0x%x)\r\n", address, command, data);

#if defined(__PCD__) // CCS PCD compiler.
    unsigned int ackStatus = 0;

    // Send start condition
    i2c_start (AD5272_I2C_STREAM);
   
    // Send address with write bit (0)
    ackStatus = i2c_write (AD5272_I2C_STREAM, address << 1);
    if (ackStatus == 0)
    {
        // ACK'd, so something is there, continue writing.
        i2c_write (AD5272_I2C_STREAM, value >> 8);
        i2c_write (AD5272_I2C_STREAM, value & 0xff);
       
        status = true;
    }
   
    // Send stop condition
    i2c_stop (AD5272_I2C_STREAM);

#else // assume MPLAB X compiler.

     ...snip...

#endif

    return status;
}


Does anyone here work with both systems?

The code that was presented to me in MPLABs uses "void i2c2_waitForEvent(uint16_t*);" over there, and looks like it may require some steps to have interrupts working.

I am using a PIC24FJ1024GA606 for this project, but I am happy with a polled I2C approach like we do in CCS. This MPLAB code looks like it wants interrupts, since that wait function is looking at slave and master IRQ bits.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?

Using: 24FJ256GA106, 24EP256GP202 and 24FJ64GA002.
allenhuffman



Joined: 17 Jun 2019
Posts: 639
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 03, 2025 11:36 am     Reply with quote

Wow, the "Foundation Services" functions in MPLAB are basically just C wrappers to I2C register calls. I've chatted with Bing Copilot, Google Gemini, and even Claude and none of them can produce working I2C code.

I have learned you need to manually clear IRQs (polled mode) and such, so I can at least see traffic and get responses from the chip, but it leaves the bus in a weird state according to the Saleae Logic captures I have done.

"The grass is always greener on the other side."

This is a good example of how easy the CCS routines are compared to what this MPLAB stuff seems to require -- and the MPLAB stuff is still not working the same way:

Code:
uint16_t AD5272ReadCommandData (unsigned int address, uint8_t command, uint16_t data)
{
    uint16_t retValue = 0;
    uint16_t value = ((command & AD5272_CMD_MASK) << 10) | (data & AD5272_DATA_MASK);

    //AD5272_PRINTF ("AD5272ReadCommandData (0x%x, 0x%x, 0x%x)\r\n", address, command, data);

#if defined(__PCD__) // CCS PCD compiler.
    unsigned int ackStatus = 0;
   
    // Send start condition
    i2c_start (AD5272_I2C_STREAM);
   
    // Send address with write bit (0)
    ackStatus = i2c_write (AD5272_I2C_STREAM, address << 1);
    if (ackStatus == 0)
    {
        // ACK'd, so something is there, continue writing.
        uint8_t msb = 0;
        uint8_t lsb = 0;

        i2c_write (AD5272_I2C_STREAM, value >> 8); // MSB
        i2c_write (AD5272_I2C_STREAM, value & 0xff); // LSB

        // Send repeated start condition.
        i2c_start (AD5272_I2C_STREAM);
       
        // Send address with write bit (1)
        i2c_write (AD5272_I2C_STREAM, (address << 1) | 1);
       
        msb = i2c_read (AD5272_I2C_STREAM, 1); // ACK
        lsb = i2c_read (AD5272_I2C_STREAM, 0); // No ACK

        retValue = (msb << 8) | lsb;
    }
   
    // Send stop condition
    i2c_stop (AD5272_I2C_STREAM);

#else // assume MPLAB X compiler.

    // i2c2_driver_driver_open() is done during system startup.
    unsigned int ackStatus = 0;
    uint16_t event;

    i2c2_driver_clearBusCollision ();
    i2c2_driver_resetBus (); // Currently an empty function.
    i2c2_clearIRQ ();        // Clear the interrupt flag
   
    // Send start condition
    i2c2_driver_start ();
    i2c2_waitForEvent (&event); // Wait for the event flag
    i2c2_clearIRQ ();         // Clear the interrupt flag

    i2c2_driver_TXData (address << 1);  // Address + Write
    i2c2_waitForEvent (&event); // Wait for the event flag
    i2c2_clearIRQ ();         // Clear the interrupt flag
    if (!i2c2_driver_isNACK())
    {
        ackStatus = true;

        // ACK'd, so something is there, continue writing.
        i2c2_driver_TXData (value >> 8); // MSB
        i2c2_waitForEvent (&event); // Wait for the event flag
        i2c2_clearIRQ ();         // Clear the interrupt flag

        i2c2_driver_TXData (value & 0xFF); // LSB
        i2c2_waitForEvent (&event); // Wait for the event flag
        i2c2_clearIRQ ();        // Clear the interrupt flag

        // Send repeated start condition.
        i2c2_driver_restart ();
        i2c2_waitForEvent (&event); // Wait for the event flag
        i2c2_clearIRQ ();         // Clear the interrupt flag

        // Send address with write bit (1)
        i2c2_driver_TXData ((address << 1) | 1);
        i2c2_waitForEvent (&event); // Wait for the event flag
        i2c2_clearIRQ ();         // Clear the interrupt flag
    }
   
    // Only proceed to read if the initial write was ACK'd AND the Read address was ACK'd
    if (ackStatus && !i2c2_driver_isNACK())
    {
        uint8_t msb = 0;
        uint8_t lsb = 0;

        // Prepare to receive
        // BSET.B  I2C2CON.RCEN         ; Enable receive mode
        i2c2_driver_startRX (); // RCEN=1
        while (I2C2CONLbits.RCEN); // Wait for receive to complete
       
        // BCLR.B  I2C2CON.ACKDT        ; ...send ACK
        // BSET.B  I2C2CON.ACKEN        ; Send ACK/NACK
        i2c2_driver_sendACK (); // ACKDT=0, ACKEN=1
        // TODO: Wait for ACKDT/RCEN bits to clear?
        while(I2C2CONLbits.ACKEN);
       
        // BTSS.B  I2C2STAT.RBF         ; Wait for RBF (Receive Buffer Full)
        while (!i2c2_driver_isBuferFull ());
        // MOV     I2C2RCV,W0           ; Read received byte into W0
        msb = i2c2_driver_getRXData ();

        // Clear overflow if needed.
        if (I2C2STATbits.I2COV)
        {
            I2C2STATbits.I2COV = 0; // Clear overflow
        }

        i2c2_driver_startRX ();
        while (I2C2CONLbits.RCEN); // Wait for receive to complete

        i2c2_driver_sendNACK ();
        while(I2C2CONLbits.ACKEN); // ACKDT=1, ACKEN=0
       
        while (!i2c2_driver_isBuferFull ());
        lsb = i2c2_driver_getRXData ();
       
        if (I2C2STATbits.I2COV)
        {
            I2C2STATbits.I2COV = 0; // Clear overflow
        }
       
        retValue = (msb << 8) | lsb;
    }

    i2c2_driver_stop ();  // STOP condition
    i2c2_waitForEvent (&event); // Wait for the event flag
    i2c2_clearIRQ ();         // Clear the interrupt flag

    // Ensure the bus is fully released by polling the PEN/TRSTAT bits.
    while(I2C2CONLbits.PEN);
    while(I2C2STATbits.TRSTAT);   
#endif

    return retValue;
}

_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?

Using: 24FJ256GA106, 24EP256GP202 and 24FJ64GA002.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group