Couple of TWI questions...

Go To Last Post
40 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does Atmel now Microchip have an AVR### type document where they make an ISR driven driver for TWI master and/or slave?

 

Does it make sense (save CPU cycles) to do the master/slave via ISR's instead of a doing it without interrupts?  Does there come a point where the overhead of firing interrupts back and forth is not so efficient compared to just doing it without?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You might want to do a search of the site as this has come up in the past.  I think it was a 50/50 on the benefits of the interrupt/non-interrupt.

 

FWIW I myself have never bothered with the interrupt.  Always just ran a routine that serviced the TWI and then jumped back to the main loop.  If the slave device had an interrupt pin then I would use that to trigger the AVR if needed and then used  the TWI accordingly.

 

I'll ask before someone else does......Whats your application and what device are you looking to interface with?

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Jim - it is for some work I'm doing for someone.  It is not high bandwidth, not a lot of data, just two AVR's communicating with each other.

 

I just wonder if I am going to build a driver to do it, does it make sense to make an interrupt driven one or not.

Last Edited: Mon. Apr 2, 2018 - 02:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For comms between two AVR's why not use the USARTS?    WAY simpler and you can certainly use the interrupts easily

 

SPI would be another option as well.

 

I am not saying NOT to use TWI, I just think the other interfaces might be a better/easier option.  It all depends on what you want the two AVR's to pass back and forth, as well as distance between teh two as well.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hear you Jim; not my design and the interface is already done/selected!  Each AVR is on its own board separated by 8-10" or so.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, then with that being said, then the question is one board is the "Master" and the other the "Slave" yes?  Two Wires and a ground Yes?

 

The master of course handles the START and all the good stuff.  The slave then could have the Interrupt enabled so that when the Master 'polls' it the interrupt fires in the slave, and it does what needs to be done and thats it.

 

In theory I would think that you could use Peter Fleurys TWI master code(non interrupt based) for the master, and then do an Internet search for a library of interrupt based TWI slave routines.

 

Job done....happy hour awaits.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Appnotes AVR311 and AVR315 are for interrupt driven TWI, but if I remember well they are not well regarded and buggy or incomplete (and pretty old).

 

There are some TWI and I2C libraries for AVR on github, maybe some of them are good:

https://github.com/search?utf8=%E2%9C%93&q=avr+twi&type=

https://github.com/search?utf8=%E2%9C%93&q=avr+i2c&type=

 

 

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What are the issues with AVR311/315 - they both look to be interrupt driven and methodical.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the apps that I have written, the master works well as non-interrupt, while the slave worked well being interrupt driven. YMMV!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

AVR311, AVR315 both work fine.
As a general rule, a Slave needs interrupts. A Master can poll or interrupt.
.
I would use the Fleury polled code for the Master. And adapt AVR315 to implement your Slave behaviour.
.
Codevision and Arduino both provide TWI Slave functionality.
Even if your final project uses GCC, it is useful to test your code with proven library code.
.
Remember that TWI provides status values. Library code provides error return values. USE THEM.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
TWI provides status values

By "TWI" here, do you mean, "the AVR's TWI peripheral" ?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks like AVR311/315 have directories for both IAR and Atmel Studio now.  I'll start with their functions and see what I can do with them.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was a long time that I tried to use I2C.

I have vague memories of some of the error conditons not being handled properly which could result in an infinite loop.

 

This is mostly due to an ommision in the I2C standard where no thought was given to timeouts.

The SM Bus Standard is very similar to I2C. It's biggest change are the inclusion of timeouts to prevent infinite error conditions.

This also has some side effects, such as a minimum baudrate.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, I'm going to try the AVR 311/315.  I have a question of "protocol".  I am reading basically 9 bytes from this device, one 8 bit value and four 16 bit values.  Perhaps 10 times per second.  Not a lot of data or bandwidth.  Using the "register" method, you would setup an i2c write, provide the register number, then do a repeated start with a read and then read it out.  That is what someone else's code is doing right now.  To me that seems like a whole lot of waste, but I can appreciate the register method for its flexibility.  Part of me says just do a read to the device and read out the 9 bytes each and every time.  No reason to write which register I want.  There are only 9 bytes to get and I need them everytime!!!  I get that there is a hybrid approach of set the register and read out multiple with an autoincrementing register number.  How would you do it?  Both are AVR's and this is the only communication between them except for maybe a write command to tell it to reset so I can get it into a bootloader mode.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Remember when the master reads data from the slave, the master must ACK each byte received until the last byte, which the master must NAK to tell the slave to release the bus so the master can send stop!

