i2c 読み取りおよび書き込みツール、シェル ループ読み取りおよび書き込みレジスタ値

実際の開発では、i2c に対応するレジスタの値を読み書きする必要がある場合があります。i2ctool は非常に優れたツールですが、i2cset を使用してレジスタの値を書き込むときに、次のような対応する状況に遭遇することがあります。

i2cset -f -y 0 0x2d 0x00 0x11 i2cset: モードが長すぎます (「i2cset --help」を参照)

入力したパラメータが多すぎるというプロンプトが表示されますが、入力したパラメータが多すぎないため、関連するレジスタの値を正常に書き込むことができません. 私自身の検証の後、次のツールはこの問題を非常にうまく解決できます.レジスタの書き込みに関する問題。シェル スクリプトもあります。これは、大量の i2c レジスタ値を読み書きする必要がある場合に使用されます。ツール Android システムに統合でき、スクリプトも実行のために Android システムにプッシュされます。具体的な関連方法については、フォローアップされます。

次のコマンドは、adb push の前に実行する必要があります。そうしないと、許可エラーが報告されます。また、スクリプトは chmod を使用して、実行前に実行権限を追加する必要があります。

adb ルート

adb 再マウント

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

シェル スクリプト, シェル スクリプトは、入力コマンド ラインがファイルまたはアドレスのどちらであるかに基づいて実行できます. xxx.txt の場合は、シェル スクリプトを使用して 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