Pages: [1]   Go Down
Author Topic: Custom I2C Library  (Read 1792 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 33
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I took it on myself to develop a master transmit / receive library for the two wire interface (I2C).  Then port this to an interrupt service routine.

I've made good progress.  However, I cannot quite seem to figure out how to setup the bus.  Problem is this.  If I include the wire.h library my code works.  I don't even have to call any functions from the library.  Just include it.  However, if I do not include wire.h the slave will not acknowledge SLA (slave address).

Can any body see what I'm missing to setup the bus?  Here's my initialization code:

void setup()
{
  Serial.begin(9600);
  
  // Init I2C  
  PORTC |= 0x18;      // Connect Pull-Up resistors
  TWSR &= 0xF9;       // Set bit rate prescalar (p239)
  TWBR = 0x0a;        // Set two wire bit rate
  TWCR = (1 << TWEN); // Enable I2C
}

Logged

Brisbane, Australia
Offline Offline
God Member
*****
Karma: 1
Posts: 593
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'd take a look at the .h file. It will be something in there.
Logged

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Quote
I took it on myself to develop a master transmit / receive library for the two wire interface (I2C).  Then port this to an interrupt service routine.
What is wrong with the Wire-lib, I think it does exactly what you want to do?
It can act as a Master, and a Slave. See the index for topic TWI here
http://wiring.org.co/learning/index.html

Quote
Problem is this.  If I include the wire.h library my code works.  I don't even have to call any functions from the library.  Just include it.  
The Wire-lib installs an Interrupt-service routine for receiving data,maybe that interfers with your code?

Eberhard Fahle
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 33
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm having trouble getting low level help with the TWI interface.  So I think I'll have to use the wire library.  I never got far enough on my own to implement an ISR.  

My code will transmit and receive.  The receive routine matches the implementation example in the Atmel data sheet.  However, if I loop it, the code crashes after so many iterations.  If I loop the wire implementation it never crashes.

I'm wondering if it's a setup issue.  The data sheet is rather lacking in that respect.

Here's the full code:

#include <Wire.h>

#define DEBUG
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22

void setup( void )
{
  Serial.begin(9600);
  
  // Init I2C  
  PORTC |= 0x18;       // Connect Pull-Up resistors
  TWSR  &= 0xF8;       // Set bit rate prescalar (p239)
  TWBR  =  0x0a;       // Set two wire bit rate
  TWCR  =  (1 << TWEN);// Enable I2C
}

void loop( void )
{
  int i = 0;

  while(1)
  {
    Serial.print( "#: " );
    Serial.print( i );
    
    start();
    TX( 0x3A );
    TX( 0x0F );
    start();
    TX( 0x3B );
    RX();
    stop();

    Serial.print( " D: " );
    Serial.println( TWDR, HEX );
 
    i++;
    
    delay( 1000 );
  }
}

void start()
{
  // ******* Send Start Sequence
  /* TWINT - Clear Interrupt Flag
     TWSTA - Transmit start
     TWEN  - Enable I2C Bus
     TWEA  - Enable Acknoledge */
  TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA) | (1 << TWEA);
  while( !(TWCR & (1 << TWINT) ) );
  
  #if defined DEBUG
    Serial.print( "STA:" );
    Serial.println( TWSR, HEX );
  #endif
}

void TX( byte data )
{
  // *******  Send register address
  TWDR = data;
  /* TWINT - Clear Interrupt Flag
     TWEN  - Enable I2C Bus
     TWEA  - Enable Acknoledge */
  TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN);
  while( !(TWCR & (1 << TWINT) ) );

  #if defined DEBUG
    Serial.print( "TX: " );
    Serial.println( TWSR, HEX );
  #endif
}

void RX()
{
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
  while( !(TWCR & (1 << TWINT) ) );

  #if defined DEBUG
    Serial.print( "RX: " );
    Serial.println( TWSR, HEX );
  #endif  
}
void stop( void )
{  
  TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWINT) | (1 |TWSTO);  
  while( TWCR & (1 << TWINT) );
  
  #if defined DEBUG
    Serial.print( "STO:" );
    Serial.println( TWSR, HEX );
  #endif
}
« Last Edit: February 22, 2008, 08:41:20 am by weinerschizel » Logged

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Quote
I'm having trouble getting low level help with the TWI interface.  So I think I'll have to use the wire library.  
Good idea. I havn't seen any complaints about the the Wire-lib around here. so it seems to be working fine for most people.
Quote
I never got far enough on my own to implement an ISR.  
I don't think you could write a library for the TWI without using Interrupts. (the Wire-sources provide a good example how to do this :-) )


Sorry, I did not go through your code maybe someone else will do that...
Eberhard
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 33
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah you can write a library for the I2C not using interrupts but polling instead.  Going through the Wire library code I see polling all over the place.  However, I'm not able to completely figure out their mnemonics so I don't know exactly what they are polling.

I was going to trigger a state machine off the TWI interrupt bit.  Then the machine would transmission based off of the Status Register.  There would be a TX buffer and RX buffer to queue the data in.  However, I could not get the TWI port to setup correctly.

My motivation for this was to streamline the code as much as possible.  I would like to try and read a GPS as well as emulate a USB port on the same microprocessor.  So I'll need every scrap of power and space I can muster up.

I'm working to make an inertial referencing circuit that saves it's data on a thumb drive.  If there's any space left over I'll also implement a CAN sniffer so I can capture ECU data off a car to the thumb drive as well.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the Wire library with Arduino and am running into a huge problem. If I request data from devices not on the bus, they reply with the data of the last successful response from a device actually one the bus.

Has anyone run into this problem? Is this a problem with the implementation of the library or an intended design decision.

Is there a way to set the response of a device not yet on the bus? Surely there must be a way around this.
« Last Edit: February 29, 2008, 09:33:37 pm by alexabreu » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 33
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like the data buffer doesn't get cleared.  Makes since.  Looking at the wire library I didn't see anywhere where they did do this.  But the library is kind of overwhelming so I could have missed something.
Logged

Pages: [1]   Go Up
Jump to: