merhaba arkadaşlar linux i2c ile slave bir cihazın istediğim adresine nasıl veri yazıp okuyabilirim
Normalde pc nin kendi sensorleri için lm_sensors paketi mevcut. Ancak
i2cdetect, i2cget, i2cset gibi komutlar da kullanılabilmekte...
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.
İ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...
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
ACK, NACK bunlarda olmalı.
Pc bağlantınızı nasıl yaptınız...
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;
}