I2C functions of a good library will return a status, be sure to use it and check for expected value. handle exceptions when needed and all will work well.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the tip Jim - the first time I tried i2c I thought the "stop" would be good enough, but it isn't!  Gotta have the NAK!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

At a TWI speed of 400K, each bit takes 2.5 microseconds.  Each bit is equal amounts high and low (or released and asserted states), for a 1.25 uS "I2C interval".  Each read and write byte to TWI takes 18 to 20 intervals, and the START / repeated START takes about 4 intervals.   So reading a protocol frame of 9 bytes plus a register address and SLA takes about 275 microseconds using the polling method [the TWI starts the operation and the main code polls the TWI operation-complete bit in the TWI status register].  This is done 10 times a second: 275 microseconds is consumed by TWI for every 100,000 mircoseconds of CPU time.  Since this is a small value, and there is no indication that there are any timing-critical operations ( small CPU activities running at intervals faster than 275 microseconds, which would necessitate interrupting the TWI download) and the code is already written and functional, I recommend keeping the TWI as it currently is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I assume you have control over both AVR's here and there is no legacy protocol you have to be compatible with?

I also assume you do not have a copy of the original software and have to re-create it? (Re-use of existing sw would be too easy).

 

Keeping it simple is often a good idea.

When reading from the slave I would probably just read all 9 bytes, maybe read 11 bytes and add an (optional) 16 bit CRC, but I2C is pretty reliable on itself.

But I would also make sure that if "issues" arise later and modifications are wanted that there is a way to add them to the protocol when needed.

This can be as easily as to define that if at first a byte is written to the device that it then uses the "register" based method.

"Options" can always be added if needed to make your device also respond to another I2C address.

 

Or simply make your device compatible with (a part of) some existing protocol. Maybe a 24c02 EEprom?

 

But for me the most important would probably to make it reliable under all forseeable circumstances.

SM Bus https://en.wikipedia.org/wiki/System_Management_Bus has the built in timeouts. Implementing timeouts properly can be the difference between a total crash of your application if one of the I2C pullups is badly soldered or a message to another system such as a PC or a morse code on a blinking led that there is a problem on I2C and the sensor can not be read but the rest of the application keeps on working, or does a gracefull shutdown.

 

Writing / testing / debugging all errors on I2C will probably take more development time than getting I2C to work. I2C has a lot of possible error modes.

What happens if you receive a Nack after 3 bytes when you are reading a 9 byte message?

What happens if a bit is tretched into infinity.?

What happens if your slave does not answer at all?

What happens if one or both of the pullups are missing?

What happens if ...

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

Last Edited: Tue. Apr 3, 2018 - 09:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All excellent thoughts everyone.  I myself prefer the simplicity of SPI, but we'll see what I can get going on this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I myself prefer the simplicity of SPI, but we'll see what I can get going on this.
Huh ???

You started this thread with I2C questions and now you say you prefer SPI?

 

Big advantage of SPI is it's simplicity and that you can easily push it through some opto couplers.

