您的位置:首页 > 其它

应用层读写i2c从设备寄存器

2015-09-29 11:59 645 查看
在配置i2c从设备寄存器时往往需要修改驱动中的初始化函数来修改寄存器的值,这样往往需要重新编译内核,其实可以使用i2c驱动提供给应用层的接口函数ioctl来在命令行修改寄存器,只需要编写一个类似i2c测试程序的程序文件,使用int main(int argc, char **argv) 来向程序传递参数即可实时读写从设备的寄存器,工作队列(workqueue)可以实现多个寄存器的取值。

#include <stdio.h> 
#include <linux/types.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/ioctl.h> 
#include <errno.h> 
#include <assert.h> 
#include <string.h> 
#include <linux/i2c.h> 
#include <linux/i2c-dev.h> 

#define MAX_I2C_MSG          2 

#define I2C_RETRIES       0x0701 
#define I2C_TIMEOUT       0x0702 
#define I2C_RDWR          0x0707 
#define ADV7180_REG_NUM      253     /*连续读的寄存器个数*/
#define ADV7180_REG_BASE_ADDR   0   /*要连续读的第一个寄存器的地址,此处从0x00开始连续读253个寄存器值*/
/*此函数作用是把从命令行输入的数字字符转换为十六进制数,即寄存器地址或值*/
int strtol_dzb(unsigned char *ps,int flag)
{
    int i=10;    
    int r=0; 
    char *pc = ps;

    if(NULL==ps )  return -1;

    while(*pc != '\0')
    {
       if((*pc >= 'a' && *pc <= 'f') || 
          (*pc >= 'A' && *pc <= 'F') || 
          (*pc == 'x' || *pc == 'X') )
       {   
           i=16;          
       }
       else if( *pc < '0' || *pc > '9')
       {
           return -1;
       }
       pc++;  
    }  

    if(flag!=0)  i=flag;

    pc = ps;

    while(*pc != '\0')
    {
       r *= i;

       if( *pc>='a' && *pc <= 'f')
       {   
           r += (*pc-'a')+10;
       }
       else if( *pc>='A' && *pc <= 'F')
       {   
           r += (*pc-'A')+10;
       }
       else if( *pc>='0' && *pc <= '9')
       {   
           r += (*pc-'0');
       }
       
       pc++;  
    }    
    return r;
}
/* 主函数,3种情况,一个参数时读出253个值;三个参数时为“./test -r 0x00”,读某个寄存器;四个参数时为“./test -w 0x00 0x11”,写寄存器00值为11。*/
int main(int argc, char **argv) 
{ 
    struct i2c_rdwr_ioctl_data work_queue; 
    unsigned char idx; 
    unsigned char mode=1;//1--read, 0--w; 
    unsigned int fd;     
    unsigned short slave_address=0x68;
    unsigned short reg_address =ADV7180_REG_BASE_ADDR;//0x2c; 
    unsigned char val[256]={0};
    unsigned char data_len=ADV7180_REG_NUM;
    unsigned char data=0;
    int ret,tmp; 

    fd = open("/dev/i2c-1",O_RDWR); 
    work_queue.nmsgs = MAX_I2C_MSG; /*  消息数量  */  
    
    work_queue.msgs  =  (struct  i2c_msg*)malloc(work_queue.nmsgs*sizeof(struct i2c_msg)); 
    if (!work_queue.msgs) 
    { 
      	printf("Memory alloc error\n"); 
      	close(fd); 
      	return 0; 
    } 

    //printf("argc =%d \n",argc);
    if(argc==1) // dump 7180
    {
        idx = reg_address;
        val[idx]=idx;
      	(work_queue.msgs[0]).len = 1; 
        //(work_queue.msgs[0]).flags = 0;//I2C_M_WR;
      	(work_queue.msgs[0]).addr = slave_address; 
      	(work_queue.msgs[0]).buf = &val[idx]; 

        (work_queue.msgs[1]).len = data_len; 
        (work_queue.msgs[1]).flags = 1;//I2C_M_RD; 
      	(work_queue.msgs[1]).addr = slave_address; 
      	(work_queue.msgs[1]).buf  = &val[idx];         
   
	    ioctl(fd, I2C_TIMEOUT, 2); /*  设置超时  */ 
	    ioctl(fd, I2C_RETRIES, 1); /*  设置重试次数  */

	    ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue); 

	    if (ret < 0) 
	    { 
	      	printf("Error  during  I2C_RDWR  ioctl  with  error  code:  %d\n",  ret); 
	    } 
	    else
	    {
               
		printf("\n-----------------ADV7180 Reg-Test---------------------\n");
                printf(  "addr:  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f \n");
                printf(  "------------------------------------------------------");
	    
		for(idx = 0; idx < ADV7180_REG_NUM; idx++) 
		{ 
		    if(idx%16==0) printf("\n %02x: ", idx);   
		    printf(" %02x", val[idx]);
		}
                printf("\n-----------------------END----------------------------\n"); 
                           
	    }            
      }    
      else if(argc==2|| argc > 4)
      {
 	    printf("Usage:    %s [[-r regAddr] | [-w regAddr byteData]]\n", argv[0]);
            printf("              -r regAddr     read a byte from register--regAddr of adv7180\n");
            printf("              -w regAddr  data   write a byte data to register--regAddr of adv7180\n");
     }     
     else 
     {
          if(strstr(argv[1],"-r") ) // read a byte only
          {     
                if(-1 == (tmp=(unsigned short)strtol_dzb(argv[2],16)) )
                {
                     printf(" Invalid reg_addr: %s ",argv[2]);
                     close(fd);
                     return -1;
                }    
       
	    	reg_address=(unsigned short)tmp;
                printf("mode: read  reg_addr:  %3d (%02x) \n", reg_address, reg_address);
                
	    	
	    	val[0]=(unsigned char)reg_address;
      	    	(work_queue.msgs[0]).len = 1; 	    	
      	    	(work_queue.msgs[0]).addr = slave_address; 
      	    	(work_queue.msgs[0]).buf = &val[0]; 

	    	(work_queue.msgs[1]).len = data_len; 
	    	(work_queue.msgs[1]).flags = 1;//I2C_M_RD; 
      	    	(work_queue.msgs[1]).addr = slave_address; 
      	    	(work_queue.msgs[1]).buf  = &val[0];         
   	     	work_queue.nmsgs=2;

	    	ioctl(fd, I2C_TIMEOUT, 2); /*  璁剧疆瓒呮椂  */ 
	    	ioctl(fd, I2C_RETRIES, 1); /*  璁剧疆閲嶈瘯娆℃暟  */ 

	    	ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue); 

	    	if (ret < 0) 
	    	{ 
	      		printf("Error  during  I2C_RDWR  ioctl  with  error  code:  %d\n",  ret); 
	   	} 
                else 
                {
			printf("Read: Reg--%02x   Data--%02x  \n", reg_address, val[0]);
                }
          }
          else if( strstr(argv[1],"-w") ) // write a byte only
          {
            	   
                if(-1 == (tmp=(unsigned short)strtol_dzb(argv[2],16)) )
                {
                     printf(" Invalid reg_addr: %s ",argv[2]);
                     close(fd);
                     return -1;
                } 

	    	reg_address = (unsigned short)tmp;

            	if(-1 == (tmp=(unsigned short)strtol_dzb(argv[3],16)) )
                {
                     printf(" Invalid data: %s ",argv[3]);
                     close(fd);
                     return -1;
                } 
	    	data = (unsigned char)tmp;

            	printf("mode: write  reg_addr:  0x%02x   data: %x  \n", reg_address, data);
                        	
    		val[0]=(unsigned char)reg_address;
            	val[1]=data;

  	    	(work_queue.msgs[0]).len = 2; 
    		(work_queue.msgs[0]).flags = 0;//I2C_M_WR;
  	    	(work_queue.msgs[0]).addr = slave_address; 
  	    	(work_queue.msgs[0]).buf = &val[0]; 		          
        	work_queue.nmsgs=1;

		ioctl(fd, I2C_TIMEOUT, 2); /*  璁剧疆瓒呮椂  */ 
		ioctl(fd, I2C_RETRIES, 1); /*  璁剧疆閲嶈瘯娆℃暟  */ 

		ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue); 

		if (ret < 0) 
		{ 
		    printf("Error  during  I2C_RDWR  ioctl  with  error  code:  %d\n",  ret); 
		} 
