basil4j 1 Posted March 17, 2014 Share Posted March 17, 2014 Hi All, Using the MSP430FR5739 UCSI_B in i2c mode. Just checking ive got this right, as I've never used it before. I neod to do the following, Ive left out the ack's S= start E= stop [Address+write][Register][Address+read][Read 6 bytes][E] Setup at beginning of program: UCB0CTL1 = UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 = UCMODE_3 | UCMST | UCSSEL__SMCLK; //I2C master mode UCB0BRW = 0x0008; //clock scaler UCB0CTL1 &= !UCSWRST; // eUSCI_B in operational state UCB0IE |= UCTXIE; // Enable interrupts Program calls the following to get things going: UCB0CTL1 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW1 |= UCASTP_2; // stop after bytes sent UCB0TBCNT = 6; // automatic stop after bytes UCB0CTL1 &= !UCSWRST; // eUSCI_B in operational state UCB0I2CSA = 0x3A; // address of slave UCB0CTLW0 |= UCTR; //transmitter mode UCB0CTLW0 |= UCTXSTT; // generate start condition, Transmit interrupt (should 1 byte and then get ready to send a repeat start once that byte has finished) case 0x18: // Vector 24: TXIFG0 Ok to accept data into buffer UCB0TXBUF = 0x32; // send register of first byte of data //I2C will start sending this data //Get i2c ready for next bit UCB0CTLW0 &= !UCTR; //receive mode UCB0CTLW0 |= UCTXSTT; // generate start condition. break; Receive interrupt (accel[] is a char array where I want to store the data, should receive 6 bytes into this array then stop. The auto stop was setup at the beginning. case 0x16: // Vector 22: RXIFG0 Ready to take data from buffer accel[UCB0TBCNT] = UCB0RXBUF; //Get data from buffer break; Thanks in advance! Quote Link to post Share on other sites
tripwire 139 Posted March 17, 2014 Share Posted March 17, 2014 The MSP430FR5739 has the enhanced eUSCI_B module, which is slightly different to the USCI_B on the g2xx series chips. The eUSCI_B doesn't have UCBxCTL0 and UCBxCTL1 registers (they've been merged into UCBxCTLW0). Interestingly the example initialization sequence in section 20.3.1 of the MSP430FR57xx Family User's Guide hasn't been updated to account for the change. Unless the FR57 headers have some backward compatibility support for USCI_B register names the guide needs to be corrected. EDIT: Looking at the User's Guide again I see that UCBxCTL0 and UCBxCTL1 are available on FR57 parts. They just alias the appropriate bytes of UCBxCTLW0. When using UCBxCTL0 or UCBxCTL1 it looks like you need to append _L or _H (respectively) onto the names of any bit constants to get the correct value. I think the initialization sequence needs to look like this: UCB0CTLW0 = UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 = UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSWRST; // I2C master mode, SMCLK, retain reset flag state UCB0BRW = 0x0008; //clock scaler UCB0CTLW0 &= ~UCSWRST; // eUSCI_B in operational state (clear reset flag) UCB0IE |= UCTXIE0; // Enable TX interrupt for address 0 The "get things going" block looks ok (apart from a couple more uses of UCB0CTL1). You might have issues due to taking the module out of reset before setting the slave address. I'm not sure on that though, the fact that UCTR is clear at that time might mean it's safe. In the interrupt I think you're clearing UCTR and setting UCTXSTT too early. According to the timeline diagrams in the user guide you should wait for UCTXIFG0 to go high again after you set UCB0TXBUF to the command value. The receive looks ok, though I've not used USCI_B interrupts before so can't be sure. Quote Link to post Share on other sites
basil4j 1 Posted March 17, 2014 Author Share Posted March 17, 2014 I think the initialization sequence needs to look like this: UCB0CTLW0 = UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 = UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSWRST; // I2C master mode, SMCLK, retain reset flag state UCB0BRW = 0x0008; //clock scaler UCB0CTLW0 &= ~UCSWRST; // eUSCI_B in operational state (clear reset flag) UCB0IE |= UCTXIE0; // Enable TX interrupt for address 0 Thanks! Not something someone new to MSP would know too well haha The "get things going" block looks ok (apart from a couple more uses of UCB0CTL1). You might have issues due to taking the module out of reset before setting the slave address. I'm not sure on that though, the fact that UCTR is clear at that time might mean it's safe. Thats the main bit I am confused about. The Family giude says After initialization, master transmitter mode is initiated by writing the desired slave address to the UCBxI2CSA register, selecting the size of the slave address with the UCSLA10 bit, setting UCTR for transmitter mode, and setting UCTXSTT to generate a START condition. None of these registers say the module needs to be in reset mode to access, so I just left them out of it to keep things simple in my code (i.e. only things which must be done in reset are done in reset). The timing diagram says it starts when both UCTXSTT and UCTR = 1, it then generates a start and sends the slave address so I figured as long as I set the slave address before these 2 registers it would be ok. In the interrupt I think you're clearing UCTR and setting UCTXSTT too early. According to the timeline diagrams in the user guide you should wait for UCTXIFG0 to go high again after you set UCB0TXBUF to the command value. The receive looks ok, though I've not used USCI_B interrupts before so can't be sure. EDIT: I think you're right, UCTXSTT needs to be set and UCTR clearing during transmission of the last byte (not before). UCTXIFG0 goes high once UCB0TXBUF is being sent. Quote Link to post Share on other sites
basil4j 1 Posted March 17, 2014 Author Share Posted March 17, 2014 Revised code. This should take care to avoid resending the data byte over and over...How does this look? case 0x16: // Vector 22: RXIFG0 Ready to take data from buffer accel[UCB0STATW >> 8] = UCB0RXBUF; //UCB0STATW byte counter starts at bit 8 break; case 0x18: // Vector 24: TXIFG0 TXIFG0 is set when TXBUF is empty or when Start condition is generated /* The UCTXIFG0 bit is set when the START condition is generated and the first data to be transmitted can be written into UCBxTXBUF. The UCTXSTT flag is cleared as soon as the complete address is sent.*/ if (UCB0CTLW0 && UCTXSTT) { // UCTXSTT is still set so this branch will be taken the first time around (i.e. start condition generated) UCB0TXBUF = 0x32;// put byte of data into TX buffer. } else { // UCTXSTT will be cleared by now and TXBUF will have been transfered to shift register UCB0CTLW0 &= !UCTR; // Put into receive mode UCB0CTLW0 |= UCTXSTT; // generate start condition. } break; Quote Link to post Share on other sites
tripwire 139 Posted March 17, 2014 Share Posted March 17, 2014 You're right about not needing to hold the USCI module in reset between the initialisation and master transmitter mode initiation. The module will just wait for UCTXSTT to be set before starting to do anything. The updated interrupt looks ok, but you need to use UCB0CTLW0 & UCTXSTT rather than UCB0CTLW0 && UCTXSTT as the condition ("bitwise and" rather than "logical and"). There's something else I totally forgot to mention - you'll need to set up the port registers appropriately to connect the USCI to the outside world. The pinouts vary per chip and package, so the information on that is in the datasheet for the MSP430FR5739 rather than the family user guide. Quote Link to post Share on other sites
basil4j 1 Posted March 17, 2014 Author Share Posted March 17, 2014 Oops, typo haha thanks. I did this to the port registers. P1SELC |= I2C_SDA | I2C_SCK; //Configure I2C pins P1SELC sets P1SEL0 and P1SEL1 simultaneously. I assume USCI is tertiary function, the pin list on the datasheet says there are up to 5 functions on some of the pins, so who knows how i'd use something beyond tertiary :/ Quote Link to post Share on other sites
basil4j 1 Posted March 17, 2014 Author Share Posted March 17, 2014 Oh thats something I didnt think of. Does the USCI module add the read/write bit to the end of the slave address? I assume it does, because the address is refered to as 7 bits, not 8. Thought i'd check because I cant change the address before the repeat start without resetting everything... Quote Link to post Share on other sites
tripwire 139 Posted March 17, 2014 Share Posted March 17, 2014 I don't think you want to select tertiary function for P1.6 and P1.7 - take a look at page 74 of the datasheet. UCB0SDA on P1.6 and UCB0SCL on P1.7 are selected when bits 6 and 7 of P1SEL1 are set to one and the corresponding bits of P1SEL0 are zero. The USCI module will automatically send the R/W bit along with the address. That's something to be wary of, as some I2C peripherals give an 8 bit address which includes the R/W bit already. Quote Link to post Share on other sites
basil4j 1 Posted March 17, 2014 Author Share Posted March 17, 2014 Oh look at that! Thanks! Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.