This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430Fx5xx I2c EEPROM random readi

I

the below code is not working for me - 

  UCB1CTL1 |= UCTR;
I2CStart();
SendByte(0x00);
SendByte(0xff);
SendByte(0xAf);
I2CStop();
__delay_cycles(1000);
I2CStart();
SendByte(0x00);
SendByte(0xff);
UCB1CTL1 &= ~UCTR;
I2CStart();
while (!(UCB1IFG&UCRXIFG)); //this loop is not ending
UCB1IFG &= ~UCRXIFG;
rxbuff[0] = UCB1RXBUF;

while this code below is working - 

  UCB1CTL1 |= UCTR;
I2CStart();
SendByte(0x00);
SendByte(0xff);
SendByte(0xAf);
I2CStop();
__delay_cycles(1000);
I2CStart();
SendByte(0x00);
SendByte(0xff);
 I2CStop();
  UCB1CTL1 &= ~UCTR; 
I2CStart();
while (!(UCB1IFG&UCRXIFG));
UCB1IFG &= ~UCRXIFG;
rxbuff[0] = UCB1RXBUF;

those are the func for both codes - 

void I2CStart(void)
{
UCB1CTL1 |= UCTXSTT; // I2C TX, start condition
}

void I2CStop(void)
{
UCB1CTL1 |= UCTXSTP; // I2C TX, stop condition
}

void SendByte(unsigned char Sbyte)
{
UCB1TXBUF= Sbyte;
while(!(UCB1IFG&UCTXIFG));
UCB1IFG &= ~UCTXIFG;
while(UCB1CTL1&UCTXSTT);
__delay_cycles(500);
}

my qustion is, how can i do a random read with a dummy write and restart condition for reading and without the stop condition part

Thanks,

