Pic24F I2C incomplete address - Page 1
Forum section: electronics / general

author: TbayBoy
author_rank: Contributor
timestamp: September 15, 2025, 02:44:00 pm
content: Ill try to add complete info but ask.using, pic24fj64gb002, 3.3V, Mplabx 6.25, xc16 2.10 on Linux Mint.the I2C bus speed is 100kHz, pull up resistors 2K,what is happening is the bus seems to stall after the first bit of the address, no stop bit at end. (i2cLOGIC.png)my code compiles without errors or warnings.pics attached of logic output and various registers (while program halted at the end of the i2cwrite function before returni2cLOGIC: outputi2cBRG: baud rate generator register (reload value)i2cCON: control registeri2cIF: interrupt flagsi2cSTAT: status register(config bits)Code:Config bits// CONFIG2#pragma config POSCMOD = NONE // Primary Oscillator Select (Primary Oscillator disabled)#pragma config I2C1SEL = PRI // I2C1 Pin Select bit (Use default SCL1/SDA1 pins for I2C1 )#pragma config IOL1WAY = ON // IOLOCK One-Way Set Enable (Once set, the IOLOCK bit cannot be cleared)#pragma config OSCIOFNC = ON // OSCO Pin Configuration (OSCO pin functions as I/O (RA3))#pragma config FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor (Sw Disabled, Mon Disabled)#pragma config FNOSC = FRCDIV // Initial Oscillator Select (Fast RC Oscillator with Postscaler (FRCDIV))#pragma config PLL96MHZ = ON // 96MHz PLL Startup Select (96 MHz PLL Startup is enabled automatically on start-up)#pragma config PLLDIV = DIV12 // USB 96 MHz PLL Prescaler Select (Oscillator input divided by 12 (48 MHz input))#pragma config IESO = ON // Internal External Switchover (IESO mode (Two-Speed Start-up) enabled)(header)Code:// System oscillator and time definitions#define FOSC 8000000UL // FOSC = 8Mhz#define FCY FOSC/2 // FCY = (Fosc/2)#define T1Inter 5 // Timer1 interrupt settable for (1-5ms)#define _1000ms 1000/T1Inter // 1 second#define _500ms _1000ms/2 // half second#define _250ms _500ms/2 // quarter second#define HBLED LATAbits.LATA1 // Heartbeat LED PORT A1#define TEST LATBbits.LATB10 // test pulse output#define I2C_Gen 0b0000000 // I2C general call address#define I2C_Portx 0b1111111 // I2C port expander address (1111xxx)(init)Code:void I2C1_Init() {// I2C 1 initialized// I2C on default SDA1 & SCL1 pins see I2C1SEL config bitI2C1CONbits.I2CEN=0; // Disable I2CI2C1CONbits.DISSLW=1; // slew rate disabledI2C1CONbits.ACKDT=0; // send ACK (master mode)// Set Baud Rate// I2CxBRG = ((FCY/Fscl) - (FCY/10M))-1// Fscl = 100kHz// I2C1BRG = ((4000000/100000)-(4000000/10000000))-1// = 38.6I2C1BRG = 39; // 100kHz busIFS1bits.MI2C1IF = 0; // MI2C FlagIEC1bits.MI2C1IE = 1; // Master I2C interruptI2C1CONbits.I2CEN = 1; // Enable I2Creturn;}(functions)Code:void I2C1_Test() {I2C1Start();I2C1Write((I2C_Portx<<1)&0xFE); //shift left and add write bitI2C1Stop();return;}void _ISR_PSV _MI2C1Interrupt() {IFS1bits.MI2C1IF = 0; // MI2C Flag}void I2C1Wait() {// check that ACKEN, RCEN, PEN, RSEN, SEN bits are clearwhile ((I2C1STAT & 0x04) || (I2C1CON & 0x1F));return;}void I2C1Start() {I2C1Wait();I2C1CONbits.SEN = 1; // Startwhile(I2C1CONbits.SEN); // Wait for START to endreturn;}void I2C1Stop() {I2C1Wait();I2C1CONbits.PEN = 1; // Stopwhile(I2C1CONbits.PEN); // Wait for STOP to endreturn;}unsigned char I2C1Write(unsigned char c) {// write to the transmit bufferI2C1Wait();I2C1TRN = c;I2C1Wait();//while(I2C1STATbits.TRSTAT);while(I2C1STATbits.TBF);return I2C1STATbits.ACKSTAT;}

author: mikerj
author_rank: Super Contributor
timestamp: September 16, 2025, 08:02:54 pm
content: Presumably I2C1Start(), I2C1Write() and I2C1Stop() are blocking functions that don't return until the specific I2C operation has completed? If so, what are these functions polling to determine the end of the operation and are they intended to operate with the I2C interrupt enabled (I suspect not)?

author: TbayBoy
author_rank: Contributor
timestamp: September 16, 2025, 09:09:50 pm
content: They are waiting for their status bit to clear.

author: TbayBoy
author_rank: Contributor
timestamp: September 29, 2025, 07:56:49 pm
content: it's working now.

author: TomS_
author_rank: Frequent Contributor
timestamp: October 03, 2025, 12:20:09 pm
content: In your initial logic analyser trace you have a sampling frequency that is equal to the I2C clock rate (100Khz), in the second one you are sampling at 10x the I2C clock (1Mhz).Maybe it was working to begin with but the sampling rate made it look like it wasnt?Also be cautious about watching status registers for hardware peripherals. Some bits can be "clear on read", and updating the watch window will clear those bits meaning that the code doesnt get to see the change in status and may stall as a result.