Pregunta

I've read through the Linux kernel documents on i2c and written a code to try to replicate the command i2cset -y 0 0x60 0x05 0xff

The code that I've written is here:

#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>

int main(){

 int file;    
 file = open("/dev/i2c-0", O_RDWR);
 if (file < 0) {
  exit(1);
 }

 int addr = 0x60;

 if(ioctl(file, I2C_SLAVE, addr) < 0){
 exit(1);
 }

__u8 reg = 0x05;
__u8 res;
__u8 data = 0xff;

int written = write(file, &reg, 1); 
printf("write returned %d\n", written);

written = write(file, &data, 1); 
printf("write returned %d\n", written);

}

When I compile and run this code I get: write returned -1
write returned -1

I've tried to follow exactly what the docs tell me, my understanding is that the address is set first with the call to ioctl, then I need to write() the register and then the data that I want sent to the register.

I've also tried to use use SMbus, but I can't get my code to compile using this, it complains at the linking stage that it can't find the functions.

Have I made any mistakes in this code? I'm a beginner to i2c and don't have a lot of experience with c either.

EDIT: errno give the following message: Operation not supported. I am logged in as root on this machine though, so I don't think it can be a permissions thing, although I may be wrong.

¿Fue útil?

Solución

The way I got around this problem was to use SMBus, in particular the functions i2c_smbus_write_byte_data and i2c_smbus_read_byte_data. I was able to use these functions to successfully read and write to the device.

I did have a little trouble finding these functions, I kept trying to download libraries using apt-get to install the appropriate header files. In the end I simply downloaded the files smbus.c and smbus.h.

Then the code I needed was:

#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "smbus.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>


int main(){

int file;     
file = open("/dev/i2c-0", O_RDWR);
if (file < 0) {
    exit(1);
}

int addr = 0x60;

if(ioctl(file, I2C_SLAVE, addr) < 0){
    exit(1);
}

__u8 reg = 0x05; /* Device register to access */
__s32 res;

res = i2c_smbus_write_byte_data(file, reg, 0xff);
close(file);
}

Then if I compile the smbus.c file: gcc -c smbus.c and myfile: gcc -c myfile.c, then link them: gcc smbus.o myfile.o -o myexe I get a working executable that runs my I2C command. Ofcourse, I have smbus.c and smbus.h in the same directory as myfile.c.

Otros consejos

In C, you can check the content of the errno variable to get more details into what went wrong. It is automatically declared when including errno.h and you can get a more descriptive text by calling strerror(errno).

Have you checked that you had write access to /dev/i2c-0 ?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top