Skip to main content
Graduate
March 5, 2024
Question

Question about I2C TXIS bit in stm32g071rb

  • March 5, 2024
  • 5 replies
  • 3705 views

Hello, 

I'm studing I2C on stm32g071rb and I have a question about it.

In the datasheet there is this line: "In the case of a write transfer, the TXIS flag is set after each byte transmission, after the 9th SCL pulse when an ACK is received", but for the last byte TXIS remain LOW and TC become HIGH.

It's correct that for the last byte that I have to send via I2C, the TXIS bit remain LOW?

For example if I have to send(master to slave): 0x00, 0x01, 0x02

I set the CR2_NBYTES bit (3 << I2C_CR2_NBYTES_Pos)...etc

But after send the 0x02 byte, only TC is HIGH...so also the TXIS bit should be HIGH in this case?

Thanks

 

Simeon

    This topic has been closed for replies.

    5 replies

    Super User
    March 5, 2024

    > I set the CR2_NBYTES bit (3 << I2C_CR2_NBYTES_Pos)...etc

    What is "etc"? Details do matter, so post code and observed waveforms.

    JW

     

    PS. For your reference, an example, manually walked through in debugger, here - the first example is the correct/expected behaviour of the I2C registers/flags for given peripheral (SHT31).

    dmrsimAuthor
    Graduate
    March 6, 2024

    Hello, at the moment I have a problem with my oscilloscope and I have to fix it...
    My code(sorry for code quality but  at the moment is only a test), I followed the datasheet flowchart(image in attach).
    Do you think that I make some mistakes?
    The slave seems to send an ACK at the moment.
    I have 2 questions:

    1) Sometimes at the end of the transmission, the TC bit remain low but I notices that if I put some delay before the TC check it work(as if I had to wait a certain time first, but in the flowchat I don't see this)

    2) It's correct that for the last byte TXIS remain low?


    Thanks a lot!

    Simeon

     

     

    void i2c_enable()
    {
    	RCC->IOPENR |= RCC_IOPENR_GPIOBEN_Msk;
    	RCC->APBENR1 |= RCC_APBSMENR1_I2C1SMEN_Msk;
    
    	GPIOB->MODER &= ~(GPIO_MODER_MODE8_Msk | GPIO_MODER_MODE9_Msk);
    	GPIOB->MODER |= (GPIO_MODER_MODE8_1 | GPIO_MODER_MODE9_1);
    
    	GPIOB->OSPEEDR |= (GPIO_OSPEEDR_OSPEED8_1 | GPIO_OSPEEDR_OSPEED9_1);
    
    	GPIOB->AFR[1] |= GPIO_AFRH_AFSEL8_1
    			| GPIO_AFRH_AFSEL8_2
    			| GPIO_AFRH_AFSEL9_1
    			| GPIO_AFRH_AFSEL9_2;
    
    	GPIOB->OTYPER |= (GPIO_OTYPER_OT8 | GPIO_OTYPER_OT9);
    
    	I2C1->CR1 &= ~(I2C_CR1_PE_Msk); //clean PE bit
    
    	//clock configuration
    	I2C1->TIMINGR |= 1 << I2C_TIMINGR_PRESC_Pos
    			| 2 << I2C_TIMINGR_SDADEL_Pos
    			| 3 << I2C_TIMINGR_SCLDEL_Pos
    			| 3 << I2C_TIMINGR_SCLH_Pos
    			| 9 << I2C_TIMINGR_SCLL_Pos;
    
    	I2C1->CR1 |= I2C_CR1_PE_Msk;
    }
    
    void i2cSendStartCondition()
    {
    	while((I2C1->ISR & I2C_ISR_BUSY_Msk)) {
    		printf("BUS not free!!!\r\n"); // wait for free bus
    	}
    
    	I2C1->CR2 |= I2C_CR2_START_Msk; // SEND START CONDITION
    
    	while ((I2C1->CR2 & I2C_CR2_START_Msk)) {
    		//start = 0, wait for start sended on BUS
    		printf("Waiting\r\n");
    		if (I2C1->ISR & I2C_ISR_NACKF_Msk) {
    				printf("ERROR: NACK received\r\n");
    				return;
    		}
    	}
    
    	while (!(I2C1->ISR & I2C_ISR_TXIS_Msk)) {
    		printf("Wait for ack\r\n");
    		if (I2C1->ISR & I2C_ISR_NACKF_Msk) {
    			printf("ERROR: NACK received\r\n");
    			return;
    		}
    
    	}
    
    }
    
    
    void i2cMasterSendData2(uint8_t slaveAddr, uint8_t addr, uint8_t *data, uint8_t len)
    {
    	i2cMasterInit(slaveAddr, false);
    	I2C1->TXDR = addr;
    
    	for (int i = 0; i < len; i++) {
    		while (!(I2C1->ISR & I2C_ISR_TXIS_Msk)) {
    			printf("Wait for TXIS\r\n");
    			if (I2C1->ISR & I2C_ISR_NACKF_Msk) {
    				printf("ERROR: NACK received\r\n");
    				return;
    			}
    		}
    		printf("send data");
    
    		I2C1->TXDR = data[i];
    	}
    
    	if ((I2C1->ISR & I2C_ISR_TC_Msk)) {
    		printf("TC setted: %u\r\n", I2C1->ISR);
    		//send stop condition
    		I2C1->CR2 |= I2C_CR2_STOP_Msk;
    	} else {
    		printf("ISR: %u, \r\n", I2C1->ISR);
    
    		printf("TC not setted\r\n");
    	}
    
    }

     

     

     

    Super User
    March 6, 2024

    > set the CR2_NBYTES bit (3 << I2C_CR2_NBYTES_Pos)...etc

    I don't see that in the above code.

    Try to step through it, reading out and printing/displaying I2C_ISR and I2C_CR2 after each relevant step; post resulting sequence.

    JW

    Super User
    March 6, 2024

    OK I think I understand what is the source of your confusion. I believe the flowchart is not quite correct. We might've discussed this here before, I can't find that thread at the moment.

    > 1) Sometimes at the end of the transmission, the TC bit remain low but I notices that if I put some delay before the TC check it work(as if I had to wait a certain time first, but in the flowchat I don't see this)

    After storing the last byte to TXDR, it takes time until it gets transmitted. Only after the last byte gets transmitted is TC set.

    > 2) It's correct that for the last byte TXIS remain low?

    Yes. Again, the narrative and the flowchart is not quite correct. The intention is, that TXIS is not indicator of "transmit register got empty" but "transmit register needs data"; the distinction is exactly that after the NBYTE bytes have been transmitted, there is no more "transmit register needs data" request.

    waclawekjan_0-1709721332467.png

     

    JW

    dmrsimAuthor
    Graduate
    March 7, 2024

    Hello @waclawek.jan , thanks as always!

    Yes you guessed the cause of my confusion.

    For the answer to the first question, I have a doubt: How do I understand how many time I have to check the TC bit before report a I2C timeout?

    However yesterday night I have checked the i2c write using an oscilloscope, I sended:

    start + 0x40 + 0x05 + 0x02 + 0x01 + stop

    As you can see in attacched image it seems to work correctly(could you check please?)

     

    Simeon