i2c读写工具,shell 循环读写寄存器的值

在实际开发中,我们可能会遇到要读写i2c对应寄存器里面的值,i2ctool是个非常好的工具,但是有时候我们在利用i2cset 写寄存器的值时会遇到对应的情况,如下:

i2cset -f -y 0 0x2d 0x00 0x11                                                                                                                                                                           i2cset: mode too long (see "i2cset --help")

会出现一个提示,说我们输入的参数过多,但是我们并没有多输入参数,导致我们不能够正常的写相关寄存器的值,我经过自己的验证,以下的工具能够很好的解决这一个不能够写寄存器的问题。还有一个shell脚本,用与在我们在需要大量的读写i2c寄存器的值时来用,因为我这个人比较懒,所以不喜欢一个一个字的慢慢去敲命令,那样太费事,该工具可以集成到android系统中使用的,且脚本也是push 到android系统中去执行。具体的相关的方法,后续出方法。

adb push 之前应该执行以下命令。否则会报权限错误。且脚本在执行前应该利用chmod添加执行权限。

adb root

adb remount

#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>  

#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 */
#define I2C_RDWR	0x0707	/* Combined R/W transfer (one STOP only) */


/* This is the structure as used in the I2C_RDWR ioctl call */  
struct i2c_rdwr_ioctl_data {  
        struct i2c_msg __user *msgs;    /* pointers to i2c_msgs */  
        __u32 nmsgs;                    /* number of i2c_msgs */  
};  
  
int i2c_read_reg(char *dev, unsigned char *buf, unsigned slave_address, unsigned reg_address, int len)  
{  
    struct i2c_rdwr_ioctl_data work_queue;  
    unsigned char w_val = reg_address;  
    int ret;  
  
    int fd = open(dev, O_RDWR);  
    if (!fd) {  
        printf("Error on opening the device file\n");  
        return 0;  
    }  
  
    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 error\n");  
        close(fd);  
        return 0;  
    }  
  
    ioctl(fd, I2C_TIMEOUT, 2);  
    ioctl(fd, I2C_RETRIES, 1);  
  
    (work_queue.msgs[0]).len = 1;  
    (work_queue.msgs[0]).addr = slave_address;  
    (work_queue.msgs[0]).buf = &w_val;  
  
    (work_queue.msgs[1]).len = len;  
    (work_queue.msgs[1]).flags = I2C_M_RD;  
    (work_queue.msgs[1]).addr = slave_address;  
    (work_queue.msgs[1]).buf = buf;  
  
    ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue);  
    if (ret < 0) {  
        printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);  
        close(fd);  
        free(work_queue.msgs);  
        return 0;  
    } else {  
        printf("read salve:%02x reg:%02x\n", slave_address, reg_address);  
        close(fd);  
        free(work_queue.msgs);  
        return len;  
    }  
}  
  
int i2c_write_reg(char *dev, unsigned char *buf, unsigned slave_address, unsigned reg_address, int len)  
{  
    struct i2c_rdwr_ioctl_data work_queue;  
    unsigned char w_val = reg_address;  
    unsigned char w_buf[len+1];  
    int ret;  
  
    w_buf[0] = reg_address;  
  
    int fd = open(dev, O_RDWR);  
    if (!fd) {  
        printf("Error on opening the device file\n");  
        return 0;  
    }  
  
    work_queue.nmsgs = 1;  
    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;  
    }  
  
    ioctl(fd, I2C_TIMEOUT, 2);  
    ioctl(fd, I2C_RETRIES, 1);  
  
    (work_queue.msgs[0]).len = 1 + len;  
    (work_queue.msgs[0]).addr = slave_address;  
    (work_queue.msgs[0]).buf = w_buf;  
  
    memcpy(w_buf + 1, buf, len);  
  
    ret = ioctl(fd, I2C_RDWR, (unsigned long) &work_queue);  
    if (ret < 0) {  
        printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);  
        close(fd);  
        free(work_queue.msgs);  
        return 0;  
    } else {  
        printf("write salve:%02x reg:%02x\n", slave_address, reg_address);  
        close(fd);  
        free(work_queue.msgs);  
        return len;  
    }  
}  
  
