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.

MSP430FR2433: MSP430FR2433 - I2C (DS1621 )

Part Number: MSP430FR2433

Hi, I'm trying to read the DS1621 temperature sensor on I2C using MSP430FR2433.

Batch execution of reading lines of code causes the I2C bus to “hang” and the ACK confirmation bit is not generated !!!

bis.w   #UCTXSTT, &UCB0CTLW0   ; I2C START+ADDRESS
mov.w #0x00AA, UCB0TXBUF         ; Command DS1621 (Read Temperature)
bis.w   #UCTXSTP, &UCB0CTLW0   ; I2C STOP

If I have a program in steps, then the I2C bus works!


There is a “partially” write cycle of the I2C bus in 2 stages

bis.w #UCTXSTT, &UCB0CTLW0 ; I2C START+ADDRESS
mov.w #0x00AA, UCB0TXBUF ; Command DS1621 (Read Temperature)

bis.w #UCTXSTP, &UCB0CTLW0 ; I2C STOP

or

bis.w #UCTXSTT, &UCB0CTLW0 ; I2C START+ADDRESS

mov.w #0x00AA, UCB0TXBUF ; Command DS1621 (Read Temperature)
bis.w #UCTXSTP, &UCB0CTLW0 ; I2C STOP

then after START + ADDRESS, ACK + TX_DATA appears in 50ms intervals regardless of baudrate.

Cycle recording of several bytes on the I2C bus is not possible with a partial step by step debugging in 2 stages.

bis.w #UCTXSTT, &UCB0CTLW0 ; START+ADDRESS

mov.w #0x00AA, UCB0TXBUF ; ACK+Command DS1621 (Read Temperature)
mov.w #0x00EE, UCB0TXBUF ; ACK+Command DS1621 (Initiates temperature conversion)
mov.w #0x0022, UCB0TXBUF ; ACK+Command DS1621 (Halts temperature conversion)
mov.w #0x00AA, UCB0TXBUF ; ACK+Command DS1621 (Read Temperature)
bis.w #UCTXSTP, &UCB0CTLW0 ; ACK+STOP

or

bis.w #UCTXSTT, &UCB0CTLW0 ; I2C START+ADDRESS
mov.w #0x00AA, UCB0TXBUF ; ACK+Command DS1621 (Read Temperature)
mov.w #0x00EE, UCB0TXBUF ; ACK+Command DS1621 (Initiates temperature conversion)
mov.w #0x0022, UCB0TXBUF ; ACK+Command DS1621 (Halts temperature conversion)
mov.w #0x00AA, UCB0TXBUF ; ACK+Command DS1621 (Read Temperature)

bis.w #UCTXSTP, &UCB0CTLW0 ; ACK+STOP

only ACK + 1 byte of data + is transmitted with the same interval of 50 ms appears on the NACK + STOP bus

If you pre-set the data in the register UCB0TXBUF and then in one command to set the bits START + STOP

mov.w #0x00AA, UCB0TXBUF ; Command DS1621 (Read Temperature)
bis.w #UCTXSTT+UCTXSTP, &UCB0CTLW0 ; I2C START+ADDRESS

START + ADRESS + ACK + STOP appear on the bus I2C.

  1. Why MASTER does not generate ACK after transmitting every 8 bits of data as it is supposed by the I2C protocol and forms it before transmitting the next state (TX_DATA and STOP)?
  2. Why does the I2C automaton "hang" 50 ms?
  3. Why does the I2C automaton refuse to perform the bus cycle without step-by-step mode (Analysis of the UCBBUSY bit did not lead to the result)?
  4. How to transfer several data bytes in 1 write cycle in SLAVE?

Batch code execution causes only the first byte to be read!

bis.w #UCTXSTT, &UCB0CTLW0 ; I2C START+ADDRESS+RX_DATA
mov.w UCB0RXBUF, R7
bis.w #UCTXSTP, &UCB0CTLW0
mov.w UCB0RXBUF, R8 ; ACK+NACK+STOP

In the step-by-step execution of the

bis.w #UCTXSTT, & UCB0CTLW0

