Jump to content
43oh

G2553 I2C SCL/INT combined?


Recommended Posts

Writing a small lib for an i2c ic.

I got it all working, but there's room for improvement and I can't seem to figure it out nor did I find anything similiar.

 

The chip has combined it's SCL with an INT, which triggers (INT = 0) when measurement is complete.

I have currently worked around this with a 1000 cycle delay at 8Mhz.

Preferably I would like to enter LPMx in between ofcourse, could (ab)use a timer, but the interrupt seems the cleanest solution.

 

So the question is howto capture this interrupt signal?

I'm using the i2c code from TI with the exception that SDA = P1.7, SCL = P1.6

Furthermore SCL/SDA are pulled high with 1.2kOhm resistors.

 

I've tried polling at various i2c related registers during the 1000 cycles delay (IFG2, UCB0STAT, UCB0I2CIE, IE2) for a flag, but cannot see anything happening.

I was hoping UCSCLLOW could be a solution. SCL is more just an output signal I guess.

I've also tried to swith to GPIO type interrupt and monitor P1IFG & BIT6 without any luck, I tried various settings maybe I missed something?

Maybe I need a different approach in my hardware?

Maybe there are other chips that work this way and someone else figured this out?

 

Any help greatly appreciated :o

Be happy to post more info or code if that helps.

Link to post
Share on other sites

UCSCLLOW should reflect SCL status if I read the documentation correctly, maybe you have a timing problem? I would think the interrupt generated by the chip in question would be a pulse of some duration to allow the I2C bus to resume normal operation without code intervention. The SCL pin is open drain so can act as an input and output at the same time, it is the reason a pullup is required for correct operation. Its default state is logical high, but can be driven low by both the master and slaves...

Link to post
Share on other sites

In more detail, now that I looked at the MSP430G2553 datasheet:

 

To use I2C, the TI library will set bit 5 and 6 in P1SEL and P1SEL2 to connect these pins with the USCB0 peripheral. See table 19.

 

Looking at the schematic on the previous page, P1SEL and P1SEL2 are connected through an OR gate to the active low enable pin of the interrupt logic. I.e. if one of the two is high, there will be no interrupts.

post-9974-0-24356200-1467405528_thumb.png

 

You could manually clear bit 6 in P1SEL and P1SEL2 when you are waiting for the INT signal, and set them again before start using I2C.

Link to post
Share on other sites

@@fatihinanc

Out of the millions of chips out there, you guessed correctly!

Working on the same? Did you figure it out...

 

@@chicken,

i2c just uses P1.6 and P1.7 I believe?

void i2c_init(unsigned char addr, unsigned char prescale){
    //P1.6 SCL / P1.7 SDA
    P1SEL  |= BIT6 | BIT7;
    P1SEL2 |= BIT6 | BIT7;
    
    //...
}

Isn't P1.5 just used for SPI?

I will try your suggestion. Think the whole thing stranded when I do that.

 

As a general note I'm trying to see the Interrupt on my little DSO202 oscilloscope, but not really getting around with that thing.

Maybe the problem is that the pin is pulled high with 1.2kOhm resistor?

 

Will return with more findings, thanks for thinking with me :-)

 

EDIT:

 

I got it working, due to your hints/ideas.

For future reference this is quite simply it...

void main(void){

   //setup...

   for(;{
        //issue i2c command...

        //P1.6 SCL disable
        P1SEL  &= ~BIT6;
        P1SEL2 &= ~BIT6;

        P1IE   |=  BIT6;                            // interrupt
        P1IES  |=  BIT6;                            // falling edge (default)
        P1IFG  &= ~BIT6;                            // flag clear

        __bis_SR_register(LPM4_bits);               // sleep
        //-----------------------------------------------------------/
        P1IE   &= ~BIT6;                            // !interrupt

        //P1.6 SCL re-enable
        P1SEL  |= BIT6;
        P1SEL2 |= BIT6;
        
        //read i2c data
   }
}
#pragma vector=PORT1_VECTOR
__interrupt void ISR_P1(void){
    if(P1IFG & BIT6){
        P1IFG &= ~BIT6;                             // clear flag
        __bic_SR_register_on_exit(LPM4_bits);       // clear LPM bits, returns to main after last LPMx 
    }
}

Thanks again!

 

Now to make sense of the data :huh:

Link to post
Share on other sites

@@fatihinanc

eUSCI, what mcu are you on exactly?

Could be handy for the future.

 

And what scope is that? digital only one?

 

 

Furthermore

I don't see your "Calculation of the magnetic flux" as described in the User manual chapter 3, page 9?

 

This is what I got for that:

signed int TLV493D_flux12Bit(unsigned int r){
    signed int c = 0;
                                      //bit value
    c -= (r & 0x0800) ? 0x0800 : 0;   //12 ~ 2048
    c += (r & 0x0400) ? 0x0400 : 0;   //11 ~ 1024
    c += (r & 0x0200) ? 0x0200 : 0;   //10 ~  512
    c += (r & 0x0100) ? 0x0100 : 0;   // 9 ~  256
    c += (r & 0x0080) ? 0x0080 : 0;   // 8 ~  128
    c += (r & 0x0040) ? 0x0040 : 0;   // 7 ~   64
    c += (r & 0x0020) ? 0x0020 : 0;   // 6 ~   32
    c += (r & 0x0010) ? 0x0010 : 0;   // 5 ~   16
    c += (r & 0x0008) ? 0x0008 : 0;   // 4 ~    8
    c += (r & 0x0004) ? 0x0004 : 0;   // 3 ~    4
    c += (r & 0x0002) ? 0x0002 : 0;   // 2 ~    2
    c += (r & 0x0001) ? 0x0001 : 0;   // 1 ~    1
    return c;
}
signed int TLV493D_flux8Bit(unsigned int r){
    signed int c = 0;
                                      //bit value
    c -= (r & 0x0800) ? 0x80 : 0;     //12 ~  128
    c += (r & 0x0400) ? 0x40 : 0;     //11 ~   64
    c += (r & 0x0200) ? 0x20 : 0;     //10 ~   32
    c += (r & 0x0100) ? 0x10 : 0;     // 9 ~   16
    c += (r & 0x0080) ? 0x08 : 0;     // 8 ~    8
    c += (r & 0x0040) ? 0x04 : 0;     // 7 ~    4
    c += (r & 0x0020) ? 0x02 : 0;     // 6 ~    2
    c += (r & 0x0010) ? 0x01 : 0;     // 5 ~    1
    return c;
}

unsigned int  x=0, y=0, z=0;

        //later in loop....

        x = (r[0] << 4) | ((r[4] >> 4) & 0x0F);         // byte 0 + high nibble 4
        y = (r[1] << 4) | (r[4] & 0x0F);                // byte 1 + low nibble 4
        z = (r[2] << 4) | (r[5] & 0x0F);                // byte 2 + low nibble 5

        printf("FRM: %d \n\r", ((r[3] & 0x0C) >> 2));   // frame count
        printf("CH:  %d \n\r",  (r[3] & 0x03));         // channel 0=none or x, 1=y, 2=z, 3=temp
        printf("PD:  %d \n\r", ((r[5] & 0x10) >> 4));   // power down
        printf("x: %d / %d \n\r", TLV493D_flux12Bit(x), TLV493D_flux8Bit(x));
        printf("y: %d / %d \n\r", TLV493D_flux12Bit(y), TLV493D_flux8Bit(y));
        printf("z: %d / %d \n\r", TLV493D_flux12Bit(z), TLV493D_flux8Bit(z));

FRM should increment 0,1,2,3, 0, etc.

CH should be zero meaning measurement is finalized.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...