int main(int argc, char **argv)  
{  
    unsigned int fd;  
    unsigned int slave_address, reg_address;  
    unsigned r_w;  
    unsigned w_val;  
    unsigned char rw_val;  
  
    if (argc < 5) {  
        printf("Usage:\n%s /dev/i2c-x start_addr reg_addr rw[0|1] [write_val]\n", argv[0]);  
        return 0;  
    }  
  
    fd = open(argv[1], O_RDWR);  
  
    if (!fd) {  
        printf("Error on opening the device file %s\n", argv[1]);  
        return 0;  
    }  
  
    sscanf(argv[2], "%x", &slave_address);  
    sscanf(argv[3], "%x", &reg_address);  
    sscanf(argv[4], "%d", &r_w);  
  
    if (r_w == 0) {  
        i2c_read_reg(argv[1], &rw_val, slave_address, reg_address, 1);  
        printf("Read %s-%x reg %x, read value:%x\n", argv[1], slave_address, reg_address, rw_val);  
    } else {  
        if (argc < 6) {  
            printf("Usage:\n%s /dev/i2c-x start_addr reg_addr r|w[0|1] [write_val]\n", argv[0]);  
            return 0;  
        }  
        sscanf(argv[5], "%x", &w_val);  
        if ((w_val & ~0xff) != 0)  
            printf("Error on written value %s\n", argv[5]);  
  
        rw_val = (unsigned char)w_val;  
        i2c_write_reg(argv[1], &rw_val, slave_address, reg_address, 1);  
    }  
  
    return 0;  
}  

对应的Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

ifeq ($(SPEC_FOR_5071_TMFP),true)
        LOCAL_CFLAGS += -DCONFIG_SPEC_FOR_5071_TMFP
else
endif

LOCAL_MODULE = i2c_rw
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := i2c_rw_tool.c //换成该.c文件名,可换为文件命

include $(BUILD_EXECUTABLE)

shell 脚本,该shell 脚本可根据输入命令行是文件还是地址,如果是xxx.txt 该shell 脚本就是用于写i2c寄存器的值,如果是读取i2c寄存器地址中的值,需要输入所要读取的寄存器的地址。

#At present, the value of I2C read register needs to be improved, 
#and the value of I2C corresponding register can be written normally

#!/bin/bash
b=1 #i2c number
i2c_path="/dev/i2c-1"	#read / write path
i2c_reg="0x2c" #i2c reg address
num=1   
file_name=$1

 if [ $# == 0 ]
 then
 	echo "Please re-enter and exit the script"
 	exit 1
 elif [ $# == 1 ]
 then
	if [ ! -f $1 ]
	then              
		echo "the $1 is not a file"
		exit 
	else
		flage=1
		echo "write the value of the register"
		echo "Start reading file data"
	fi
 else
 	flage=0
 	echo "Read the value of the register"	
 fi

i2cdetect -y $b
i2cdump -f -y $b $i2c_reg 
echo "Start the read/write i2c adder"
   
if [ $flage == 1 ] #write
	then
	while ((num<=$(cat "$file_name"|wc -l)))  
	    do  
		file_reg[$num]=$(cat "$file_name"|sed -n "${num}p"|awk -F ',' '{print $1}')  
		((num+=1))  
           done  
	num=1
	while ((num<=$(cat "$file_name"|wc -l)))  
	    do  
		file_val[$num]=$(cat "$file_name"|sed -n "${num}p"|awk -F ',' '{print $2}')  
		((num+=1))  
	    done 
	    
    num=`expr $num - 1` 
 	i=$num
 else   #read
 	#i=`expr $#/2`
 	i=$#
 fi
	while ((i>0))
	do		
	        if [ $flage == 0 ] #read
	        then
	        	i2c_rw $i2c_path $i2c_reg $flage $1  	
	        	echo "$1"
	        	shift 1
	        else  #write
	        	i2c_rw $i2c_path $i2c_reg ${file_reg[i]} $flage ${file_val[i]}
	        	echo ${file_reg[i]}
	        	echo ${file_val[i]}
	        	
	        fi
		let i--
	done
i2cdump -f -y $b $i2c_reg     


     

使用案例:

/data # ./write_i2c.sh 0x14 0x01 0x15 0x23 0x16 0x40 0x17 0x00 0x18 0x01 0x19 0x23 0x1A 0x40 0x1B 0x00   该命令是用来读取i2c寄存器中的值。

/data # ./write_i2c.sh file.txt 该命令是用来批量的往寄存器里写值。

file.txt 文件内容如下:

0x00,0xAA
0x48,0x02
0xB6,0x20
0x01,0x38
0x02,0x80
0x03,0x74
0x04,0x64
0x05,0x50
0x06,0x64
0x07,0x00
0x08,0x14
0x09,0x05
0x0A,0x14
0x0B,0x02
0x0C,0x52
0x0D,0x01
0x0E,0x80
0x0F,0x20
0x10,0x20
0x11,0x03
0x12,0x1B
0x13,0x53
0x14,0x32
0x15,0x10
0x16,0x40
0x17,0x00
0x18,0x32
0x19,0x10
0x1A,0x40
0x1B,0x00
0x1E,0x46
0x51,0x30
0x1F,0x10
0x2A,0x01


注:左边是寄存器地址,右侧是要写如寄存器地址中的值

猜你喜欢

转载自blog.csdn.net/qq_48709036/article/details/123105311