在hi3516平台上使用i2C
1.前言
这阵子在搞hi3516DV300的i2c通信,加上温度传感器tmp117为从机进行通信。梳理了一下关于hi3516DV300的调用i2c的方法,分别是APP,命令行和驱动三方面。
2.查看设备树是使能i2c-2
rp-hi3516dv300-sdk020/osdrv/opensource/kernel/linux-4.9.y-smp/arch/arm/boot/dts下的hi3516dv300-demb.dts中status 改为 “okay”
&i2c_bus2 {
status = "okay";
clock-frequency = <100000>;
};
3.需要配置SDA和SCL引脚的复用状态
我们这边使用的i2c-2来与tmp117通信。
需要将 0x111f0018和0x111f001c两个寄存器配置成0x201,有两种方法:
a.使用himm工具配置SDA和SCL引脚的复用状态
#在linux命令行中配置
himm 0x111F001C 0x201 (这是SCL的配置)
himm 0x111F0018 0x201 (这是SDA的配置)
b.在u-boot中配置SDA和SCL引脚的复用状态
进入展开后SDK的 rp-hi3516dv300-sdk020/osdrv/tools/pc/uboot_tools 目录下的文件:
Hi3516DV300-DMEB_4L_FLYBY-DDR3_1800M_512MB_16bitx2-A7_900M-SYSBUS_300M.xlsm
的pinout页面进行添加,好处是不用重新上电就要用himm去修改。
#将修改后的文件编译进u-boot
cd ./osdrv/tools/pc/uboot_tools
tar -zxf hiregbin-v5.0.1.tgz
cd hiregbin-v5.0.1
sudo chmod +x hiregbin
./hiregbin ../Hi3516DV300-DMEB_4L_FLYBY-DDR3_1800M_512MB_16bitx2-A7_900M-SYSBUS_300M.xlsm ./reg.bin
cp reg.bin ../../../../opensource/uboot/u-boot-2016.11/.reg
cd ../../../../opensource/uboot/u-boot-2016.11
make ARCH=arm CROSS_COMPILE=arm-himix200-linux- u-boot-z.bin
修改后可以用himm去读取看看。
4.通过命令行去读写i2c
a.在控制台使用i2c_read命令对I2C外围设备进行读操作:
i2c_read <i2c_num> <device_addr> <reg_addr> <end_reg_addr> <reg_width> <data_width> <reg_step>
例如:读挂载在I2C控制器2上、设备地址为0x49设备的0x0寄存器:
#0X92 = 0x49<<1
i2c_read 2 0x92 0x0 0x0 0x1 0x2
i2c_num:I2C控制器序号(对应《Hi3516CV500 专业型 Smart IP Camera SoC用户指南》中的I2C控制器编号)
device_addr:外围设备地址(Hi3516CV500支持标准地址(7bit)和扩展地址(10bit))
reg_addr:读外围设备寄存器操作的开始地址
end_reg_addr:读外围设备寄存器操作的结束地址
reg_width:外围设备的寄存器位宽(Hi3516CV500支持8/16/24/32bit)
data_width:外围设备的数据位宽(Hi3516CV500支持8/16/24/32bit)
reg_step:连续读外围设备寄存器操作时递增幅值,默认为1,即连续读寄存器,读取单个寄存器时不使用该参数
b.在控制台使用i2c_write命令对I2C外围设备进行写操作:
i2c_write <i2c_num> <device_addr> <reg_addr> <value> <reg_width> <data_width>
i2c_num:I2C控制器编号(对应《Hi3516CV500 专业型 Smart IP Camera SoC用户指南》中的I2C控制器编号)
device_addr:外围设备地址(Hi3516CV500支持标准地址(7bit)和扩展地址(10bit))
reg_addr:写外围设备寄存器操作的地址
value:写外围设备寄存器操作的数据
reg_width:外围设备的寄存器位宽(Hi3516CV500支持8/16/24/32bit)
data_width:外围设备的数据位宽(Hi3516CV500支持8/16/24/32bit)
5.用ioctl控制读写i2c设备。
通过打开/dev/i2c-2来打开设备,ioctl来对i2c设备读写控制。
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <errno.h>
#define I2C2_ADDR "/dev/i2c-2"
#define TMP117_ADDR 0x49
#define I2C_SLAVE 0x0703 /* Use this slave address */
#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it*/
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
int i2c_dev_Open( int *fd,unsigned char dev_addr)
{
int retval = 0;
int tmpfd =0;
tmpfd = open(I2C2_ADDR, O_RDWR);
if (tmpfd < 0) {
printf("i2c_dev_Open %s addr:%x error!\n",I2C2_ADDR,dev_addr);
retval = -1;
goto end0;
}
retval = ioctl(tmpfd, I2C_SLAVE, dev_addr);
if (retval < 0) {
retval = ioctl(tmpfd, I2C_SLAVE_FORCE, dev_addr);
if(retval < 0)
{
printf("i2c_dev_Open CMD_SET_I2C_SLAVE error! %s\n",strerror(errno));
close(tmpfd);
goto end0;
}
}
printf("i2c_dev_Open %s suc! [%d]\n",I2C2_ADDR, tmpfd);
*fd = tmpfd;
end0:
return retval;
}
int i2c_dev_Close(int *fd)
{
int tmpfd =*fd;
if(tmpfd)
close(tmpfd);
*fd = -1;
return 0;
}
int8_t i2c_dev_ReadByte(int fd,unsigned char dev_addr,unsigned char reg_addr,unsigned char *data,int len)
{
int retval = 0;
unsigned char tmp_reg_addr = 0x00;
struct i2c_rdwr_ioctl_data rdwr;
struct i2c_msg msg[2];
unsigned short Temperature ;
memset(data, 0x0, len);
msg[0].addr = dev_addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &tmp_reg_addr;
msg[1].addr = dev_addr;
msg[1].flags = I2C_M_RD;
msg[1].len = 2;
msg[1].buf = data;
rdwr.msgs = &msg[0];
rdwr.nmsgs = 2;
retval = ioctl(fd, I2C_RDWR, &rdwr);
if (retval != 2) {
printf("TMP117_ReadByte CMD_I2C_READ error!\n");
retval = -1;
goto end0;
}
Temperature = data[0]<<8|data[1];
printf("TMP117_ReadByte %s addr:%x reg:%x data:%x(%d)!\n",I2C2_ADDR,dev_addr,reg_addr,Temperature,Temperature);
end0:
return retval;
}
int main(int argc, char* argv[])
{
int rc;
int fd =0;
unsigned short Temperature ;
unsigned char data[2] ;
printf("TMP117_Open \n"