Help With I2C

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

Help With I2C

Post by rp181 »

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

Post by Andy »

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
Contact:

Post by rp181 »

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: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

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
Contact:

Post by rp181 »

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: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

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

Post by kster59 »

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?
Post Reply