Big advantage of I2C is that you have a 7 bit address space.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, I like SPI more.  I've used i2c before, and on this project, someone else designed it with i2c, so that is what I'm stuck with.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I2C is not really that complicated....if you use a well proven library.  

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ISR(TWI_vect)
{
  static unsigned char TWI_bufPtr;
  
  switch (TWSR)
  {
    case TWI_START:             // START has been transmitted  
    case TWI_REP_START:         // Repeated START has been transmitted
      TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
      
      
      /* SHOULD THERE BE A BREAK HERE */ 
      
      
    case TWI_MTX_ADR_ACK:       // SLA+W has been transmitted and ACK received
    case TWI_MTX_DATA_ACK:      // Data byte has been transmitted and ACK received
      if (TWI_bufPtr < TWI_msgSize)
      {
        TWDR = TWI_buf[TWI_bufPtr++];
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to send byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
               (0<<TWWC);                                 //  
      }else                    // Send STOP after last byte
      {
        TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully. 
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
               (0<<TWWC);                                 //
      }
      break;
    case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK transmitted
      TWI_buf[TWI_bufPtr++] = TWDR;
    case TWI_MRX_ADR_ACK:       // SLA+R has been transmitted and ACK received
      if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
               (0<<TWWC);                                 //  
      }else                    // Send NACK after next reception
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to read next byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
               (0<<TWWC);                                 // 
      }    
      break; 
    case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK transmitted
      TWI_buf[TWI_bufPtr] = TWDR;
      TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully. 
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
             (0<<TWWC);                                 //
      break;      
    case TWI_ARB_LOST:          // Arbitration lost
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
             (0<<TWWC);                                 //
      break;
    case TWI_MTX_ADR_NACK:      // SLA+W has been transmitted and NACK received
    case TWI_MRX_ADR_NACK:      // SLA+R has been transmitted and NACK received    
    case TWI_MTX_DATA_NACK:     // Data byte has been transmitted and NACK received
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
    default:     
      TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.
                                                        // Reset TWI Interface
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
             (0<<TWIE)|(0<<TWINT)|                      // Disable Interrupt
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
             (0<<TWWC);                                 //
  }
}

This is from their code - should there be a break where I added the comment???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think that there should be a "break;" where you added the comment.  After receiving a START, the TWI needs to receive an SLA+R/w and sets up the TWCR and TWDR to do this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you Simonetta!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I extended it to do repeated starts and multiple commands all in the interrupt.

 

  TWI_buf[0]=0xce;
  TWI_buf[1]=0;
  TWI_buf[2]=TWI_RESTART;
  TWI_buf[3]=0xce | TWI_READ;
  TWI_buf[4]=0;
  TWI_buf[5]=0;
  TWI_buf[6]=0;
  TWI_buf[7]=0;
  TWI_buf[8]=0;
  TWI_buf[9]=0;
  TWI_buf[10]=0;
  TWI_buf[11]=0;
  TWI_buf[12]=0;
  TWI_buf[13]=TWI_END;
  TWI_Execute();

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

IPv6 is also really simple (if you only use a web browser).

 

I think I've spent over a week to get the last bugs out of an I2C driver lib.

Then I wanted to use it with an attiny2313 instead of a m8 (or m328) and I could start all over again.

Incompatibilities between AVR's are a real bummer.

Tiny2313 could have been a real nice customizable I2C slave, but it does not even have the required slew-rate limited pins for proper I2C.

 

SPI was, maybe a few hours to from scratch to finish.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the proper way to shut down/abort a failed TWI transaction?  The AVR31x did not address a timeout so I added one using a timer ISR, but I am just setting TWEN.  I noticed in a failed situation that it doesn't issue a stop.  If I get to a timeout (TWI interrupt not called within x time), should I issue a stop instead?  Or perhaps only if start was ever done?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Alan, it can get a lot more complicated than what you describe. Since the TWI peripheral is a state machine things go horribly wrong if the two devices lose sync. My solution was to reset the TWI peripheral to bring it to a known state. My test procedure was to randomly short the i2c bus and the system should recover.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman, with i2c/TWI that doesn't surprise me!  What did you do to reset it?  In my case I just set TWEN only.  I did see a failure condition where one of the two lines was stuck low and then the next time it tried to communicate, it self corrected.  That is what made me wonder if I needed to issue a stop if a timeout occurs.  It seems like I've read some people advising doing a stop a number of times to make sure, but I can't recall where, likely here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Most of my experience is with AVR as master, if I always verify the ACK is received from the slave during start before tx/rx of the data, skip to stop if NAK, I never had a problem.

I could plug/unplug sensors on/off the bus and never had a hang or used a timeout. 

I would think doing a power cycle via the PRR reg would clear a bad state....

I've not tried that.

 