#if 0
        	else 
	        {
	                (work_queue.msgs[0]).len = 1; 
		    	(work_queue.msgs[0]).flags = 0;//I2C_M_WR;
	      	        (work_queue.msgs[0]).addr = slave_address; 
	      	        (work_queue.msgs[0]).buf = &val[0]; 

		    	(work_queue.msgs[1]).len = data_len; 
		    	(work_queue.msgs[1]).flags = 1;//I2C_M_RD; 
	      	        (work_queue.msgs[1]).addr = slave_address; 
	                val[idx]=0;
	      	        (work_queue.msgs[1]).buf  = &val[0];         
	   	     	work_queue.nmsgs=2;

		    	ioctl(fd, I2C_TIMEOUT, 2); /*  璁剧疆瓒呮椂  */ 
		    	ioctl(fd, I2C_RETRIES, 1); /*  璁剧疆閲嶈瘯娆℃暟  */ 
		    	ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue);
				
			if (ret < 0) 
		        { 
		      	    printf("Error  during  I2C_RDWR  ioctl  with  error  code:  %d\n",  ret); 
		        } 
	            	else
		    	{
			    printf("Write: reg--%02x   w-data--%02x  r-data--%02x \n", reg_address,data,val[0]);
	            	}
	        }
#endif
      	} 
    }      

    close(fd); 
    return ; 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: