Author Topic: Does size matter? 10-bits is a bit too much for i2c  (Read 3904 times)

0 Members and 1 Guest are viewing this topic.

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Does size matter? 10-bits is a bit too much for i2c
« on: September 11, 2022, 10:25:42 am »
Below is the code for a I2C configured as a Master 7-bit Addr sending to a Slave MCU and both are  configured without Start/End IRQ configuration.

I can't get my Slave MCU (both master and slave are pic18F252) to respond and I don't get any SSPIF when I socket the Slave MCU when this write address starting frame is sent. You can see the 0x20 address sent to it! (Addr1=0x20;)

The Nack is clearly seen where Ack should be, identifying this bit as the Ack/Nack bit, but it's 10th in line.

But what astonishes me is that I see a 10-bit frame when SEN starts sends this address! I can't make any SEN of this?

Although you can't see it on the scope trace attached, the Start and Stop events are clearly ok.  I2C baudrate 400KHz

Slave mcu is not inserted in socket, this is only the Master's game.

Attached is the scope trace that shows what I am talking about.

I have run out of hair to pull out. This I2C is driving me SEN seless!

There's an extra bit at the start!

Is this normal?  What do am I doing wrong?

//00000000000h ooooooooooooooooooh!

void GetDat() //Receiving data doesn't require interrupt ISR, Sending does.
{
 

  if(SSt==Begin)
   { if(SSPOV || WCOL)
      { AdrRec=0;    //just a 8-bit var to check the address being sent
        i2c_Setup();
        goto xitgetdat;
      }

     hh=0;uu=0;bn=0; //all unsigned int  16-bit

     i2c_start();
     SSPBUF=Addr1<<1;   //address 0x20 sent to Slv in write mode 

     waitmssp();
     bn=0;
     OhOh=0;


W4Ack:
     while(ACKSTAT)    //Waiting for Ack of address from Slave
        LATD5=1;LATD5=0;
        hh++;
        if(hh>1000)
         { OhOh=1;
           LATD6=1;LATD6=0;
           i2c_stop();
           break;
         }
      }

     if(ACKDT)
      { OhOh=2;
        AdrRec=SSPBUF;
        i2c_stop();
        goto badxit;
      }


     if(OhOh)goto badxit; //Error got a Nack instead of ack

W4byterec: 
     if(BF==0)
      { uu++;
        if(uu>65534)
         { OhOh=3;
           goto badxit;
         }
        goto W4byterec;
      }
     Rx[bn]=SSPBUF;
     i2c_ack();
     SSPIF=0;

}


void i2c_start()
{
   SEN=1;
   waitmssp();
}

void i2c_stop()
{
   PEN=1;
   waitmssp();
}

void i2c_ack()
{
   ACKDT=0;
   ACKEN=1;
   waitmssp();
}

void i2c_nak()
{
   ACKDT=1;
   ACKEN=1;
   waitmssp();
}

void waitmssp()
{
   while(!SSPIF);
   SSPIF=0;
}
« Last Edit: September 11, 2022, 11:03:55 am by Salome2 »
 

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 3372
  • Country: au
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #1 on: September 11, 2022, 08:17:29 pm »
Below is the code for a I2C configured as a Master 7-bit Addr sending to a Slave MCU and both are  configured without Start/End IRQ configuration.
But what astonishes me is that I see a 10-bit frame when SEN starts sends this address! I can't make any SEN of this?

It is normal to see 9 clocks, which is 7 bits of address 1 bit of R/W and then the ACK.
Some i2c parts have extended address, but you have too few clocks for that


https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing

If you have bogus output, one approach could be to slow things down with debug delays between each i2c access.
If you have setups or access-before-done issues you can get strange pin results.

Also try send of different address values to see where the bogus clk appears. (beginning or end?) 
The first CLK is narrower, unsure if that is a clue or an artifact.
 
« Last Edit: September 11, 2022, 08:22:44 pm by PCB.Wiz »
 
The following users thanked this post: Salome2

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6926
  • Country: es
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #2 on: September 11, 2022, 09:03:49 pm »
You're lacking all the calls, and the most important part, the setup/initialization.
Also the gotos... uhh no good, are you coming from old school assembly?

Do you really understand how i2c works? Some basics:
https://openlabpro.com/guide/basics-of-i2c/
https://rheingoldheavy.com/i2c-signals/

