应用层读写i2c从设备寄存器
在配置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 0else {(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 ;
}
应用层读写i2c从设备寄存器相关推荐
- iic获取salve设备地址_Linux下使用IIC总线读写EEPROM(读写i2c从设备通用程序)
Linux 下使用IIC总线 读写 EEPROM by 韩大卫 @吉林师范大学 handawei@jusontech.com 转载请务必表明出处 ******************* ******* ...
- Linux应用层的i2c读写
i2c通道在开发过程中使用是非常的方便的,主要是由于其简单的结构,i2c主要有SCL,SDA两条通道,一个时钟线,一个数据线,这也是i2c之所以应用如此普遍的原因.i2c的时序如下: 实现上述时序,便 ...
- linux读写文件实例,Linux在应用层读写寄存器的方法及实现实例
Linux在应用层读写寄存器的方法 可以通过操作/dev/mem设备文件,以及mmap函数,将寄存器的地址映射到用户空间,直接在应用层对寄存器进行操作,示例如下: #include #include ...
- Linux读写I2C设备I2C_RDWR用法
i2c注册设备知识点:kernel/msm-4.9/drivers/i2c/i2c-dev.c为每个i2c设备创建设节点,所以我们不用创建./dev/i2c-0是在注册i2c-dev.c后产生的,代表 ...
- 工业超高频读写头|读写器|读卡器CK-UR08-A01寄存器的配置方法与攻略
工业超高频读写头|读写器|读卡器CK-UR08-A01部分寄存器用于设置设备地址.通信波特率.通信校验方法以及读卡器的工作模式,部分寄存器用于显示RFID卡检测状态以及显示命令执行是否正常,可设置的寄 ...
- linux i2c ioctl错误,关于读写I2C总线的时候出错的有关问题
关于读写I2C总线的时候出错的问题 我的程序是这样的: #include #include #include #include #include #include #include #include ...
- C++ MFC界面读写USB HID设备数据程序
C++ MFC界面读写USB HID设备数据程序 发一个简单易用的界面,用来对USB HID设备(比如说游戏手柄,控制面板等)读写数据,一般情况下面板上有一些LED,可以帮助我们测试读写是否正确.另外 ...
- 同时使用两片I2C同型号设备时地址怎样设置 (如何更改器件地址)
同时使用两片I2C同型号设备时地址怎样设置 有时候 可能 需要同时使用 多个同型号i2C的器件,这就需要 我们 更改 器件的物理地址. 同时使用两片pcf8591时地址怎样设置,也就是如何更改 器件 ...
- 【RTT】I2C总线设备:分析
I2C总线设备 概要 一.I2C硬件资源初始化 二.软件I2C的注册函数 三.I2C总线设备的注册 四.I2C总线设备的初始化 五.I2C的数据 六.I2C总线设备的使用 1. 查找I2C总线设备 2 ...
最新文章
- 用户自定义协议client/server代码示例
- 7_7_2013 E.Function
- 计算机基础知识易错,事业单位考试计算机基础知识易错试题.doc
- boost::hana::string_c用法的测试程序
- 肝货!你想要的资源这里都有!
- jboss eclipse_调试生产服务器– Eclipse和JBoss展示
- 文言的理解 —— 古时的称谓、别称、别名
- 【风马一族_Java】如何使用ACSLL表的值,
- 如何在dev cpp中使用c++11标准
- Java新手入门值得看的五本书!
- 计算机无法启动print,Win7无法启动print spooler服务报错1068怎么办
- 主机与虚拟机ping通
- matlab 图片黑白图片,MATLAB读取黑白图像显示却是黑色,24位深转8位深黑白图像解决方法(示例代码)...
- 描述12个异性追求者(互动媒体技术作业)
- 创建群晖共享文件夹,并进行电脑访问
- 使用SIMD指令加速计算
- SQLServer 时间段分隔,时间段查询,查询时间段内的数据
- 徐直军:今年至少3亿设备用上鸿蒙,互联网又一领域暗藏“金矿“
- LintCode题解【Python版】
- Unlocker给VMware解锁虚拟机苹果macOS系统教程