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.

Reading NAK flag on MSP430

Other Parts Discussed in Thread: MSP430F5255

Hi All,

I am using MSP430F5255 in Master mode and talking to a slave device in HTU21D over I2c.

The recommended format for starting a conversion and reading the results is as per the attached file.

MSP just hangs after it receives the first NAK from the slave. I have tried a combination of steps to try and read the NAK_INTERRUPT(that would not help as I understand reading from some previous posts.)

So wanted to know what would be the best approach  to send multiple read requests after receiving the first NAK ?

Best Regards,

Chinmay

  • Hi all,

    So posting some more updated information so I could get some help with symptoms that i am seeing. 

    Code:

    switch (eHTU21MeasureType) {
    	case HUMIDITY: // commented this part as I am configuring the mode earlier on in the code .
    		//USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, I2C_ADR_W);
    		//USCI_B_I2C_enable(USCI_B1_BASE);
    		//USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);
    
    		USCI_B_I2C_masterMultiByteSendStartWithTimeoutHTUD21(USCI_B1_BASE,
    				TRIG_RH_MEASUREMENT_POLL, UCS_getSMCLK() / 8);
    		break;
    	case TEMP:
    		//USCI_B_I2C_setSlaveAddress(USCI_B1_BASE, I2C_ADR_W);
    		//USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_TRANSMIT_MODE);
    		//USCI_B_I2C_enable(USCI_B1_BASE);
    		USCI_B_I2C_masterMultiByteSendStartWithTimeoutHTUD21(USCI_B1_BASE,
    				TRIG_T_MEASUREMENT_POLL, UCS_getSMCLK() / 8);
    		break;
    	default:
    		break;
    //		assert(0);
    	}
    // I see the slave address being sent out here but the clock edges are missing when sending gout the command that is 0xF5 - No hold master trigger humidity measurement.
    // the strange part is that the Logic analyser I am using fails to capture this part at all. Which makes me suspicious if MSP is violating some setup hold times /I2C requirements.
    // sets the device in receive mode to read the NAK bit 
        USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);
    	USCI_B_I2C_clearInterruptFlag(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT|
    	USCI_B_I2C_NAK_INTERRUPT|USCI_B_I2C_TRANSMIT_INTERRUPT);
    
    	uint8_t intr_status = 0;
    	//USCI_B_I2C_masterMultiByteSendStop(USCI_B1_BASE);
    
    
    
        
       // I am trying to send multiple start conditions here just to see where I receive an ACK. - have not been able to get this far yet as I have not been able to determine if the command has been sent successfully. 
    // Not sure if I should be waiting for the UCRXIFG flag or soomething else to see if I receive and ACK- need suggestions on how to read this condition USCI_B_I2C_masterSingleReceiveStartWithTimeoutHTUD21(USCI_B1_BASE,100);
    	while(UCRXIFG)
    	{
    
    		//USCI_B_I2C_masterSendStart(USCI_B1_BASE);
    		USCI_B_I2C_masterSingleReceiveStartWithTimeoutHTUD21(USCI_B1_BASE,100);
    		//USCI_B_I2C_masterMultiByteSendStop(USCI_B1_BASE);
    		//intr_status = USCI_B_I2C_getInterruptStatus(USCI_B1_BASE,USCI_B_I2C_RECEIVE_INTERRUPT);
    
    	}
    	//-- wait hold master released --
    	* pMeasurand = 0;
    
    	USCI_B_I2C_clearInterruptFlag(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT);
    	USCI_B_I2C_masterMultiByteReceiveStart(USCI_B1_BASE);
    	USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);
    	while (USCI_B_I2C_isBusy(USCI_B1_BASE))
    		;
    	*pMeasurand |= (uint16_t) USCI_B_I2C_masterMultiByteReceiveNext(
    			USCI_B1_BASE)* 256;
    	*pMeasurand |= (uint16_t) USCI_B_I2C_masterMultiByteReceiveNext(
    			USCI_B1_BASE);
    	while (USCI_B_I2C_isBusy(USCI_B1_BASE))
    		;
    	USCI_B_I2C_masterMultiByteReceiveStop(USCI_B1_BASE);

    Best Regards,

    Chinmay

  • This diagram is a bit ambiguous. Most likely it tells you this:

    You start a transfer, address the slave (which the USCI does automatically when setting UCTXSTT, so you don’t send the address yourself), then a command.
    The slave begins measurement. Now you make a repeated start. Which the slave won’t acknowledge because it has no result yet. The slave behaves as if it wouldn’t be there. Your code has to detect this and simply retries. As soon as the slave has a result for you, it will ACK the read request and you can fetch the data.

    So depending on the time the slave is busy, the second line may happen multiple times or never.
    But since sending the command was successful, you know that the slave is there and just busy. If the write attempt (the first line) had resulted in a NACK (which you need to check too!), the slave really isn’t there. Or you use the wrong slave address :)

    This ‘no hold master’ mode is for not blocking the bus while being busy. In ‘hold master’ mode, the slave would hold the clock line low at the end of the second line, releasing it and sending an ACK (skipping ht e3rd line) when ready. Which would block the bus, but is easier to handle if it is the only slave, and also would be faster (no need to wait for another start)

  • Hi ,

    Earlier on in the code I do send out a reset to the slave that happens successfully. Attaching the waveform for that below. it happens about 50 ms prior to the request to trigger measurement.

    This is what confuses me. 

    Possible suspects.

    1. Wrong slave address(slave not present): I am able to communicate with it early on and receive an AC so want to rule that out. I am trying out this code on a production level board(PCB) so will have to see if there is something wrong going there. 

    2. Getting a NAK after the command after the first command. - That is something I need to look at . So how do you read the NACK flag on MSP ? I was reading through some posts earlier and figured that the flag is cleared as soon as the interrupt is received.  I tried to use the "USCI_B_I2C_getInterruptStatus(USCI_B1_BASE,USCI_B_I2C_NAK_INTERRUPT);" with little success, it would always return a 0. 

    3. I preferred the no hold master mode as there are other "things" happening in the code, cannot wait on that. But I have tried the other mode as well with similar results. 

    4. Not important but I am able to talk to two other slave devices on the bus. 

    -Chinmay

  • Yes, the hold master mode, while providing faster reaction time, blocks the bus. If there are multiple slaves, this is no solution.
    Some devices offer an ‘interrupt’ signal to tell the master that the operation is complete and the slave is available for delivering the result. If this is available and can be used (a matter of available additional I/O lines), this would be preferred over polling like this. However, it still requires starting a transfer from scratch rather than have the transfer started and stalled until data available. So 'hold master' is still fastest.

    If you set UCTXSTT and the slave doesn’t answer, then when UCTXSTT clears, UCNACKIFG is set (and if UCNACKIE is set too, the ISR is called).
    This way you know that the slave didn’t respond and is apparently not ready yet.

  • Hi Jens,

    Many thanks for your comments. I was able to resolve the issue with some debugging and some code samples with a local TI Engineer.

    I had the following problems in the code.

    1. I should have waited , with a delay or checking the busy flag when transmitting the slave address, i.e. when I change mode from transmit to receive.

    2. The way I was reading the NACK flag was not correct (calling the API USCI_get_interrupt status), .You have to send the start condition and then poll on UCNACKIFG. Maybe this could be made a part of the standard API, that are present.

    Best Regards,

    C Nanda

  • Asynchronous calls in operating systems usually have blocking and non-blocking versions (or a flag to select)
    The library apparently uses non-blocking calls. That means, the operation is initiated, but the function returns before it is complete. It would be indeed nice to have it return with a return value whether an ACK or a NACK was received. However, this is difficult to do, because the USCI I2C requires a value written to TXBUF before it completes the ACK cycle.
    To simply check for the slave presence, you can set UCTXSTT and UCTXSTP together. This will send the start byte and complete the ACK, then send a stop. You can then check UCNACKIFG. This does, however, add 11 bit times overhead to the transfer.

    That’s why I prefer writing my own low-level code and not using libraries. At least on microcontrollers.

**Attention** This is a public forum