i2c 읽기 및 쓰기 도구, 쉘 루프 읽기 및 쓰기 레지스터 값

실제 개발에서 우리는 i2c 해당 레지스터의 값을 읽고 쓸 필요가 있을 수 있습니다. i2ctool은 매우 좋은 도구이지만 때때로 i2cset을 사용하여 레지스터의 값을 쓸 때 다음과 같은 해당 상황에 직면하게 됩니다.

i2cset -f -y 0 0x2d 0x00 0x11 i2cset: 모드가 너무 깁니다("i2cset --help" 참조).

파라미터를 너무 많이 입력했는데 파라미터를 너무 많이 입력하지 않아서 해당 레지스터의 값을 정상적으로 쓸 수 없다는 메시지가 나오는데, 직접 확인 후 다음 도구를 사용하면 이 문제를 잘 해결할 수 있습니다. 레지스터를 쓸 수 있는 문제. 쉘 스크립트도 있는데, 저는 게으르기 때문에 많은 수의 i2c 레지스터 값을 읽고 써야 할 때 사용됩니다. 그래서 명령을 한 단어씩 천천히 입력하는 것을 좋아하지 않습니다. 도구 안드로이드 시스템에 통합할 수 있으며 스크립트도 실행을 위해 안드로이드 시스템에 푸시됩니다. 구체적인 관련 방법이 뒤따를 것입니다.

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


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

Guess you like

Origin blog.csdn.net/qq_48709036/article/details/123105311