内核态I2C 读写程序示例

#include 

#include 

#include 



#include 

#include 

#include 

#include 

#include 



#ifdef __cplusplus

#if __cplusplus

extern "C"{

#endif

#endif /* __cplusplus */



/* /dev/i2c-X ioctl commands.  The ioctl's parameter is always an

 * unsigned long, except for:

 *      - I2C_FUNCS, takes pointer to an unsigned long

 *      - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data

 *      - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data

 */

#define I2C_RETRIES     0x0701  /* number of times a device address should

				   be polled when not acknowledging */

#define I2C_TIMEOUT     0x0702  /* set timeout in units of 10 ms */

/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses

 * are NOT supported! (due to code brokenness)

 */

#define I2C_SLAVE       0x0703  /* Use this slave address */

#define I2C_SLAVE_FORCE 0x0706  /* Use this slave address, even if it

				   is already in use by a driver! */

#define I2C_TENBIT      0x0704  /* 0 for 7 bit addrs, != 0 for 10 bit */



#define I2C_FUNCS       0x0705  /* Get the adapter functionality mask */



#define I2C_RDWR        0x0707  /* Combined R/W transfer (one STOP only) */



#define I2C_PEC         0x0708  /* != 0 to use PEC with SMBus */

#define I2C_SMBUS       0x0720  /* SMBus transfer */

#define I2C_16BIT_REG   0x0709  /* 16BIT REG WIDTH */

#define I2C_16BIT_DATA  0x070a  /* 16BIT DATA WIDTH */



unsigned int reg_width  = 1;

unsigned int data_width = 1;

unsigned int reg_step   = 1;





int atoul(char *str, unsigned int *pulValue);

int atoulx(char *str, unsigned int *pulValue);





/*****************************************************************************

 Prototype    : StrToNumber

 Description  : 10/16 进制字符串转换为无符号数字。

 Input  args  : IN CHAR *str

                   10进制字符串, 不接受符号

                   16进制字符串, 不包括前缀0x. 如ABCDE



 Output args  : U32* pulValue, 转换后的数字

 Return value : HI_RET  HI_SUCCESS 转换成功

                        HI_FAILURE 转换失败

 Calls        : isdigit



 Called  By   :



 History        :

 1.Date         : 2005年7月10日

   Author       : t41030

   Modification : Created function

*****************************************************************************/



int StrToNumber(char *str , unsigned int  *pulValue)

{

    /*判断是否16进制的字符串*/

    if ( *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X') )

    {

        if (*(str+2) == '\0')

        {

            return -1;

        }

        else

        {

            return atoulx(str+2,pulValue);

        }

    }

    else

    {

        return atoul(str,pulValue);

    }

}



/*****************************************************************************

 Prototype    : atoul

 Description  : 10进制字符串转换为无符号数字。

 Input  args  : IN CHAR *str 10进制字符串

                不接受符号

 Output args  : U32* pulValue, 转换后的数字

 Return value : HI_RET  HI_SUCCESS 转换成功

                        HI_FAILURE 转换失败

 Calls        : isdigit



 Called  By   :



 History        :

 1.Date         : 2005年7月10日

   Author       : t41030

   Modification : Created function

*****************************************************************************/

int atoul(char *str, unsigned int * pulValue)

{

	unsigned int ulResult=0;



    while (*str)

    {

        if (isdigit((int)*str))

        {

            /*最大支持到0xFFFFFFFF(4294967295),

               X * 10 + (*str)-48 <= 4294967295

               所以, X = 429496729 */

            if ((ulResult<429496729) || ((ulResult==429496729) && (*str<'6')))

            {

                ulResult = ulResult*10 + (*str)-48;

            }

            else

            {

                *pulValue = ulResult;

                return -1;

            }

        }

        else

        {

            *pulValue=ulResult;

            return -1;

        }

        str++;

    }

    *pulValue=ulResult;

    return 0;

}







/*****************************************************************************

 Prototype    : atoulx

 Description  : 16进制字符串转换为无符号数字。输入的16进制字符串不包括前缀0x

 Input  args  : IN CHAR *str 16进制字符串, 不包括前缀0x. 如ABCDE

 Output args  : U32* pulValue, 转换后的数字

 Return value : HI_RET  HI_SUCCESS 转换成功

                        HI_FAILURE 转换失败

 Calls        : toupper

                isdigit



 Called  By   :



 History        :

 1.Date         : 2005年7月10日

   Author       : t41030

   Modification : Created function

*****************************************************************************/

#define ASC2NUM(ch) (ch - '0')

#define HEXASC2NUM(ch) (ch - 'A' + 10)



int  atoulx(char *str, unsigned int * pulValue)

{

	unsigned int   ulResult=0;

    char ch;



    while (*str)

    {

        ch = toupper(*str);

        if (isdigit(ch) || ((ch >= 'A') && (ch <= 'F' )))

        {

            if (ulResult < 0x10000000)

            {

                ulResult = (ulResult << 4) + ((ch<='9')?(ASC2NUM(ch)):(HEXASC2NUM(ch)));

            }

            else

            {

                *pulValue=ulResult;

                return -1;

            }

        }

        else

        {

            *pulValue=ulResult;

            return -1;

        }

        str++;

    }



    *pulValue=ulResult;

    return 0;

}



int i2c_read(int argc , char* argv[])

{

	int fd = -1;

	int ret;

	unsigned int i2c_num, device_addr, reg_addr, reg_addr_end;

	unsigned int data;

	char recvbuf[4];

	int cur_addr;



	memset(recvbuf, 0x0, 4);



	if (argc < 4)

	{

		printf("usage: %s    "

				"  . sample: \n", argv[0]);

		printf("------------------------------------------------------------------------------------\n");

		printf("\t\t%s 0x1 0x56 0x0 0x10 2 2. \n", argv[0]);

		printf("\t\t%s 0x1 0x56 0x0 0x10 2 2 2. \n", argv[0]);

		printf("\t\t%s 0x1 0x56 0x0 0x10. default reg_width, data_width, reg_step is 1. \n", argv[0]);



		return -1;

	}



	if (StrToNumber(argv[1], &i2c_num)) {

		close(fd);

		return 0;

	}



	if (i2c_num == 0)

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

	else if (i2c_num == 1)

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

	else if (i2c_num == 2)

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

	else

		return -1;



	if (fd<0)

	{

		printf("Open i2c dev error!\n");

		return -1;

	}



	if (StrToNumber(argv[2], &device_addr))

	{

		close(fd);

		return 0;

	}

	if (StrToNumber(argv[3], ®_addr))

	{

		close(fd);

		return 0;

	}



	if(argc > 4)

	{

		if (StrToNumber(argv[4], ®_addr_end))

		{

			close(fd);

			return 0;

		}

		if (reg_addr_end < reg_addr)

		{

			printf("end addr(0x%2x) should bigger than start addr(0x%2x)\n",

					reg_addr_end, reg_addr);

			close(fd);

			return 0;

		}



		if((argc > 5) && StrToNumber(argv[5], ®_width))

		{

			close(fd);

			return 0;

		}



		if((argc > 6) && StrToNumber(argv[6], &data_width))

		{

			close(fd);

			return 0;

		}

		if ((argc > 7) && StrToNumber(argv[7], ®_step))

		{

			close(fd);

			return 0;

		}

	}

	else

	{

		reg_addr_end = reg_addr;

	}



	printf("i2c_num:0x%x, dev_addr:0x%2x; reg_addr:0x%2x; reg_addr_end:0x%2x; reg_width: %d; data_width: %d. \n\n",

			i2c_num, device_addr, reg_addr, reg_addr_end, reg_width, data_width);



		ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);

#if 0

		if (ret < 0)

		{

		        printf("CMD_SET_DEV error!\n");

			close(fd);

		        return -1;

		}

#endif



		if (reg_width == 2)

			ret = ioctl(fd, I2C_16BIT_REG, 1);

		else

			ret = ioctl(fd, I2C_16BIT_REG, 0);



		if (ret < 0)

		{

		        printf("CMD_SET_REG_WIDTH error!\n");

			close(fd);

		        return -1;

		}



		if (data_width == 2)

			ret = ioctl(fd, I2C_16BIT_DATA, 1);

		else

			ret = ioctl(fd, I2C_16BIT_DATA, 0);



		if (ret < 0)

		{

		        printf("CMD_SET_DATA_WIDTH error!\n");

			close(fd);

		        return -1;

		}



		for (cur_addr = reg_addr; cur_addr < reg_addr_end + reg_width; cur_addr += reg_step)

		{

			if (reg_width == 2) {

				recvbuf[0] = cur_addr & 0xff;

				recvbuf[1] = (cur_addr >> 8) & 0xff;

			} else

				recvbuf[0] = cur_addr & 0xff;



			ret = read(fd, recvbuf, reg_width);

			if (ret < 0)

			{

				printf("CMD_I2C_READ error!\n");

				close(fd);

				return -1;

			}



			if (data_width == 2) {

				data = recvbuf[0] | (recvbuf[1] << 8);

			} else

				data = recvbuf[0];



			printf("0x%x 0x%x\n", cur_addr, data);

		}



	close(fd);



	return 0;

}



int i2c_write(int argc , char* argv[])

{

	int fd = -1;

	int ret =0, index = 0;

	unsigned int i2c_num, device_addr, reg_addr, reg_value;

	char buf[4];



	if(argc < 5)

	{

		printf("usage: %s      . sample:\n", argv[0]);

		printf("----------------------------------------------------------------------------\n");

		printf("\t\t%s 0x1 0x56 0x0 0x28 2 2. \n", argv[0]);

		printf("\t\t%s 0x1 0x56 0x0 0x28. default reg_width and data_width is 1. \n", argv[0]);

		return -1;

	}



	if (StrToNumber(argv[1], &i2c_num)) {

		close(fd);

		return 0;

	}



	if (i2c_num == 0)

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

	else if (i2c_num == 1)

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

	else if (i2c_num == 2) {

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

	} else

		return -1;



	if(fd < 0)

	{

		printf("Open i2c dev error!\n");

		return -1;

	}



	if (StrToNumber(argv[2], &device_addr))

	{

		close(fd);

		return 0;

	}

	if (StrToNumber(argv[3], ®_addr))

	{

		close(fd);

		return 0;

	}

	if (StrToNumber(argv[4], ®_value))

	{

		close(fd);

		return 0;

	}



	if(argc > 5)

	{

		if(StrToNumber(argv[5], ®_width))

		{

			close(fd);

			return 0;

		}



		if((argc > 6) && StrToNumber(argv[6], &data_width))

		{

			close(fd);

			return 0;

		}

	}



	printf("dev_addr:0x%2x; reg_addr:0x%2x; reg_value:0x%2x; reg_width: %d; data_width: %d.\n",

			device_addr, reg_addr, reg_value, reg_width, data_width);



	ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);



	if (reg_width == 2)

		ret = ioctl(fd, I2C_16BIT_REG, 1);

	else

		ret = ioctl(fd, I2C_16BIT_REG, 0);



	if (data_width == 2)

		ret = ioctl(fd, I2C_16BIT_DATA, 1);

	else

		ret = ioctl(fd, I2C_16BIT_DATA, 0);



	if (reg_width == 2) {

		buf[index] = reg_addr & 0xff;

		index++;

		buf[index] = (reg_addr >> 8) & 0xff;

		index++;

	} else {

		buf[index] = reg_addr & 0xff;

		index++;

	}



	if (data_width == 2) {

		buf[index] = reg_value & 0xff;

		index++;

		buf[index] = (reg_value >> 8) & 0xff;

		index++;

	} else {

		buf[index] = reg_value & 0xff;

		index++;

	}



	write(fd, buf, (reg_width + data_width));

	if(ret < 0)

	{

		printf("I2C_WRITE error!\n");

		return -1;

	}



	close(fd);



	return 0;

}



int main(int argc, char* argv[])

{
	i2c_write(argc , argv);

	return 0;

}



#ifdef __cplusplus

#if __cplusplus

}

#endif

#endif /* __cplusplus */

 

你可能感兴趣的:(内核态I2C 读写程序示例)