Of course you're not getting ACK, ACK is set by the slave by pulling SDA low, which you aren't connecting, so you're getting a NACK!

Show us the rest of your i2c-related code for the slave & master...
How is your circuit? And the pullpup resistors?
It's clearly 100KHz, not 400.

Your waveforms look wrong, i2c lines should be floating (high) when idle, but SDA is LOW before/after your clocks.
This is how a byte transfer should look:


The NAK at the end means the receiver doesn't want more bytes, thus ending the transfer.
But for the address, a matching receiver will always acknowledge.

10-bit addressing actually sends 2 bytes addressing bytes, not 10 bits! (You must take care of each of these bytes)
Check pages 144-145 of the PIC18F252 datasheet! Better you throughly read the i2c section again :D
« Last Edit: September 11, 2022, 09:31:05 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: Salome2

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #3 on: September 12, 2022, 12:56:25 am »
Thanks PCB.wiz, I have shifted the address sent and the scope clearly shows the first narrow bit is a puzzling glitch on the data line.

 If I shift the address left 3-bits, the one-bit of ox20<<3 disappears, while SSBUF=Addr1<<2 can still see the one bit as if setting the Slave an address of 0x40

The glitch bit on the left only occurs if I use SEN to start the address transmission.

I don't know why right after the SEN start event the clock is held low before starting to transmit the address bits ( using the code I  have posted!)

I do expect the Ack bit to be a Nack, as the Slave mcu is not inserted in its socket.

 All P/S voltages AOK, proper caps bypassing on the VDD pins.

 I am using 1-K pullups for I2C Clk and Data   The 1k's are positioned right at the Slave mcu Clk and Data pins of the second Slave(also not yet inserted while I try to resolve this glitch bit problem.) The total wire twisted pair length of Master to 2nd Slave <5-in.

Below is my setup code for I2C
-------------------------------------
void i2c_Setup()    // (for the Master mcu)
{

        WCOL1=0;SSPOV1=0;
        SSPCON1=0x28;  //SSP Module as Master 7-bt address I2C mode and Enabled /b]
        TRISC3=1;TRISC4=1; //Sets I2C clock and data pins as inputs
        SSPADD=((40000000/4)/400000)-1; //Setting I2C Baud/Clock Speed at , My Fosc = 40MHz   10MHz ext. Xtal PLL*4
                                       
        SSPSTATbits.SMP=1; //SMP Must be off=1 for i2c
        SSPIF=0;
        Addr1=0x20;  //I2C address of first Slave
       
        SSt=Begin;   //The MSSP operation state var (  Stores Begin as MSSP I2C state to start communication by sending Addr1 )
}

void waitmssp()
{
        while(!SSPIF);
   SSPIF=0;
}
void i2c_ack()
{
   ACKDT=0;
        ACKEN=1;
   waitmssp();
}

void i2c_nak()
{
   ACKDT=1;
   ACKEN=1;
   waitmssp();
}



« Last Edit: September 12, 2022, 09:31:27 am by Salome2 »
 

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #4 on: September 12, 2022, 01:36:09 am »
Thanks DavidAlfa. I assure you I have read and studied carefully so many datasheet I2C pages.(18F25K22, 16F18446, 18F252 and Microhip AN734,735 apnotes and also watched several videos on Youtube. )

It is quite fascinating that almost everything, (especially Youtube videos) I've seen is almost always the same old story, almost all info I googled assumes a mcu is talking to an EEPROM, very little info out there shows interfacing MCU<-->MCU in C code(..and I don't do assembly.)

Many thanks for posting a scope pattern I've seen over and over again, except yet on my scope.
« Last Edit: September 12, 2022, 01:59:06 am by Salome2 »
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6926
  • Country: es
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #5 on: September 12, 2022, 02:57:02 am »
You want help but you're still missing all the slave i2c
code...can't help more with so little details.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: Salome2

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #6 on: September 12, 2022, 09:23:30 am »
Thanks DavidAlfa for your kind help! Below is my Slave mcu code.
I didn't think it was time to post the mcu Slave code when the Master sends leading extra bit prob was not resolved.