Oz

  • Simply omit the stop. A start without previous stop is called a repeated start and perfectly valid.
    It is also valid to change UCTR even if no stop was sent. However, you should pass a direciton parameter to your IcCStart function, to make it moreflexible.

    However, your SendByte is not the msot efficient implementation.
    1) If you writ eto TXBUF and waited for TXIFG to be set again, this means the first byte has started to send. Which also means that TXSTT must be clear. However, if UXCTIFG doesn't come up again, it may mean that the slave didn't answer and UCNSACKIFG is set. In this case your cod eiwll wait forever for UCTXIFG.
    The delay is superfluous too. The TXIFG bit does the syncing. And is baudrate.independent. Also, you waste some time by doing things this way.
    Better wait for UCTXIFG first (and bail out if UCNACKIFG is set while waiting for UCTXIFG, as it means that the slave didn't answer and TXIFG will never be set), then write to TXBUF and return. Now you have plenty of time to prepare the next byte. YOu should return a status to tell the calling function that a NACK was received.

  • Hi Jens

    Thanks for the answer and the remarks.

    The main problom that i am not able to do random read to my device without the stop condition. 

    I am trying to do the random read with the repeated start but my code is wating forever at the the -  while (!(UCB1IFG&UCRXIFG)); 

    any idea?

    those are 2 more func - 

    void SetAddress(unsigned char Address)
    {
    UCB1I2CSA = Address;
    }

    void InitI2C(unsigned char Address)
    {
    P6OUT &= ~BIT0;
    P6DIR |= BIT0;
    P4SEL |= (BIT1|BIT2) ; // Assign I2C pins to USCI_B1
    UCB1CTL1 |= UCSWRST; // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB1CTL1 = UCSSEL__SMCLK + UCSWRST; // Use SMCLK, keep SW reset
    UCB1BR0 = 7; // fSCL = SMCLK/12 = ~100kHz
    UCB1BR1 = 0;
    SetAddress(Address);
    UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    //UCB1IE |= UCTXIE; // Enable TX interrupt
    }

    Thanks

  • oz zoaretz said:
    The main problom that i am not able to do random read to my device without the stop condition. 
    I am trying to do the random read with the repeated start but my code is wating forever at the the -  while (!(UCB1IFG&UCRXIFG)); 


    Then you're missing something.

    You should take a look at the nice diagram in the users guide. It tells oyue when flags are set or when you can set UCTXSTT etc.
    You must align your wait loops to this diagram.

    P.s.: don' tuse function calls for simple assignments. It's a waste of time, since a function call needs a call instruction, a return instruction and interferes with compiler code optimization, wasting time. It isn't important here since I2C is slow anyway, but as a general rule you should avoid trivial functions.

    You can do something like this instead if you don't want the assignemnts in your code:

    #define SetAddress(x) UCBI2CSA = (x)

    It looks like a funciton, but is compiled as a direct instruction.

  • Hi

    Thanks for the remarks, i changed my while's and my NACK checking.

    the repeted starts is working, BUT only when I am puting deleays at this part (after sending the dummy writing address):

      UCB1CTL1 &= ~UCTR;      //Recive mode
    __delay_cycles(100);
    UCB1CTL1 |= UCTXSTT; //Repeated start cond
    
    
    this is the all code for writing 64bytes and then read them:
    
    
      char rxbuff[300];
    char byte1,byte2,byte3;
    char i;
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    Init5528UCS();
    for (i=1;i<255;i++)
    rxbuff[i]=5;

    InitI2C(0x50);
    UCB1CTL1 |= UCTR; //Transmited mode
    UCB1CTL1 |= UCTXSTT; //Start cond
    char gotAddr=1;

    while(gotAddr){ //Sending the page address 2 byte address
    gotAddr=0;
    if(!(SendByte(0x01))) gotAddr=1;
    else if(!(SendByte(0x00)) ) gotAddr=1;
    }

    for (i=1;i<65;i++) //Writing 64 bytes
    while(!(SendByte(i)));
    if(UCB1IFG&UCNACKIFG); //Cheking NACK


    UCB1CTL1 |= UCTXSTP; //Stop
    while(UCB1IFG&UCSTPIFG); //Stop flag

    UCB1CTL1 |= UCTXSTT; //Start dummy write to random address

    gotAddr=1;
    while(gotAddr){ //Sending the page 2 byte random read address
    gotAddr=0;
    if(!(SendByte(0x01))) gotAddr=1;
    else if(!(SendByte(0x00)) ) gotAddr=1;
    }

    UCB1CTL1 &= ~UCTR; //Recive mode
    __delay_cycles(100);
    UCB1CTL1 |= UCTXSTT; //Repeated start cond
    while(UCB1IFG&UCNACKIFG)
    UCB1CTL1 |= UCTXSTT; //Start cond

    for (i=0;i<64;i++){
    while (!(UCB1IFG&UCRXIFG) && !(UCB1IFG&UCNACKIFG)); //Reciving 64 data bytes
    if(UCB1IFG&UCNACKIFG){ //Bad reciving
    UCB1CTL1 |= UCTXSTT; //Repeated start cond
    i--;
    }
    else
    rxbuff[i] = UCB1RXBUF;
    }
    UCB1IFG |= UCNACKIFG; //Sending NACK
    UCB1CTL1 |= UCTXSTP;
    rxbuff[i] = UCB1RXBUF;
    
    
    
    
    char SendByte(unsigned char Sbyte)
    {
    while(!(UCB1IFG&UCTXIFG) && !(UCB1IFG&UCNACKIFG));
    if( UCB1IFG&UCNACKIFG )
    {
    UCB1CTL1 |= UCTXSTT;
    while(UCB1IFG&UCNACKIFG)
    UCB1CTL1 |= UCTXSTT;
    return 0;
    }
    else UCB1TXBUF= Sbyte;
    return 1;
    }
    
    
    void InitI2C(unsigned char Address)
    {
    P6OUT &= ~BIT0;
    P6DIR |= BIT0;
    P4SEL |= (BIT1|BIT2) ; // Assign I2C pins to USCI_B1
    UCB1CTL1 |= UCSWRST; // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB1CTL1 = UCSSEL__SMCLK + UCSWRST; // Use SMCLK, keep SW reset
    UCB1BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB1BR1 = 0;
    SetAddress(Address);
    UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    //UCB1IE |= UCTXIE; // Enable TX interrupt
    }
    
    
    do you have any idea Y it's working only with the  "__delay_cycles(100);"
    without the  __delay_cycles(100) i am getting only "FF" at my array.
    
    
    
    
    Thanks again
    Oz
  • oz zoaretz said:
    do you have any idea Y it's working only with the  "__delay_cycles(100);"

    Yes. Your SendByte (which is actually more than SendByte - it is a 'start until slave answers, then send one byte' function) immediately exits after stuffing teh data byte into TXBUF.

    If you now clear UCTR and immediately set the UCSTP, the stop condition will be initialted before sending the byte has even started. Remember, the UCSTT bit is cleared during the ACK cycle of the address. THen the USCI waits with finishing the ACK cycle until you write to TXBUF. And then the ACK cycle is finished. If you set UCSTP before the sending of the next byte has begun, the content of TXBUF is discarded and the STP immediately happens.
    A delay of 100 cycles is not necessary, but waiting for UCTXIFG is required before setting UCSTP. Coincidentally, in your setup, 100 cycles are same or larger than the time it takes to start sending the byte (and setting TXIFG).

    However, your waiting cycle is wrong:

    oz zoaretz said:
    while(!(UCB1IFG&UCTXIFG) && !(UCB1IFG&UCNACKIFG));
    if( UCB1IFG&UCNACKIFG )
    {
    UCB1CTL1 |= UCTXSTT;
    while(UCB1IFG&UCNACKIFG)
    UCB1CTL1 |= UCTXSTT;
    return 0;
    }

    You try a repeated start if you got NACKIFG. Which clears NACKIFG and won't set it again until the address has been set. So the while loop will never be executed and the function immediately returns with 0. Which most likely isn't what you want.

  • it's working, Thanks!!!

**Attention** This is a public forum