我是靠谱客的博主 傻傻哈密瓜,最近开发中收集的这篇文章主要介绍Zynq-Linux移植学习笔记之43-linux下应用读写I2C设备,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在读写I2C设备时,由于I2C地址分为7bit和10bit,读写时序存在区别,因此应用程序也存在区别。

首先来看读写时序对比,这里以写为例:

可以看出从设备地址分成了两次进行传输。

于是应用程序可以这样修改。

首先是7位模式下对某设备寄存器的读写:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>
int higher2lower(char c);
int htoi(char s[]);
#define MSB_0_7_OF_U32(DATA) ((DATA >> 24) & 0xFF)
#define MSB_8_15_OF_U32(DATA) ((DATA >> 16) & 0xFF)
#define MSB_16_23_OF_U32(DATA) ((DATA >> 8) & 0xFF)
#define MSB_24_31_OF_U32(DATA) ((DATA >> 0) & 0xFF)
#define REG_VAL_32_BIT(VAL_8_BIT_0, VAL_8_BIT_1, VAL_8_BIT_2, VAL_8_BIT_3) 
		((VAL_8_BIT_0 << 24) | (VAL_8_BIT_1 << 16) | (VAL_8_BIT_2 << 8) | VAL_8_BIT_3)


//this is i2c 7-bit
int main1(int argc, char *argv[]) 
{ 
	int fd, i, j, ret; 
	char *errorinfo;			 
	struct i2c_rdwr_ioctl_data work_queue;
	unsigned int i2c_adaptor, slave_address, reg_address, byte_count, reg_val, format_cetc, reg_num, rw_flag;
	unsigned char val;

//	access_tran access;
	i2c_adaptor = 0;
	slave_address = htoi(argv[1]);
	reg_address = htoi(argv[2]);
	reg_val = htoi(argv[3]);
	rw_flag = htoi(argv[4]);
	printf("i2c_adaptor : %#xnslave_address : %#xnreg_address : %#xnreg_val : %#xnrw_flag : %#xn", 
				i2c_adaptor, slave_address, reg_address, reg_val, rw_flag);

	fd = open("/dev/i2c-1", O_RDWR);

	if(!fd)
	{
		printf("Error on opening the device filen");
		return 0;
	}
	
	//IIC configuration
	ioctl(fd, I2C_TIMEOUT, 2);
	ioctl(fd, I2C_RETRIES, 1);

	/*
	 * IIC operation
	 * rw_flag = 1; READ
	 * rw_flag = 0; WRITE
	 */
	if(rw_flag)
	{
		work_queue.nmsgs = 2;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));

		if(!work_queue.msgs)
		{
			printf("memory alloc errorn");
			close(fd);
			return 0;
		}

		reg_num = 1;	
		format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		printf("format_cetc : %#xn", format_cetc);
		(work_queue.msgs[0]).len = 4;
		(work_queue.msgs[0]).addr = slave_address;
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(4);
		(work_queue.msgs[0]).buf[0] = MSB_0_7_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[1] = MSB_8_15_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[2] = MSB_16_23_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[3] = MSB_24_31_OF_U32(format_cetc);
//		(work_queue.msgs[0]).buf[3] = MSB_0_7_OF_U32(format_cetc);
//		(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
//		(work_queue.msgs[0]).buf[1] = MSB_16_23_OF_U32(format_cetc);
//		(work_queue.msgs[0]).buf[0] = MSB_24_31_OF_U32(format_cetc);
	//	(work_queue.msgs[0]).buf[0] = MSB_16_23_OF_U32(reg_address);
	//	(work_queue.msgs[0]).buf[1] = MSB_24_31_OF_U32(reg_address);

		(work_queue.msgs[1]).len = 4;
		(work_queue.msgs[1]).flags = I2C_M_RD;//R
		(work_queue.msgs[1]).addr = slave_address;
		(work_queue.msgs[1]).buf = (unsigned char *)malloc(4);
		
		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		reg_val = REG_VAL_32_BIT(work_queue.msgs[1].buf[0], work_queue.msgs[1].buf[1], 
						work_queue.msgs[1].buf[2], work_queue.msgs[1].buf[3]);
		if(ret < 0)
		  printf("error code : %dn", ret);
		else
		  printf("slave_addr : %#x  reg_addr : %#x  reg_val : %#xn", slave_address, reg_address, reg_val);
		free(work_queue.msgs);
	}
	else
	{
		work_queue.nmsgs = 1;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
		printf("work_queue.msgs addr* : %#xn", (unsigned int*)work_queue.msgs);

		if(!work_queue.msgs)
		{
			printf("memory alloc errorn");
			close(fd);
			return 0;
		}
		reg_num = 1;	
		format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		printf("format_cetc : %#xn", format_cetc);
		(work_queue.msgs[0]).len = 8;//reg_addr 4 + reg_val 4
		(work_queue.msgs[0]).addr = slave_address;
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(8);
		(work_queue.msgs[0]).buf[0] = MSB_0_7_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[1] = MSB_8_15_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[2] = MSB_16_23_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[3] = MSB_24_31_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[4] = MSB_0_7_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[5] = MSB_8_15_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[6] = MSB_16_23_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[7] = MSB_24_31_OF_U32(reg_val);

		
		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		if(ret < 0)
		  printf("error code : %dn", ret);
		free(work_queue.msgs);
	}

	close(fd);
	return ret;
} 
																	
int higher2lower(char c)
{
	if(c >= 'A' && c <= 'Z')
		return c + 'a' - 'A';
	else
	  return c;
}

int htoi(char s[])
{
	int i;
	int n = 0;
	if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
	  i = 2;
	else
	  i = 0;

//	if((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') 
			|| (s[i] >= 'A' && s[i] <= 'F'))