command in the debugger, it calls START + ADDRES + ACK + RX_DATA (16bit), while the UCB0RXBUF register (slau445h.pdf page 655) accepts only 8 low bits!

Read register UCB0RXBUF causes ACK + RX_DATA (8 bits) on the bus

mov.w UCB0RXBUF, R7

Read register command UCB0RXBUF when the #UCTXSTP bit is set causes ACK + NACK + STOP

bis.w #UCTXSTP, & UCB0CTLW0
mov.w UCB0RXBUF, R7                          ; ACK + NACK + STOP

Running

bis.w # UCTXSTT + UCTXSTP, & UCB0CTLW0

causes a read cycle of 8 data bits START + ADDRESS + ACK + RX_DATA + NACK + STOP

How to read a few bytes of data?


IAR WorkBench ASM code:

;-------------------------------------------------------------------------------

; CPU: MSP430FR2433IRGER

;-------------------------------------------------------------------------------

; I2C adress:

; #090h - DS1621     (W)

; #091h - DS1621     (R)

; UCB0I2CSA = #048h

;-------------------------------------------------------------------------------

#include "msp430.h"                     ; #define controlled include file

           RSEG   CSTACK                 ; Define stack segment

           RSEG   CODE

;-------------------------------------------------------------------------------

RESET       mov.w   #SFE(CSTACK),SP             ; Initialize stackpointer

StopWDT     mov.w   #WDTPW+WDTHOLD,&WDTCTL     ; Stop watchdog timer

 

// Configure GPIO

           BIS.b #BIT2+BIT3,P1SEL0           ; I2C pins

           BIC.b #BIT2+BIT3,&P1DIR

           bic.w   #LOCKLPM5,PM5CTL0           ; Unlock I/O pins

// Configure USCI_B0 for I2C mode

           bis.w   #UCSWRST, &UCB0CTLW0

           bis.w   #UCMST,   &UCB0CTLW0       ; I2C Master mode

           bis.w   #UCMODE_3, &UCB0CTLW0       ; eUSCI_B mode = I2C

           mov.w   #0x0100,   UCB0BRW         ; baudrate = SMCLK / 100

           bic.w   #UCSWRST, &UCB0CTLW0       ;

 

wait1       bit.w #UCBBUSY,&UCB0STATW         ; wait until I2C module has finished all operations

           JC     wait1

          

// WIRITE I2C          

           mov.w   #0x0048,   UCB0I2CSA               ; I2C slave address = DS1621

           bis.w   #UCTR,     &UCB0CTLW0               ; I2C=TX

 

           bis.w   #UCTXSTT, &UCB0CTLW0       ; START+ADDRESS

           mov.w   #0x00AA,   UCB0TXBUF       ; ACK+Command DS1621 (Read Temperature)

           mov.w   #0x00EE,   UCB0TXBUF       ; ACK+Command DS1621 (Initiates temperature conversion)

// Pause

           nop

// ----

  mov.w   #0x0022,   UCB0TXBUF       ; ACK+Command DS1621 (Halts temperature conversion)

           mov.w   #0x00AA,   UCB0TXBUF       ; ACK+Command DS1621 (Read Temperature)

           bis.w   #UCTXSTP, &UCB0CTLW0       ; ACK+STOP

 

// READ I2C

           bic.w   #UCTR,     &UCB0CTLW0       ; I2C=RX

 

           bis.w   #UCTXSTT+UCTXSTP, &UCB0CTLW0       ;START+ADDRESS+RX_DATA

           mov.w   UCB0RXBUF, R7

 

           bis.w   #UCTXSTT, &UCB0CTLW0       ; I2C START+ADDRESS+RX_DATA

           mov.w   UCB0RXBUF, R7

           bis.w   #UCTXSTP, &UCB0CTLW0      

           mov.w   UCB0RXBUF, R8                   ; ACK+NACK+STOP

 

           JMP $                               ; jump to current location '$'

                                           ; (endless loop)

 

;-------------------------------------------------------------------------------

           COMMON INTVEC                 ; Interrupt Vectors

