I2C驱动(四) --I2C-Tools介绍


参考资料

一、I2C软件流程

在Linux中,应用程序想要访问硬件设备,必须通过驱动程序。下图是应用程序访问硬件设备的流程,应用程序经过设备驱动再到控制器驱动程序来访问到硬件设备。(1)控制器驱动程序adapter_driver一般由芯片厂家编写,Linux内核还提供了gpio模拟的I2C控制器驱动程序。(2)对于设备驱动程序,可以根据特定芯片编写特定程序,Linux内核也提供了通用的设备驱动程序,对应驱动文件为i2c-dev.c。(3)i2c-tools就是上层的应用程序,它是一个好用的工具,也可以根据它的示例代码来编写自己的APP程序。
在这里插入图片描述

二、I2C-Tools使用

一句话概括I2C数据传输:APP 通过I2C Controller 与 I2C Device传输数据。
所以使用I2C-Tools也需要确定:

  • 使用哪个I2C控制器(或称为I2C Bus、I2C Adapter)
  • 和哪个设备通信(设备地址)
  • 数据:读还是写、数据本身

2.1 交叉编译

  • 首先需要在Ubuntu上设置工具链
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/zpz/share/imx6ullsdk/repo/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
  • 修改Makefile,指定工具链
#原内容
CC      ?= gcc
AR      ?= ar
STRIP   ?= strip
# 在Makefile中,“?=”是延时变量,在第一次设置变量时才会起效果,如果之前设置过该变量,则不会起效果。

#修改(指定交叉编译工具链前缀, 去掉问号):
CC      = $(CROSS_COMPILE)gcc
AR      = $(CROSS_COMPILE)ar
STRIP   = $(CROSS_COMPILE)strip
  • 执行make编译
    • 执行make时,是动态链接,需要把libi2c.so也放到单板上
    • 想静态链接的话,执行:make USE_STATIC_LIB=1

2.2 常用命令

2.2.1 i2cdetect: I2C检测

(1) 列出所有的I2C Adapter

i2cdetect -l

[root@100ask:~]# i2cdetect -l
i2c-1   i2c             21a4000.i2c          I2C adapter
i2c-0   i2c             21a0000.i2c          I2C adapter

(2) 打印某个I2C Adapter的Functionalities, I2CBUS为0、1、2等整数

i2cdetect -F I2CBUS

[root@100ask:~]# i2cdetect -F 0
Functionalities implemented by /dev/i2c-0:
I2C                              yes
SMBus Quick Command              yes
SMBus Send Byte                  yes
SMBus Receive Byte               yes
SMBus Write Byte                 yes
SMBus Read Byte                  yes
SMBus Write Word                 yes
SMBus Read Word                  yes
SMBus Process Call               yes
SMBus Block Write                yes
SMBus Block Read                 yes
SMBus Block Process Call         no
SMBus PEC                        yes
I2C Block Write                  yes
I2C Block Read                   yes

(3) 查看Adapter上有哪些I2C设备, I2CBUS为0、1、2等整数

i2cdetect -y -a I2CBUS

[root@100ask:~]# i2cdetect -y -a 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- UU -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- UU -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

//其中 - - 表示该地址没有对应的设备,UU表示有该设备并且它已经有驱动程
//序,数值表示有该设备,但是没有对应的设备驱动。

2.2.2 i2cget:I2C读

(1) 读一个字节: I2CBUS为0、1、2等整数, CHIP-ADDRESS表示设备地址

i2cget -f -y I2CBUS CHIP-ADDRESS

(2)读某个地址上的一个字节: I2CBUS为0、1、2等整数,CHIP-ADDRESS表示设备地址,DATA-ADDRESS: 芯片上寄存器地址,MODE:有2个取值, b-使用SMBus Read Byte先发出DATA-ADDRESS, 再读一个字节, 中间无P信号, c-先write byte, 在read byte,中间有P信号 。

i2cget -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS MODE

(3)读某个地址上的两个字节:I2CBUS为0、1、2等整数, CHIP-ADDRESS表示设备地址, DATA-ADDRESS: 芯片上寄存器地址, MODE:w-表示先发出DATA-ADDRESS,再读2个字节。

i2cget -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS MODE

2.2.3 i2cset:I2C写

(1)写一个字节:I2CBUS为0、1、2等整数, CHIP-ADDRESS表示设备地址, DATA-ADDRESS就是要写的数据。

i2cset -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS

(2)给某个地址写一个字节:I2CBUS为0、1、2等整数, CHIP-ADDRESS表示设备地址,DATA-ADDRESS: 芯片上寄存器地址,VALUE: 8位数值,MODE: 可以省略,也可以写为b。

