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.
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.
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
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?
// 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?
// 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
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
The recive of 8 data bits works only when START + STOP in one command. It is correct?
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?
**Attention** This is a public forum