;-------------------------------------------------------------------------------

           ORG     RESET_VECTOR           ; Reset Vector

           DW     RESET

           END

  • > bis.w #UCTXSTT, &UCB0CTLW0 ; START+ADDRESS
    > mov.w #0x00AA, UCB0TXBUF ; ACK+Command DS1621 (Read Temperature)
    > mov.w #0x00EE, UCB0TXBUF ; ACK+Command DS1621 (Initiates temperature conversion)

    You need to wait for UCB0IFG:UCTXIFG to go high before writing to UCB0TXBUF. Doing it earlier causes the byte to be discarded. [Ref User Guide (SLAU445H) Fig 24-12.] Then when the SLA byte is complete, the MSP430 holds SCL low waiting for you to load the TXBUF.

    I don't see any assembly examples for I2C, but you need the effect of "while((UCB0IFG&UCTXIFG) == 0)/*EMPTY*/;"
  • Thanks!

    Working ASM code samples are written to the I2C bus:

    Sample 1 -Transfer 1 bytes to I2C bus (No automatic STOP generation) -----------------------------------------------------------------------------------------

      // Configure GPIO
            BIS.b #BIT2+BIT3,P1SEL0                      ; I2C pins
           BIC.b #BIT2+BIT3,&P1DIR
           bic.w #LOCKLPM5,PM5CTL0                  ; Unlock I/O pins

    // Configure USCI_B0 for I2C mode 
           bis.w #UCSWRST, &UCB0CTLW0
           bis.w #UCMST, &UCB0CTLW0                ; I2C Master mode
           bis.w #UCMODE_3, &UCB0CTLW0        ; eUSCI_B mode = I2C
           mov.w #0x0100, UCB0BRW                    ; baudrate = SMCLK / 100
           bis.w   #UCASTP_0, &UCB0CTLW1       ; 00 = No automatic STOP generation.
                                                                             ; The STOP condition is generated after the user sets the UCTXSTP bit.
                                                                             ; The value in UCBxTBCNT is a don't care.
           bic.w   #UCSWRST,  &UCB0CTLW0       ;

          bis.w #UCTXSTT, &UCB0CTLW0           ; I2C START+ I2C ADDRESS

    w1 bit.w #UCTXIFG0, &UCB0IFG
          jnc w1
          mov.w #0x00EE, UCB0TXBUF               ; I2C TX_DATA = EE

    w2 bit.w #UCTXIFG0, &UCB0IFG
          jnc w2
          bis.w #UCTXSTP, &UCB0CTLW0           ; I2C STOP

    Sample 2 - Transfer 3 bytes to I2C bus (No automatic STOP generation)-----------------------------------------------------------------------------------------

      // Configure GPIO
            BIS.b #BIT2+BIT3,P1SEL0                      ; I2C pins
           BIC.b #BIT2+BIT3,&P1DIR
           bic.w #LOCKLPM5,PM5CTL0                  ; Unlock I/O pins

    // Configure USCI_B0 for I2C mode 
           bis.w #UCSWRST, &UCB0CTLW0
           bis.w #UCMST, &UCB0CTLW0               ; I2C Master mode
           bis.w #UCMODE_3, &UCB0CTLW0        ; eUSCI_B mode = I2C
           mov.w #0x0100, UCB0BRW                    ; baudrate = SMCLK / 100
           bis.w   #UCASTP_0, &UCB0CTLW1       ; 00 = No automatic STOP generation.
                                                                             ; The STOP condition is generated after the user sets the UCTXSTP bit.
                                                                             ; The value in UCBxTBCNT is a don't care.
          bic.w   #UCSWRST,  &UCB0CTLW0       ;

          bis.w #UCTXSTT, &UCB0CTLW0             ; I2C START+ I2C ADDRESS

    w1 bit.w #UCTXIFG0, &UCB0IFG
          jnc w1
          mov.w #0x00EE, UCB0TXBUF                 ; I2C TX_DATA=EE

    w2 bit.w #UCTXIFG0, &UCB0IFG
          jnc w2
          mov.w #0x0022, UCB0TXBUF                 ; I2C TX_DATA=22

    w3 bit.w #UCTXIFG0, &UCB0IFG
          jnc w3
          mov.w #0x00AA, UCB0TXBUF                ; I2C TX_DATA=AA

    w4 bit.w #UCTXIFG0, &UCB0IFG
          jnc w4
          bis.w #UCTXSTP, &UCB0CTLW0            ; I2C STOP

    Sample 3 -Transfer 1 bytes to I2C bus (Automatic STOP generation) ----------------------------------------------------------------------------------------------

      // Configure GPIO
            BIS.b #BIT2+BIT3,P1SEL0                      ; I2C pins
           BIC.b #BIT2+BIT3,&P1DIR
           bic.w #LOCKLPM5,PM5CTL0                  ; Unlock I/O pins

    // Configure USCI_B0 for I2C mode 
           bis.w #UCSWRST, &UCB0CTLW0
           bis.w #UCMST, &UCB0CTLW0               ; I2C Master mode
           bis.w #UCMODE_3, &UCB0CTLW0       ; eUSCI_B mode = I2C
           mov.w #0x0100, UCB0BRW                    ; baudrate = SMCLK / 100
           bis.w   #UCASTP_2, &UCB0CTLW1       ; 02 = A STOP condition is generated automatically after the byte counter value reached UCBxTBCNT.
                                                                             ; UCBCNTIFG is set with the byte counter reaching the threshold.
          bic.w   #UCSWRST,  &UCB0CTLW0       

          mov.w #0x0001, UCB0TBCNT                 ; Tranfer 1Byte to I2C 

          bis.w #UCTXSTT, &UCB0CTLW0            ; I2C START+ I2C ADDRESS

    w1 bit.w #UCTXIFG0, &UCB0IFG
          jnc w1
          mov.w #0x00EE, UCB0TXBUF                ; I2C TX_DATA=EE + I2C AUTO STOP

    Sample 4 -Transfer 3 bytes to I2C bus (Automatic STOP generation) -----------------------------------------------------------------------------------------------

      // Configure GPIO
            BIS.b #BIT2+BIT3,P1SEL0                               ; I2C pins
           BIC.b #BIT2+BIT3,&P1DIR
           bic.w #LOCKLPM5,PM5CTL0                           ; Unlock I/O pins

    // Configure USCI_B0 for I2C mode 
           bis.w #UCSWRST, &UCB0CTLW0
           bis.w #UCMST, &UCB0CTLW0                ; I2C Master mode
           bis.w #UCMODE_3, &UCB0CTLW0        ; eUSCI_B mode = I2C
           mov.w #0x0100, UCB0BRW                    ; baudrate = SMCLK / 100
           bis.w   #UCASTP_2, &UCB0CTLW1       ; 02 = A STOP condition is generated automatically after the byte counter value reached UCBxTBCNT.
                                                                             ; UCBCNTIFG is set with the byte counter reaching the threshold.
          bic.w   #UCSWRST,  &UCB0CTLW0       

          mov.w #0x0003, UCB0TBCNT                 ; Tranfer 3 Byte to I2C 

          bis.w #UCTXSTT, &UCB0CTLW0            ; I2C START + I2C ADDRESS

    w1 bit.w #UCTXIFG0, &UCB0IFG
          jnc w1
          mov.w #0x00EE, UCB0TXBUF                ; I2C TX_DATA=EE

    w2 bit.w #UCTXIFG0, &UCB0IFG
          jnc w2
          mov.w #0x0022, UCB0TXBUF                 ; I2C TX_DATA=22

    w3 bit.w #UCTXIFG0, &UCB0IFG
          jnc w3
          mov.w #0x00AA, UCB0TXBUF                ; I2C TX_DATA=AA + I2C AUTO STOP

     ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Writing to the  I2C bus - OK! RESOLVED

     

    How to read the I2C bus?

  • Set UCTR=0 and then set UCTXSTT. Each time UCRXIFG goes high, fetch a byte from UCB0RXBUF. With STP=2 the device will issue the Stop for you after TBCNT bytes. (Incidentally, I don't see you setting UCTR=1 above, but the scope trace claims you did. Is something missing?)

    For e.g. the Read Temperature (0xAA) sequence above, instead of issuing the UCTXSTP, just set UCTR=0 and set UCTXSTT right then. This will get you a Repeated Start, which the DS1621 data sheet says is just fine.
  • Hi Bruce: Thanks for your support on this thread.
  • // READ I2C (2 BYTE)
           bic.w #UCTR, &UCB0CTLW0
           bis.w #UCTXSTT, &UCB0CTLW0

    rd1 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd1
          mov.w UCB0RXBUF, R7

    rd2 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd2
          mov.w UCB0RXBUF, R8

          bis.w #UCTXSTP, &UCB0CTLW0 ; I2C STOP

    // READ I2C (1 BYTE)
           bic.w #UCTR, &UCB0CTLW0
           bis.w #UCTXSTT, &UCB0CTLW0

    rd3 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd3
          mov.w UCB0RXBUF, R7

          bis.w #UCTXSTP, &UCB0CTLW0 ; I2C STOP

    Why are 9 additional SCL cycles inserted?
    How to get rid of them?

  • Short answer: Move the UCTXSTP setting up one line, to precede reading UCB0RXBUF.

    As soon as you read RXBUF, the I2C unit will proceed with fetching the next byte, including ACKing the byte you just read. So you need to set TXSTP before reading the RXBUF for the last byte. [Ref UG (SLAU445H) sec. 24.3.5.2.2, paragraph 6].

    The Example msp43fr231x_eusci_i2c_standard_master.c illustrates this, though it issues the stop even earlier. (I don't see this Example in the FR2433 Example suite, I don't know why.)
  • // READ I2C - 1 Byte
          bic.w #UCTR, &UCB0CTLW0           ; I2C=RX
          bis.w #UCTXSTT, &UCB0CTLW0     ; I2C START
    rd1 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd1
          bis.w #UCTXSTP, &UCB0CTLW0     ; I2C STOP
          mov.w UCB0RXBUF, R7


    R7 = 0019h and not 8019h (OK!)
    but UCB0RXBUF = 0080h!!!
    How to make sure that the second byte is not read?

    Sample 5 - Recive 2 bytes to I2C bus (No automatic STOP generation)-----------------------------------------------------------------------------------------

    Reading two bytes - works!

    // READ I2C - 2 Byte 
          bic.w   #UCTR,     &UCB0CTLW0        ; I2C=RX
          bis.w #UCTXSTT, &UCB0CTLW0       ; I2C START

    rd1 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd1
          bis.w #UCTXSTP, &UCB0CTLW0       ; I2C STOP
          mov.w UCB0RXBUF, R7
    rd2 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd2
          bis.w #UCTXSTP, &UCB0CTLW0       ; I2C STOP
          mov.w UCB0RXBUF, R8


    R7 = 0019h  R8 = 0080h

    Sample 6 - Recive 1 bytes to I2C bus (No automatic STOP generation)-----------------------------------------------------------------------------------------

    // READ I2C - 1 Byte
          bic.w #UCTR, &UCB0CTLW0                          ; I2C=RX
          bis.w #UCTXSTT+UCTXSTP, &UCB0CTLW0 ; I2C START+STOP
    rd1 bit.w #UCRXIFG0, &UCB0IFG
          jnc rd1
          mov.w UCB0RXBUF, R7


    R7=001Ah

     

    The recive of 8 data bits works only when START + STOP in one command. It is correct?

  • I don't know the answer. This doesn't appear to match the behavior described in that paragraph. (Maybe there's a footnote someplace.) I usually use TBCNT with UCASTP=2, so the hardware does all this for me.

    As a practical matter, reading the extra byte requests a little extra (unneeded) work from the sensor, but I don't see a case in the DS where it will cause incorrect results. You would not see 0119h (or 8019h) in RXBUF in any case, since the high bits there are always 0.
  • Thanks!
    I apologize. I made a typo. R7 = 8019h (Corrected my question above)

    As I understand, Receive data of 8-bit data only when START + STOP in one command.

    If STOP is not in the same command line, then the device reads 2 bytes!

    It is correct?

  • Are your posts changing while I'm not looking?

    Anyway, you now seem to have a solution.
  • What will Texas Instruments answer?

**Attention** This is a public forum