i2cset -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS VALUE [b]

(3)给某个地址写两个字节:I2CBUS为0、1、2等整数,CHIP-ADDRESS表示设备地址, DATA-ADDRESS: 8位芯片寄存器地址,VALUE: 16位数值,MODE: w。

i2cset -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS VALUE w

(4)给某个地址写N个字节(SMBus Block Write): 发送的数据有:address, N, value1, value2, …, valueN,跟I2C Block Write相比,需要发送长度N,I2CBUS为0、1、2等整数, CHIP-ADDRESS表示设备地址,DATA-ADDRESS: 8位芯片寄存器地址; VALUE1~N: N个8位数值,MODE: s。

i2cset -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS VALUE1 ... VALUEN s

(5)给某个地址写N个字节(I2C Block Write):跟SMBus Block Write相比, 不需要发送长度N。MODE标志为:i。

i2cset -f -y I2CBUS CHIP-ADDRESS DATA-ADDRESS VALUE1 ... VALUEN i

2.2.4 i2cdump:列出所有寄存器

打印出总线0上设备地址为0x1e的设备,所有寄存器值。

[root@100ask:~]#i2cdump -f -y 0 0x1e
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 02 02 01 ee ee 00 00 00 00 00 00 00 00    ...?????........
10: 00 01 00 03 ee ee ee ee ee 40 00 00 ff ff ee ee    .?.??????@....??
20: 05 13 01 00 00 ee ee ee 00 00 00 80 00 80 ee ee    ???..???...?.???
30: 00 00 ee 05 ee 00 ee 1b 00 00 00 00 00 00 00 00    ..???.??........
40: 84 86 81 8c 81 86 80 b1 ee ee ee ee ee ee ee ee    ????????????????
50: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
60: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
70: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
80: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
90: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
a0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
b0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
c0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
d0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
e0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????
f0: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ????????????????

2.2.5 i2ctransfer:I2C传输(不是基于SMBus)

(1)读
从总线0上,设备地址为0x50的设备,读寄存地址0的数值
i2ctransfer 0 w1@0x50 0 r1

(2)写
往总线0上,设备地址为0x50的设备,寄存器地址0上写入0x3。
i2ctransfer 0 w2@0x50 0 0x3

2.3 I2C-Tools源码分析

一句话概括I2C数据传输:APP 通过I2C Controller 与 I2C Device传输数据。
所以在APP里有几个问题:

  • 怎么指定I2C控制器?

    • i2c-dev.c提供为每个I2C控制器(I2C Bus、I2C Adapter)都生成一个设备节点:/dev/i2c-0、/dev/i2c-1等。
      [root@100ask:~]# ls /dev/i2c-*
      /dev/i2c-0  /dev/i2c-1
      
    • open某个/dev/i2c-X节点,就是去访问该I2C控制器下的设备。
  • 怎么指定I2C设备?

    • 通过ioctl指定I2C设备的地址。
    • ioctl(file, I2C_SLAVE, address)
      如果该设备已经有了对应的设备驱动程序,则返回失败
    • ioctl(file, I2C_SLAVE_FORCE, address)
      如果该设备已经有了对应的设备驱动程序但是还是想通过i2c-dev驱动来访问它,则使用这个ioctl来强制指定I2C设备地址
  • 怎么传输数据?

    • 一般的I2C方式:ioctl(file, I2C_RDWR, &rdwr)
    • SMBus方式:ioctl(file, I2C_SMBUS, &args)

2.3.1 使用I2C方式

示例代码:i2ctransfer.c

#1.打开i2c总线设备
open_i2c_dev(i2c_bus,filename,sozeof(filename),0);
	open(filename, O_RDWR);//系统调用打开设备
#2.设置设备地址
set_slave_addr(file, address,0);
	ioctl(file,force ? I2C_SLAVE_FORCE:I2C_SLAVE,address);//系统调用设置设备地址
#3.传输数据
//构造msgs
struct i2c_rdwr_ioctl_data rdwr;
rdwr.msgs  = msgs;
rdwr.nmsgs = nmsgs;//msgs个数
//传输
ioctl(file,I2C_RDWR,&rdwr);

软件流程
在这里插入图片描述

2.3.2 使用SMBus方式

示例代码:i2cget.c 、i2cset.c
软件流程如下图,打开总线和设置设备地址和普通I2C方式一样,区别在于SMBus传输协议,对于SMBus协议封装好了一套传输函数。最终还是通过系统调用ioctl(file,I2C_SMBUS,&args)来和设备通信。
在这里插入图片描述

  • 36
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值