Jim

 

 

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wasn’t using Atmel parts - master was a kinetis and the slave a pic24. Resetting was disabling then re-enabling the peripheral.

Issuing stop won’t work in all situations - i’ve seen recommendations of trying to read bytes to escape certain states. I was lazy - reset fixes all!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So while troubleshooting some failure conditions I found that my TWI slave was not responding in some conditions / getting into a stuck condition.

 

the data sheet says:

 

     [TWEN] If this bit is written to zero, the TWI is switched off and all TWI transmissions are terminated, regardless of any
ongoing operation.

 

      case TWI_SRX_ADR_DATA_NACK: //0x88
      case TWI_SRX_GEN_DATA_NACK: //0x98
      case TWI_STX_DATA_ACK_LAST_BYTE: //0xC8
      case TWI_BUS_ERROR: //0x00
      default:
        //debug this works better for resetting it - add to all other modules!
        TWCR=0;
        TWCR=_BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
        break;

 

I added the TWCR=0, before re-initializing TWCR to enabled it and this seems to solve the problem.  has anyone else done/experienced this as well?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,  you can reset the TWI peripheral with TWEN=0.   e.g. TWCR=0

 

Resetting a locked Slave might not be as simple.   If the Master has released the bus  (with TWEN=0) it does not necessarily make the Slave release the bus.

 

I would test my Slaves thoroughly.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree David.  My code above was the slave/receiver.  I originally did NOT have the TWCR=0 before the reinit of TWCR and it did end up in a locked state where it would not respond properly.  I think even addition to the interrupt doing that when I get an unexpected status code, I will also have a timer ISR keep watch on the idle time once a transaction is started and if that also exceeds a timeout, then it will get reset as well.  That way the master can simply not talk to the slave for that timeout plus a bit and it will know the slave was already idle, or the timeout occurred and it reset the TWI making it idle again.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got a couple of AVR's using their TWI interface to talk to each other.

ISSUE # 1 - In TWI1.png below, it has a stop/start, but in TWI2.png below, I did not get the stop?  It is the same code run again and again.

 

      case TWI_MTX_ADR_ACK: //0x18
      case TWI_MTX_DATA_ACK: //0x28
        //do we have more to send?
        if (TWIPos<PROTOCOL_SIZE)
          {
            //yes, transmit byte
            TWDR=RxBuffer[TWIPos++];
            TWCR=_BV(TWEN) | _BV(TWIE) | _BV(TWINT);
          }
        else
          {
            //send stop
            TWCR=_BV(TWEN) | _BV(TWINT) | _BV(TWSTO);
            TWIState=TWISTATE_SENT;
          }
        break;

 

ISSUE # 2 - Also in TWI1.png I put a square around a glitch that shows up in many of the bytes sent to the slave.  I don't think it affects anything, but is this when one device is turning off and allowing the other to ack/nak it?  I see this tiny little glitch on many of the tx bytes.  Actually it is on the RX bytes too.  Happens during the fall of the clock though and I only think it is sampled on the rise.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I figured out the stop issue.  Apparently there is no TWINT to count on with a status code saying that the stop was successfully sent.  You need to check the TWSTO bit to make sure it is clear before trying to sent a start too quickly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, just checking but you are using the Fleury code as a template for what you are trying to achieve? As far as I know the Fleury implementation is faultless so it shows how it should be done. When something doesn't work in your own code compare against Fleury to see how what is done there differs.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:

I figured out the stop issue.  Apparently there is no TWINT to count on with a status code saying that the stop was successfully sent.  You need to check the TWSTO bit to make sure it is clear before trying to sent a start too quickly.


Yes, that is how you wait for i2c_stop() completion.
EEPROMs and certain other I2C devices will not ACK their Slave address when they are busy e.g. doing a Page Write.
You must always check i2c_start() for ACK before attempting any comms.
.
@Cliff,
Fleury is an excellent example of a polled Master. It has intuitive functions which return error status.
.
Fleury is no good for interrupt Slave or interrupt Master.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I based them on the AVR311/315.  They are working beautifully now, but they were lacking timeouts that would trigger if the TWINT interrupt was not called in a specific time, so I added that to take the interface back to a known reset state if something goes wrong.