void i2c_Setup()  //MSSP Module as Slave
{
        Addr1=0x20;  //first Slave
        Addr2=0x40;
        TRISC3=1;TRISC4=1;//Clk and Data TRIS'd as inputs Slave or Master mode
        SSPADD=Addr1<<1;//FirstSlave Addr1=0x20   (I  have also tried SSPADD=Addr1; with still no acknowledge.)
                         
        SSPSTATbits.SMP=1; //1=slew rate disabled, won't work without SMP set
        SSPCON1=0x26;  //7-bit I2C Slave mode Enabled with no IRQs Enab for Start/Pen events
        SSt=Begin;
        SSPIF=0;
}

void interrupt high_priority hp(void)  //Note: this code has minimized/modified just to see if any I2C address match event
{
 if(SSt==Begin)
  { if(SSPIF)
     { LATC5=1;LATC5=0;LATC5=1;LATC5=0;  //blips to watch on scope to detect if a SSPIF occurs(Unfortunately not yet blipped!)
       i2c_ack();
     }
    if(BF)
     { LATC5=1;LATC5=1;LATC5=1;LATC5=1;LATC5=1;LATC5=1;LATC5=0;
     
       Rx[0]=SSPBUF;
       if(Rx[0]==0x20)
        { LATC5=0;LATC5=0;LATC5=0;LATC5=0;
          LATC5=1;LATC5=1;LATC5=0;LATC5=1;LATC5=1;
          LATC5=0;
          i2c_ack();
        }
     }
  }

/*  This code is not ready for prime time until slave address issue is resolved

    if(SSt==Begin)
     { if(BF!=1)
        { SSPIF=0;
          CKP=1;
          goto Xiti2c;
        }

       if(BF)i2c_ack();

       qq=SSPBUF; //address match qq=Address
       if(qq & 1) //OK to start sending data to MAS
        { SSt=Ready2Send;
          bn=1;
          Try2Send=0;
          CKP=0;
        }
     }
    else if(SSt==Ready2Send)
     {
R2Send:
      if(BF==0)
       {
         Sends++;
         if(bn<70)
          {
            Try2Send=0;
            Sends++;
            SSPBUF=Tx[bn];
            SSPIF=0;
            CKP=1;
          }
         else
          { SSt=Begin;
            CKP=1;
            SSPIF=0;
            i2c_stop();
          }
         goto Xiti2c;
       }
      else
       {
         Try2Send++;
         if(Try2Send<3)
          {
            goto R2Send;
          }
         else
          { goto badxit;
          } 
       }
     }
    else
     {
badxit:
       Senderr++;
       SSPOV=0;
       WCOL=0;
       SSPIF=0;
       CKP=1;
       SSt=Begin;
     }
*/
void waitmssp()
{
        while(!SSPIF);
   SSPIF=0;
}
void i2c_ack()
{
   ACKDT=0;
        ACKEN=1;
   waitmssp();
}

void i2c_nak()
{
   ACKDT=1;
   ACKEN=1;
   waitmssp();
}
« Last Edit: September 12, 2022, 09:35:58 am by Salome2 »
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6926
  • Country: es
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #7 on: September 12, 2022, 01:54:49 pm »
Definitely the logic levels in your picture are wrong for i2c, so first you must find the reason of why SDA/SCL are low!
(Seems like you are sending start/data but never a stop, so SDA is never released)
Each I2C transfer is 8+1 clocks, not any other size. At the end of each byte there's a 9th clock pulse for the ACK/NAK bit, so you will always see 9 clocks.
From the master point of view, there's no diifference between 7 or 10-bit addressing, it simply sends raw bytes.

Better to configure the i2c peripheral with SSPEN off, setting it afterwards, otherwise you might confuse the hardware.

Try this very simple code in your master, with nothing connected to it:
Code: [Select]
// Some debugging leds
#define LED_TIMEOUT   LATC1
#define LED_COLLISION LATC2
#define LED_ERR_START LATC3
#define LED_ERR_DATA  LATC4
#define LED_ERR_STOP  LATC5

bool i2c_error;

void i2c_init(void){
    LED_TIMEOUT   = 0;
    LED_COLLISION = 0;
    LED_TIMEOUT   = 0;
    LED_ERR_START = 0;
    LED_ERR_DATA  = 0;
    LED_ERR_STOP  = 0;
    i2c_error     = 0;
    SSPCON1       = 0x08;
    SSPCON2       = 0;
    SSPCON3       = 0;
    SSPSTAT       = 0;
    SSPADD        = 0x63;    // For 100KHz
    //SSPADD      = 0x18;    // For 400KHz
    SSPEN         = 1;       // Enable MSSP
}

bool i2c_poll(void){
    uint16_t timeout = 1000;
    while(!SSPIF){   
        if(BCLIF){              // Write collision detected, debug/do something
            BCLIF=0;
            LED_COLLISION = 1;
            i2c_error = true;
            break;
        }       
        if(!--timeout){         // Timeout occurred, debug/do something
            LED_TIMEOUT = 1;
            i2c_error = true;
            break;
        }
    }
    SSPIF=0;
    return i2c_error;
}

void i2c_test(void){
    SEN = 1;            // Initiate Start
    if( i2c_poll() ){
        LED_ERR_START = 1;
        return;
    }
    SSPBUF = 0x55;    // Send 0x55
    if( i2c_poll() ){
        LED_ERR_DATA  = 1;
        return;
    }
    PEN=1;            // Initiate Stop
    if ( i2c_poll() ){
        LED_ERR_STOP  = 1;
        return;
    }
}

void main(void){
    // system init, etc
 
    i2c_init();
    while(1){
        i2c_test();
        if(i2c_error){
            // Compiler complaining on large delay values, split in a loop
            // Wait 5 seconds to show the leds
            for(uint8_t wait=5; wait; wait--){
                __delay_ms(1000);
            }
            i2c_init();
        }
        else{
          __delay_ms(1);
        }
  }
}



I tested it with a 18F23K22, you should see exactly this, and no errors.

« Last Edit: September 12, 2022, 02:42:10 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #8 on: September 19, 2022, 09:55:12 pm »
Now, after discovering that I had overlooked some details in my Fosc initialization. My bad to not set INTOSC to 16MHz and enable PLLEN and then discovering my delay ISR using TMR0 was counting the wrong number of Instr Clks,

In converting my code to the 64MHz 18F25K22, I had forgot to I didn't update TMR0 settings, still set for a 18F252 at 40MHz Fosc.

The problem initially was that I couldn't get rid of an extra start bit glitch. After so much time I finally realized the PIC18F452 MSSP does not do I2C correctly. SEN doesn't work!  I spent a quite a few days finding no cure for the incurable extra bit.

Oh My! Quite a few other errors!

I2C now that Ack acts fine.
« Last Edit: September 20, 2022, 02:30:37 am by Salome2 »
 

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 3372
  • Country: au
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #9 on: September 20, 2022, 02:16:39 am »
What I do see on the scope is the exactly the same with or without any Slave PIC inserted.
Any ideas?

Did you try a simple i2c slave part like an EEPROM, to verify your master code is ok.

i2c slaves can be tricky to get working, the ones I've worked with need a careful phasing of SW and hardware.
I assigned pins to tag START seen, and then Address Match and then Send ACK states.

I read about one MCU that did i2c slave like a dual port memory, so the slave needed zero SW help. What a great idea ! :)

 

Offline Salome2Topic starter

  • Regular Contributor
  • *
  • Posts: 78
  • Country: se
Re: Does size matter? 10-bits is a bit too much for i2c
« Reply #10 on: September 20, 2022, 02:50:39 am »
Thanks, PCB.Wiz!  I was really thrown off by trying to get things to work with a buggy chip (18F452)  that undoubtedly has a serious bug with i2c SEN!
Worse, I didn't find this bug listed in the 18Fx52 Errata!

I had to convert my code after changing my mcu's to 18F25K22.

After some hours I finally succeeded in finding some other coding errors.
I had initialization omissions for Fosc  and my TMR0 was way off in creating delays. I didn't realize that until finally, using a blip bit trace to debug, it showed that I was actually running the 18F25k22 chips at 4MHz. The default setting settings set INTOSC=4MHz and PLL was not enabled.  Because I had a client 1/2 sec warmup delay that was way too long, my i2c test code was delaying the client to start until way after the host 18F25K22 sent out the SEN Address Write and the client missed this event.
Finally, I discovered that I had to set SSPADD to 0x20 using SSPAD=Addr1<<1 in the i2c client.
« Last Edit: September 20, 2022, 03:04:17 am by Salome2 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->