Quantcast
Channel: MSP low-power microcontrollers
Viewing all articles
Browse latest Browse all 63713

Forum Post: RE: Launchpad MSP430FR5969 i2c driverlib hangs on while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG))

$
0
0
Hi Zachary and othes. I thought I should contribute since I stumbled across these issues. I'm also hoping to use driverlib functions to control a variety of I2C peripherals. I came to grief in a few places and have a few work arounds that seem to work for me. 1) EUSCI_B_I2C_masterSendMultiByteStartWithTimeout : Where driverlib sets the start bit, I had to add in a check for the falling edge of the start flag or it hangs up further on down. Without this check I believe the code executes straight through to the sending of the single byte of data to the TX buffer before the I2C peripheral is ready to receive it. I can see this on a scope. Here's my hacked version. bool EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout) { //Store current transmit interrupt enable uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; // wait until start flag falls (after slave addr). while(EUSCI_B_I2C_masterIsStartSent(EUSCI_B0_BASE)) { ; } //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return(STATUS_SUCCESS); } 2) I wanted to then use EUSCI_B_I2C_masterReceiveSingleByte to implement a restart condition and read back a single byte. I found that this function fails when it tries to simultaneously write the start and stop flags. The stop flag is lost, the I2C peripheral does not send the expected NACK, and it finds itself attempting to do subsequent reads, and in doing so it holds the bus hostage. I amended the function as follows: // Wait until transmitted byte is done. while(!(HWREG16(EUSCI_B0_BASE + OFS_UCBxIFG) & UCTXIFG)) { ; } //Set USCI in Receive mode HWREG16(EUSCI_B0_BASE + OFS_UCBxCTLW0) &= ~UCTR; //Send start. HWREG16(EUSCI_B0_BASE + OFS_UCBxCTLW0) |= UCTXSTT; // wait until start flag falls (after slave addr). while(EUSCI_B_I2C_masterIsStartSent(EUSCI_B0_BASE)) { ; } // send stop HWREG16(EUSCI_B0_BASE + OFS_UCBxCTLW0) |= UCTXSTP; //Poll for receive interrupt flag. while(!(HWREG16(EUSCI_B0_BASE + OFS_UCBxIFG) & UCRXIFG)) { ; } //Send single byte data. i2cData[0] = (HWREG16(EUSCI_B0_BASE + OFS_UCBxRXBUF)); 2 randon thoughts: 1. Are there any requirement on the speed of the clocks here. I've tried this with the MCLK set to 8 times the SMCLK that drives the I2C and again with MCLK = SMCLK, with the same outcome. And I've slowed the transfer baud right down. Which does set alarm bells ringing a bit. 2. It also occurs to me that code were broken up into smaller chunks and implemented inside an interrupt handler, the problems might go away, if care was taken with the interrupts. But as it stands, it looks like these driverlib functions don't quite work? Although, that not to say they aren't an awesome resource, and a fantastic starting point. Is there anyone out there who is thinking 'that guys doesn't know what he's talking about! He's doing it all wrong'. If so, please put me straight! I love it when I'm wrong. That way, I learn something! Thanks all, Al.

Viewing all articles
Browse latest Browse all 63713

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>