yyrkoon 250 Posted March 18, 2017 Share Posted March 18, 2017 I was wondering if anyone knows of a good read concerning implementing an I2C slave device. What I'm looking for, is something that covers kind of a high level discussion of what needs doing. Without a bunch of specification, or physical characteristic discussion. Meaning, I do not care about the electrical / physical characteristics of such a device, and I have a hard time digesting specification type books. Mostly, what I really need to know is a processor / language agnostic view of how to implement the slave addressing stuff. Such as device addresses, and register addressing. Code examples would be cool, in any language, but are not strictly speaking, necessary. Additionally, I'm also interested in implementing a slave device using the 1-wire protocol too. EDIT: Additional information, which may help someone else help me. As a hobby project, for the purpose of learning, I'm attempting to turn an MSP430G2553 into a slave device that could potentially be used as an I2C slave device that could possibly be an ADC, PWM, GPIO expander, or a combination of all mentioned plus more. However, the reading material does not necessarily have to be specific to the MSP430G2553, or any MSP430 for that matter. Quote Link to post Share on other sites
Clavier 34 Posted March 18, 2017 Share Posted March 18, 2017 Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family Read section 17.3.4.1 of the User's Guide, and the example code. Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests. The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address. You do not need to configure a clock source; the clock signal is supplied by the master. When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.) When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF. If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted. You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary. The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments). As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.) bluehash, Fmilburn, yyrkoon and 1 other 3 1 Quote Link to post Share on other sites
bluehash 1,581 Posted March 18, 2017 Share Posted March 18, 2017 Moving to General Electronics. Quote Link to post Share on other sites
yyrkoon 250 Posted March 18, 2017 Author Share Posted March 18, 2017 6 hours ago, Clavier said: Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family Read section 17.3.4.1 of the User's Guide, and the example code. Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests. The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address. You do not need to configure a clock source; the clock signal is supplied by the master. When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.) When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF. If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted. You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary. The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments). As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.) @Clavier , Awesome, thanks. I would have responded sooner, but someone *cough* @bluehash moved my post, and now I'm not getting notifications . . . Anyway, you pretty much answered, all the questions I had. Which mainly was if I use USCI, would I have to handle all the bus com stuff. e.g. device address, and all that. But I do need to figure out what you're talking about, concerning setting the slave address in some register. Because I'm going to need to do that via dip switches. e.g. physically. I did also find this on github last night -> https://github.com/wendlers/msp430-i2cslave Apparently written by one of the people from the German branch of TI. Quote Link to post Share on other sites
zeke 693 Posted March 18, 2017 Share Posted March 18, 2017 I have done both of these tasks for more than one client. The 1-Wire protocol speed ends up being about 15kHz, which is slow but reliable. It's really cool to see on an scope though. I developed the I2C slave code using the sample TI code as the starting point. Here are the research materials that I referred to while writing my I2C code: http://www.nxp.com/documents/application_note/AN10216.pdf http://www.nxp.com/documents/user_manual/UM10204.pdf http://i2c.info/i2c-bus-specification http://www.ti.com/lit/an/slva704/slva704.pdf My slave code just follows the logic of the transaction. yyrkoon, Fmilburn, bluehash and 1 other 4 Quote Link to post Share on other sites
yyrkoon 250 Posted March 19, 2017 Author Share Posted March 19, 2017 Part of what I was trying to figure out is would I be able to use PWM ADC, as well as I2C plus 1 each GPI, and GPO, all on a G2553, which seems perfectly doable. After that, I was not sure how USCI handles I2C coms. But if it's as simple as setting a constant to the device address value, then again, No problem . .. Quote Link to post Share on other sites
zeke 693 Posted March 19, 2017 Share Posted March 19, 2017 I've never gotten the interrupt driven I2C Master to work reliably but I have gotten the interrupt driven I2C working like a charm. I've done this working on the 2955, the 2553, and the 5529. I've used a state machine to divide up all the functionality between the I2C, the Serial IO, and the GPIO. It's weird to realize that I have never used the ADC nor the PWM yet. Quote Link to post Share on other sites
yyrkoon 250 Posted March 20, 2017 Author Share Posted March 20, 2017 On 3/19/2017 at 3:31 PM, zeke said: I've never gotten the interrupt driven I2C Master to work reliably but I have gotten the interrupt driven I2C working like a charm. I've done this working on the 2955, the 2553, and the 5529. I've used a state machine to divide up all the functionality between the I2C, the Serial IO, and the GPIO. It's weird to realize that I have never used the ADC nor the PWM yet. The ADC is pretty easy. There's documentation all over the web, which is how I prefer "things". Reading blog posts that go into detail as well as explaining their code. That way, if I don't get the initial explanation, the code, and code explanation usually does the job pretty good. Usually, blog posts are also short, and to the point. Which is why I normally do not do well with specifications. I just want to know what I need to do, in order to achieve and end goal. Not memorize ever_single_minute_detail. To do what I need to achieve, I may have to go to the 2955, for the added program ram, and flash. But, I'm 99% sure what I need to do can be done on a 2553. @zeke, would you mind going into high level detail about this state machine you mentioned ? Perhaps a very simplistic pseudo code example ? One of the things that has me a little "worried", is wondering if the interrupts could potentially preempt one another. Thus, having missed interrupts. However, I'd probably want to use hardware I2C, and for PWM, I'll probably have to use interrupts on the timers, to get a proper frequency, and duty cycle. *Maybe* I could get away with a polled GPI, but the ADC's . . . yeah not sure. EDIT: Ideally, I'd prefer to do everything in hardware if at all possible. So, PWM, ADC, and I2C all in hardware using interrupts, and as for the GPI, it doesn't matter. Quote Link to post Share on other sites
yyrkoon 250 Posted March 21, 2017 Author Share Posted March 21, 2017 So, on the surface, it looks like PWM is very simple. I could potentially get away with a fixed period, and make a variable duty cycle. e.g. *something* communicates with the MSP430 over I2C and gives a value between 1-99. Which would represent duty cycle. Then, it's just a matter of performing simple math with the value in CCR0, and put that result into CCR1. But there is still the potential for pin / resource conflicts that I'm not fully clear on yet. Quote Link to post Share on other sites
zeke 693 Posted March 21, 2017 Share Posted March 21, 2017 This is my approach to state machines. Your mileage may vary. Determine all of the sub-systems that you will want to service Commands, Controls and Inputs, User Interface, and Data Setup a system tick timer that fires its interrupt on a regular consistent basis. This system doesn't have to go into LPM4. If it does then periodically wake up the system and cycle through the software service loops then go back to sleep. Setup a series of service flags that are set during the interrupt service routine and cleared after being serviced: Flag(s) for Commands, Flag(s) for Controls and Inputs, Flag(s) for User Interface, and Flag(s) for Data Setup a variable that acts like the system timer odometer. Every Odometer == (DesiredInterval%ServiceFlag_n_now) set the ServiceFlag_n Decide how often you will service the other functional blocks of your code. For example, Update the 2x20 LCD display every one second, or Update the Serial Console every 250ms, or Retrieve the Temperature from a sensor every 15 minutes. Setup an Interrupt Service Routine to catch any characters coming into the Serial Port Buffer. Stuff them into the Input Ring Buffer Set a flag that there's something to service. In the main loop, scan all of the service flags to see if any are set. Call the servicing function for each set flag. Clear the service flag at the end of that process. Configure the program to repeat continuously until Kingdom Come. I've left out significant details about setting up all of the peripherals and general variables so don't forget to do that stuff. This is just the basic gist of my state machines on a bare metal level. bluehash, yyrkoon, nickds1 and 1 other 4 Quote Link to post Share on other sites
yyrkoon 250 Posted March 22, 2017 Author Share Posted March 22, 2017 @zeke thanks, That, more or less seems to be what I do myself. In this case however, there won't be a user interface, nor anything related to "feedback" over serial as an I2C slave can't communicate with the master unless the master initiates the communications. There also won't be an LCD, but I do not think that was you point, and I'm not sure If I will be able to use UART for serial debugging or not. However, this very well may be a chance, and a reason for me to use the logic analyzer I bought a few months ago. Now, I need to try and figure out how to program the 28pin G2553's. With the 20pin dip package MCU's I've just been using a ZIF socket on the launchpad, and moving programmed parts to a socket on the board which needed the MCU. Now, I'm kind of at a loss. My buddy wulf has put JTAG, and spy-by wire headers on the prototype, but . . . I've no clue where to start. Quote Link to post Share on other sites
NurseBob 111 Posted March 25, 2017 Share Posted March 25, 2017 On 3/22/2017 at 9:10 AM, yyrkoon said: My buddy wulf has put JTAG, and spy-by wire headers on the prototype, but . . . I've no clue where to start. @yyrkoon, One place you might explore is under the "code examples" sections for the G2553. In particular, I'd start with: msp430g2xx3_uscib0_i2c_04.c ( USCI_B0 I2C Master RX single bytes from MSP430 Slave ) msp430g2xx3_uscib0_i2c_05.c ( USCI_B0 I2C Slave TX single bytes to MSP430 Master ) and msp430g2xx3_uscib0_i2c_06.c ( USCI_B0 I2C Master TX single bytes to MSP430 Slave ) msp430g2xx3_uscib0_i2c_07.c ( USCI_B0 I2C Slave RX single bytes from MSP430 Master ) As the examples note, you need the external pullup resistors. These examples will compile under CCS, IAR and GCC and while simplistic, they are a starting point for seeing the I2C comm in the debugger. I've used similar examples for the F2013 and F5529 to get those ICs to talk to each other, and subsequently to write code for the F5529 to talk to an sx1509 port expander (an adventure in reading and understanding docs...). FWIW, I would never have gotten very far without using both my logic analyzer and my oscilloscope... As to the jtag header and spy-by-wire headers (how I build all of my prototypes) - make sure there's the 47k resistor for the reset line (most devices do not need the capacitor placed), and you may want to account for using an external supply instead of the FET. The debuggers generally are limited in their supply capacity to ~50-60 mA. If your circuit is driving other devices, that can lead to failure for the debugger to even start. HTH Bob yyrkoon 1 Quote Link to post Share on other sites
zeke 693 Posted March 29, 2017 Share Posted March 29, 2017 @yyrkoon, This is a schematic of a typical programming setup. It doesn't matter what MSP430 that you use because they all can be wired up like this. To program this unit, I connect another G2 LaunchPad to this circuit using a four wire cable between P1 of this circuit and either J3 or J4 of the G2 LaunchPad board. Then program the circuit as if you were programming the G2 LaunchPad. yyrkoon 1 Quote Link to post Share on other sites
yyrkoon 250 Posted April 17, 2017 Author Share Posted April 17, 2017 So, we've got the capes( Beaglebone ), and remote boards(I2C slave boards ) made and assembled for testing. For the moment, we're testing over cat5e, that's only about 1 foot in length, but later we're going to test 300m ( 900 feet ) worth of cable. So for those who are not aware of this "technology". We're attempting differential I2C which is supposed to be capable of up to 300 meters. So, I really do not want to sounds stupid . . . but essentially, you're transmitting over cat5e using CANBUS hardware, and what I think is reverse logic 24vdc carrier. So basically, an amplified signal. Anyway, it seems to be working on at least 1 foot, which from what I understand is fairly difficult with normal I2C signalling. So far, I've only queried the remote board via i2cdetect from the i2c-tools Linux utility set. Well, we've also dumped the registers( i2c-dump ) and everything seems to be in sync with our test jig. This specific board does not have an MSP430 on it, and this specific one probably wont. But in the future we'll be doing all kind of crazy stuff over differential I2C. So if you're interested, stay tuned ! Which by the way, wulf, and I will be selling beaglebone capes sometime in the future. Quote Link to post Share on other sites
zeke 693 Posted April 18, 2017 Share Posted April 18, 2017 If it matters, I have done I2C via 1Wire over that distance and farther. If you slow the speeds down then you should be fine. 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.