i2c 16位寄存器的读写


/* Ensure address is not busy */
int set_slave_addr(int file, int address, int force)
{
	/* With force, let the user read from/write to the registers
	   even when a driver is also running */
	if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {
		fprintf(stderr,
			"Error: Could not set address to 0x%02x: %s\n",
			address, strerror(errno));
		return -errno;
	}

	return 0;
}

/*

	reg_addr: 16 bits register address
	flags: 0 only write
		   1 read register data
	val_buf:
		if flag==0
			val is send data buf
		if flag==1
			val is recv data buf
	cnt:the counter you want to read or write
*/

int i2c_transfer_16bits
(const char *i2c_dev,unsigned char i2c_dev_addr,unsigned long reg_addr,int flags,unsigned char *val_buf,size_t cnt)
{
	int i=0;
	int flag=flags;
	int file=-1;
	int nmsgs=0;
	int nmsgs_sent=0;
	struct i2c_rdwr_ioctl_data rdwr;
	//struct i2c_msg msgs[I2C_RDWR_IOCTL_MAX_MSGS];
	struct i2c_msg msgs[2];
	char *buf;

	for (i = 0; i < 2; i++)
		msgs[i].buf = NULL;

	file=open(i2c_dev,O_RDWR);
	if(file<0){
		printf("open %s failed\n",i2c_dev);
		return -1;
	}

	if(flags==0){
		msgs[nmsgs].addr = i2c_dev_addr;
		msgs[nmsgs].flags = 0;/*write flag*/
		msgs[nmsgs].len = 2+cnt;
		msgs[nmsgs].buf=malloc(msgs[nmsgs].len);/*buf alloc according to len*/
		msgs[nmsgs].buf[0]=(unsigned char)(reg_addr>>8);
		msgs[nmsgs].buf[1]=(unsigned char)(reg_addr&0x00ff);
		if(cnt==0||cnt>2){
			printf("cnt[%d] is error\n",cnt);
			goto err_out;
		}
		if(cnt==1)
			msgs[nmsgs].buf[2]=val_buf[0];
		if(cnt==2){
			msgs[nmsgs].buf[2]=val_buf[0];
			msgs[nmsgs].buf[3]=val_buf[1];
		}
		goto write_to_reg;
	}

	if(flags==1){
		msgs[nmsgs].addr = i2c_dev_addr;
		msgs[nmsgs].flags = 0;/*write flag*/
		msgs[nmsgs].len = 2;
		msgs[nmsgs].buf=malloc(msgs[nmsgs].len);/*buf alloc according to len*/
		msgs[nmsgs].buf[0]=(unsigned char)(reg_addr>>8);
		msgs[nmsgs].buf[1]=(unsigned char)(reg_addr&0x00ff);
	}

	nmsgs++;

/*perpare read buf*/
	msgs[nmsgs].addr = i2c_dev_addr;
	msgs[nmsgs].flags = 1; /*read flag*/
	msgs[nmsgs].len=cnt;
	buf=malloc(msgs[nmsgs].len);/*buf alloc according to len*/
	memset(buf,0,cnt);
	msgs[nmsgs].buf=buf;
/*perpare read buf*/

write_to_reg:
	rdwr.msgs = msgs;
	rdwr.nmsgs = nmsgs+1;/*if read rdwr.nmsgs==2,eles if write rdwr.nmsgs==1*/

#if 1
	int k=0;
	int f=0;

	printf("%s(%d) nmsgs %d\n",__func__,__LINE__,nmsgs);
	for(f=0;f<rdwr.nmsgs;f++){
		printf("%s(%d) addr %d\n",__func__,__LINE__,msgs[f].addr);
		printf("%s(%d) flags %d\n",__func__,__LINE__,msgs[f].flags);
		printf("%s(%d) len %d\n",__func__,__LINE__,msgs[f].len);
		for(k=0;k<msgs[f].len;k++)
			printf("%s(%d) buf 0x%02x \n",__func__,__LINE__,msgs[f].buf[k]);
		printf("\n");
	}
#endif

	nmsgs_sent = ioctl(file, I2C_RDWR, &rdwr);
	if(nmsgs_sent<0)
		goto err_out;
	else if(nmsgs_sent<nmsgs){
		printf("Warning: only %d/%d messages were sent\n", nmsgs_sent, nmsgs);
		goto err_out;
	}

	printf("flag %d cnt %d\n",flag,cnt);

	if(flag==1){
		for(i=0;i<cnt;i++){
			printf("msgs[%d].buf[%d] 0x%02x \n",nmsgs,i,msgs[nmsgs].buf[i]);
			val_buf[i]=msgs[nmsgs].buf[i];
			//printf("val_buf[%d] 0x%02x \n",i,val_buf[i]);
			//memcpy(val_buf+i,msgs[nmsgs].buf+i,1);
		}
	}


	close(file);
	for (i = 0; i <= nmsgs; i++)
		free(msgs[i].buf);

	return 0;


err_out:
	close(file);
	for (i = 0; i <= nmsgs; i++)
		free(msgs[i].buf);
	return -1;
}

这个代码是参考i2c-tools中i2c_transfer的源码的

其中最重要的是

struct i2c_msg msgs[2];

这个结构体数组

根据结构体中的flags元素来决定这次操作是读还是写

如果flags是0,那说明只是写数据到i2c寄存器中,这个时候第二组结构体就可以不用了

如果flags是1,说明是读寄存器,第一组结构体就是用来写要读的寄存器地址,第二组就是用来保存读到的数据(实际上读的过程是包括写的,才能让i2c设备知道要去哪个地址读数据)

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值