//	{
	for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') 
			|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
	{
		if(higher2lower(s[i] > '9'))
		{
			n = 16 * n +(10 + higher2lower(s[i]) - 'a');
		}
		else
		  n = 16 * n + (higher2lower(s[i] - '0'));
	}
//	}
	return n;
}

然后是10位模式下对寄存器的读写

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>
int higher2lower(char c);
int htoi(char s[]);
#define MSB_0_7_OF_U32(DATA) ((DATA >> 24) & 0xFF)
#define MSB_8_15_OF_U32(DATA) ((DATA >> 16) & 0xFF)
#define MSB_16_23_OF_U32(DATA) ((DATA >> 8) & 0xFF)
#define MSB_24_31_OF_U32(DATA) ((DATA >> 0) & 0xFF)
#define REG_VAL_32_BIT(VAL_8_BIT_0, VAL_8_BIT_1, VAL_8_BIT_2, VAL_8_BIT_3) 
		((VAL_8_BIT_0 << 24) | (VAL_8_BIT_1 << 16) | (VAL_8_BIT_2 << 8) | VAL_8_BIT_3)

int main(int argc, char *argv[])
{
	int fd, i, j, ret;
	char *errorinfo;
	struct i2c_rdwr_ioctl_data work_queue;
	unsigned int i2c_adaptor, slave_address, reg_address, byte_count, reg_val, format_cetc, reg_num, rw_flag;
	unsigned char val;
	unsigned int baseadd=0;
	unsigned int value[2];
	unsigned int offset[3]={0};
	unsigned int num[3]={0};

//	access_tran access;
	i2c_adaptor = 1;
	slave_address = htoi(argv[1]);
	baseadd = htoi(argv[2]);
	reg_val = htoi(argv[3]);
	rw_flag = htoi(argv[4]);
	reg_address=baseadd;

	value[1]=slave_address&0xff;
	value[0]=((slave_address&0x300)>>8)|0x78;

	fd = open("/dev/i2c-1", O_RDWR);

	if(!fd)
	{
		printf("Error on opening the device filen");
		return 0;
	}

	//IIC configuration
	ioctl(fd, I2C_TIMEOUT, 2);
	ioctl(fd, I2C_RETRIES, 1);

	/*
	 * IIC operation
	 * rw_flag = 1; READ
	 * rw_flag = 0; WRITE
	 */
	if(rw_flag)
	{
		work_queue.nmsgs = 2;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));

		if(!work_queue.msgs)
		{
			printf("memory alloc errorn");
			close(fd);
			return 0;
		}

		reg_num = 1;
		format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		(work_queue.msgs[0]).len = 5;
		(work_queue.msgs[0]).addr = value[0];
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(5);
		(work_queue.msgs[0]).buf[0]=value[1];
		(work_queue.msgs[0]).buf[1] = MSB_0_7_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[3] = MSB_16_23_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[4] = MSB_24_31_OF_U32(format_cetc);


		(work_queue.msgs[1]).len = 4*reg_num;
		(work_queue.msgs[1]).flags = I2C_M_RD;//R
		(work_queue.msgs[1]).addr = value[0];
		(work_queue.msgs[1]).buf = (unsigned char *)malloc(4*reg_num);

		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		reg_val = REG_VAL_32_BIT(work_queue.msgs[1].buf[0], work_queue.msgs[1].buf[1], 
						work_queue.msgs[1].buf[2], work_queue.msgs[1].buf[3]);
		if(ret < 0)
		{
			printf("error code : %dn", ret);
		}
		else
		{
			printf("slave_addr : %#x  reg_addr : %#x  reg_val : %#xn", slave_address, reg_address, reg_val);
		}
		free(work_queue.msgs);
	}
	else
	{
		work_queue.nmsgs = 1;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
		printf("work_queue.msgs addr* : %#xn", (unsigned int*)work_queue.msgs);

		if(!work_queue.msgs)
		{
			printf("memory alloc errorn");
			close(fd);
			return 0;
		}
		reg_num = 1;
		format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		(work_queue.msgs[0]).len = 9;//reg_addr 4 + reg_val 4
		(work_queue.msgs[0]).addr = value[0];
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(9);
		(work_queue.msgs[0]).buf[0]=value[1];
		(work_queue.msgs[0]).buf[1] = MSB_0_7_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[3] = MSB_16_23_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[4] = MSB_24_31_OF_U32(format_cetc);
		(work_queue.msgs[0]).buf[5] = MSB_0_7_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[6] = MSB_8_15_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[7] = MSB_16_23_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[8] = MSB_24_31_OF_U32(reg_val);


		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		if(ret < 0)
		{
			printf("error code : %dn", ret);
		}
		free(work_queue.msgs);
	}
	close(fd);
	return ret;
}

int higher2lower(char c)
{
	if(c >= 'A' && c <= 'Z')
		return c + 'a' - 'A';
	else
	  return c;
}

int htoi(char s[])
{
	int i;
	int n = 0;
	if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
	  i = 2;
	else
	  i = 0;

//	if((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') 
			|| (s[i] >= 'A' && s[i] <= 'F'))
//	{
	for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') 
			|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
	{
		if(higher2lower(s[i] > '9'))
		{
			n = 16 * n +(10 + higher2lower(s[i]) - 'a');
		}
		else
		  n = 16 * n + (higher2lower(s[i] - '0'));
	}
//	}
	return n;
}

可以看出10位模式下要比7位模式多发送一个字节,10位模式是把slave addr的低8位放在了数据字段中进行发送。

最后

以上就是傻傻哈密瓜为你收集整理的Zynq-Linux移植学习笔记之43-linux下应用读写I2C设备的全部内容,希望文章能够帮你解决Zynq-Linux移植学习笔记之43-linux下应用读写I2C设备所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部