linux i2c ile istenilen adresten data okuma yada yazma

Başlatan sseedat, 19 Temmuz 2014, 22:47:00

sseedat

merhaba arkadaşlar linux i2c ile slave bir cihazın istediğim adresine nasıl veri yazıp okuyabilirim

Görünmez bir mezarlıktır Zaman...

mehmet

Normalde pc nin kendi sensorleri için lm_sensors paketi mevcut. Ancak
i2cdetect, i2cget, i2cset gibi komutlar da kullanılabilmekte...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

sseedat

i2cset ile konsoldan istediğim yere veri yazabiliyorum fakat benim istediğim c codları içinde write,read gibi fonksiyonlarla yazmak

   char buff[16]={0};
   buff[0]=0x03;  //adres
   buff[1]=8;       //data
//    buff[2]=ConvertDecimalToHex(0x80);
//    buff[3]=0;
//    buff[4]=0;
//    buff[5]=0;
//    buff[6]=0;
//    buff[7]=0;


   sprintf(busPath,"/dev/i2c-%d",I2C_BUS);

   if((fd=open(busPath,O_WRONLY))<0)
   {
      perror("cannot open i2c");
      exit(0);
   }

   if((fd=ioctl(fd,I2C_SLAVE,WDEVICE_ADRESS>>1))<0)
   {
      perror("ioctl");
      exit(0);
   }
   write(fd,buff,2);
   close(fd);

burda write ile önce adresi gönderip ardından datayı göndermek fakat bir türlü slave cihaza veri yazamadım.
Görünmez bir mezarlıktır Zaman...

mehmet

İlgili cihazın katakoğundan nasıl yazılır nasıl
okunur bunu öğrenmelisiniz öncelikle. Yazmak ve
okumak için belli işlemleri yapmanız gerekmekte...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

sseedat

kataloğa göre  slave adres + register adres + data şeklinde bende o şekilde veri yolluyorum fakat olmuyor nedense.

slave cihaz PCF8563 RTC entegresi karmaşık birşey de değil aslında
Görünmez bir mezarlıktır Zaman...

mehmet

ACK, NACK bunlarda olmalı.
Pc bağlantınızı nasıl yaptınız...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

aykuto

Ben aşağıdaki fonksiyonları kullanıyorum. Kendi yazılımım içinden kopyalayarak aldım, derlemeyi tekrar deneyemedim.

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

int main(void)
{
  int f;
  unsigned char slaveadr;
  unsigned char reg;
  unsigned char val;

   f = open("/dev/i2c-0", O_RDWR);
   slaveadr=0x18;
   reg=0x20;
   val=0x47;
   set_i2c_register(f,slaveadr,reg,val);

   val=0;
   get_i2c_register(f,slaveadr,reg,&val);

   printf("Okunan deger:%d\r\n",val);
   close(f);
}

static int set_i2c_register(int file,
                            unsigned char addr,
                            unsigned char reg,
                            unsigned char value) {

    unsigned char outbuf[2];
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[1];

    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = outbuf;

    /* The first byte indicates which register we'll write */
    outbuf[0] = reg;

    /* 
     * The second byte indicates the value to write.  Note that for many
     * devices, we can write multiple, sequential registers at once by
     * simply making outbuf bigger.
     */
    outbuf[1] = value;

    /* Transfer the i2c packets to the kernel and verify it worked */
    packets.msgs  = messages;
    packets.nmsgs = 1;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Unable to send data");
        return 1;
    }

    return 0;
}


static int get_i2c_register(int file,
                            unsigned char addr,
                            unsigned char reg,
                            unsigned char *val) {
    unsigned char inbuf, outbuf;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];

    /*
     * In order to read a register, we first do a "dummy write" by writing
     * 0 bytes to the register we want to read from.  This is similar to
     * the packet in set_i2c_register, except it's 1 byte rather than 2.
     */
    outbuf = reg;
    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = &outbuf;

    /* The data will get returned in this structure */
    messages[1].addr  = addr;
    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
    messages[1].len   = sizeof(inbuf);
    messages[1].buf   = &inbuf;

    /* Send the request to the kernel and get the result back */
    packets.msgs      = messages;
    packets.nmsgs     = 2;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Unable to send data");
        return 1;
    }
    *val = inbuf;

    return 0;
}