Date: Thu, 1 Dec 2016 10:11:04 +0000 From: Nick Hibma <Nick@ip-knowhow.com> To: =?Windows-1252?Q?=93FreeBSD_Embedded_Mailing_List=94?= <freebsd-embedded@FreeBSD.org> Subject: Questions about i2c.c (TMP102 temperature sensor) Message-ID: <9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE@ip-knowhow.com>
next in thread | raw e-mail | index | archive | help
Gents, I am not quite sure who to owner of i2c.c is, so perhaps some I2C enthousia= st could help me with the following problem. I was trying to access a TMP102 I2C temperature sensor. It kind of works wi= th the default i2c utility. But it returns twice the high byte instead of t= he high and low byte for the temperature. Probably because it does 1 byte r= eads on the I2C bus, sending a stop condition after every byte. This was ve= rified with a logic analyser. The device expects continuous reads and no stop/start in between the 2 byte= s. Trying all options i2c, most notably the -m mode switch, yields the same= results all the time. Looking at the code in i2c.c I get confused as it s= eems to somehow fiddle with start/stop to get it right because of the -m sw= itch, but uses read() in the end to get the data, not I2CREAD. fd =3D open(dev, O_RDWR); if (i2c_opt.width) { error =3D ioctl(fd, I2CSTART, &cmd); error =3D ioctl(fd, I2CWRITE, &cmd); if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { error =3D ioctl(fd, I2CSTOP, &cmd); } } if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { error =3D ioctl(fd, I2CSTART, &cmd); } else if (i2c_opt.mode =3D=3D I2C_MODE_REPEATED_START) { error =3D ioctl(fd, I2CRPTSTART, &cmd); } /******** Without i2c_opt.width set there is no START condition either to s= et the slave address for the read() ****/ /******** Why this stop? ***/ error =3D ioctl(fd, I2CSTOP, &cmd); for (i =3D 0; i < i2c_opt.count; i++) { error =3D read(fd, &i2c_buf[i], 1); } close(fd); I would have expected: fd =3D open(dev, O_RDWR); if (i2c_opt.width) { error =3D ioctl(fd, I2CSTART, &cmd); error =3D ioctl(fd, I2CWRITE, &cmd); if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { error =3D ioctl(fd, I2CSTOP, &cmd); error =3D ioctl(fd, I2CSTART, &cmd); } else if (i2c_opt.mode =3D=3D I2C_MODE_REPEATED_START) { error =3D ioctl(fd, I2CRPTSTART, &cmd); } } else { /***** Use START/STOP to set the slave address for the read() below ***/ error =3D ioctl(fd, I2CSTART, &cmd); error =3D ioctl(fd, I2CSTOP, &cmd); } error =3D ioctl(fd, I2CREAD, &cmd); // read all bytes in one go error =3D ioctl(fd, I2CSTOP, &cmd); close(fd); Any opinions on where I am wrong? Second question: Rolling my own little program with this change fails because I cannot get I= 2CREAD to work. It keeps returning EIO. Some other web pages claim that the= re is an implementation problem with that. Using read() on the fd works fin= e, so do get a valid temperature out of the device now. Cheers, Nick Hibma -- ip-knowhow E: nick@ip-knowhow.com<mailto:nick@ip-knowhow.com> T: +31 (0)85 2010923 M: +31 (0)6 14433161
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE>