Help With I2C

Non-technical related questions should go here.
User avatar
rp181
Respected Member
Posts: 395
Joined: Tue May 18, 2010 12:25 am

Help With I2C

Postby rp181 » Thu Jun 03, 2010 8:55 pm

I am trying to get the HMC5843 to work. The magnetometer is an I2C device, and i have never used I2C before. I found an arduinio library for this sensor, and it does this:

Code: Select all

void HMC5843::init()
{
  PORTC = 0b00110000; // Use the internal pull up resistors
  
  // Choose 100KHz for the bus.  Formula from 21.5.2 in ATmega168 datasheet.
  TWSR &= ~((1<<TWPS1)&(1<<TWPS0));
	TWBR = (unsigned char)(F_CPU/200000l-8);
	
	// Put the HMC5843 into continuous mode
	sendStart();
	sendByte(0x3C);
	sendByte(0x02);
	sendByte(0x00);
	sendStop();
	// note that you need to wait 100ms after this before first calling recieve
}

Code: Select all

void HMC5843::sendStart(void)
{
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
}

// close i2c
void HMC5843::sendStop(void)
{
  waitForReady();
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

// send a byte when the channel is ready
void HMC5843::sendByte(unsigned char data)
{
  waitForReady();
	TWDR = data;
	TWCR = (1<<TWINT)|(1<<TWEN);
}

Code: Select all

void HMC5843::getValues(int *x, int *y, int *z)
{
  unsigned char xin, yin, zin;
  // start the reading
  sendStart();
  sendByte(0x3D);
  // read out the 3 values, 2 bytes each.  lsb first, then msb.
  xin = receiveByte();
  *x = (xin<<8)|receiveByte();
  yin = receiveByte();
  *y = (yin<<8)|receiveByte();
  zin = receiveByte();
  *z = (zin<<8)|receiveByte();
  // wrap back around for the next set of reads and close
  sendByte(0x3D);
  sendStop();
}
How do i replicate this with XC?
User avatar
Andy
Respected Member
Posts: 279
Joined: Fri Dec 11, 2009 1:34 pm

Postby Andy » Thu Jun 03, 2010 9:25 pm

Hi,

Have you had a look at the I2C code on the XMOS website?

http://www.xmos.com/applications/module/i2c

It might be a good starting point.
User avatar
rp181
Respected Member
Posts: 395
Joined: Tue May 18, 2010 12:25 am

Postby rp181 » Thu Jun 03, 2010 10:12 pm

Yes, that is the module I am using.

In the library, it says "sendStart". What does that do?
(TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

Also, the library asks for the address everytime, whereas this arduino library sends the address only once, then commands. Whats the difference?
User avatar
lilltroll
XCore Expert
Posts: 955
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Postby lilltroll » Thu Jun 03, 2010 10:14 pm

Do not forget that you need external pull-up resistors around 2.2 kOhms (if it's not already present on the camera board) using I2C.
Probably not the most confused programmer anymore on the XCORE forum.
User avatar
rp181
Respected Member
Posts: 395
Joined: Tue May 18, 2010 12:25 am

Postby rp181 » Thu Jun 03, 2010 10:49 pm

This is for the HMC5843, not camera.
Pull up resistors are needed, thanks!
I am still not getting the code though.
User avatar
lilltroll
XCore Expert
Posts: 955
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Postby lilltroll » Fri Jun 04, 2010 12:43 am

Each transmission should start with the I2C address; since several devices can be on the same serial bus.
Here is an U(t) display on how a I2C transmission with XMOS might look like with the I2C code.
I did it when I was tracking down communication problem with the XAI board, that I first thought was due to a I2C problem, but it later showed that is happened because of a non-existing reset.

http://www.xcore.com/forum/download/file.php?id=189
Probably not the most confused programmer anymore on the XCORE forum.
kster59
XCore Addict
Posts: 162
Joined: Thu Dec 31, 2009 8:51 am

Postby kster59 » Fri Jun 04, 2010 6:48 am

You should probably start with something more basic like reading the datasheet and reading how I2C works.

Almost every interface will have 4 basic commands:
openPort(deviceID)
readFromPort
WriteToPort
closePort(deviceID)

these are the same as opening a file with fopen/fread/fwrite/fclose.

An ideal library will allow you abstract the communication and write to the device regardless of the underlying protocol but the XMOS libraries in general are not very good in terms of documentation. Probably good enough to get an idea how it works but little chance you can just use it with no other knowledge.

However, every I2C or SPI device is going to have a different init command/parameters so you will still need to read the datasheet.

It is obvious to me that the Arduino object has writes to some MCU registers to open communication with the peripheral then sends an init string to set up some registers in the device. That one line you pointed to is probably flipping some bits in the MCU register to set the baud rate, etc.

It is one of my complaints that the XMOS libraries are difficult to use with few comments and very verbose code oftening mixing C/ASM and Xc.

It would be nice if someone figured out a standard template and good documentation to make use of the library functions.
rp181 wrote:Yes, that is the module I am using.

In the library, it says "sendStart". What does that do?
(TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

Also, the library asks for the address everytime, whereas this arduino library sends the address only once, then commands. Whats the difference?

Who is online

Users browsing this forum: No registered users and 1 guest