Linux嵌入式驱动开发18——I2C通信

全系列传送门

Linux嵌入式驱动开发01——第一个驱动Hello World(附源码)

Linux嵌入式驱动开发02——驱动编译到内核

Linux嵌入式驱动开发03——杂项设备驱动(附源码)

Linux嵌入式驱动开发04——应用层和内核层数据传输

Linux嵌入式驱动开发05——物理地址到虚拟地址映射

Linux嵌入式驱动开发06——第一个相对完整的驱动实践编写

Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

Linux嵌入式驱动开发08——字符设备(步步为营)

Linux嵌入式驱动开发09——平台总线详解及实战

Linux嵌入式驱动开发10——设备树开发详解

Linux嵌入式驱动开发11——平台总线模型修改为设备树实例

Linux嵌入式驱动开发12——pinctl和gpio子系统实践操作

Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

Linux嵌入式驱动开发14——中断的原理以及按键中断的实现(tasklet中断下文)

Linux嵌入式驱动开发15——等待队列和工作队列

Linux嵌入式驱动开发16——按键消抖实验(内核定时器)

Linux嵌入式驱动开发17——输入子系统

Linux嵌入式驱动开发18——I2C通信

I2C简介

在这里插入图片描述

ls /dev

在这里插入图片描述
这里拿我们的七寸LVDS屏幕的触摸芯片为例子,通过底座的原理图,可以看到LVDS使用了I2C3的接口
在这里插入图片描述

i2c-dev.h

在这里插入图片描述
打开文件

/include/uapi/linux/i2c-dev.h

i2c_rdwr_ioctl_data 结构体代码如下所示

/* 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 */
};

第一个结构体成员就是我们要发送的数据包的指针

第二个结构体成员是我们发送的数据包的个数

i2c.h

接下俩看一下i2c_msg结构体定义,结构体的位置

/include/uapi/linux/i2c.h

struct i2c_msg {
        __u16 addr;     /* slave address                        */
        __u16 flags;
#define I2C_M_TEN               0x0010  /* this is a ten bit chip address */
#define I2C_M_RD                0x0001  /* read data, from slave to master */
#define I2C_M_STOP              0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART           0x4000  /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR      0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK        0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK         0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN          0x0400  /* length will be first received byte */
        __u16 len;              /* msg length                           */
        __u8 *buf;              /* pointer to msg data                  */
};

在这里插入图片描述

TSC2007

通过底版的原理图,可以看到触摸芯片为TSC2007
在这里插入图片描述

I2C从设备地址 —— regtsc2007的7位设备地址是由A0, A1两个引脚的连接方式确定的,在 Datasheet 有给出说明。

7位地址中,D7~D5为高3位,所以地址高位为100,即为4。由于A1, A0两个引脚接地,所以 D4~D1为1000,即为8。

因此,这7位地址应该是0x48:

代码测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

int fd;

int i2c_read_data(unsigned int slave_addr, unsigned char reg_addr)
{
    unsigned char data;
    int ret;

    struct i2c_rdwr_ioctl_data i2c_read_lcd;

    struct i2c_msg msg[2] = { 
        [0] = {                                                         //第一个数据包
            .addr   = slave_addr,                                       //从机地址
            .flags  = 0,                                                //flags=1表示写操作,这里写的就是从机的寄存器地址
            .buf    = &reg_addr,                                        //要发送的数据
            .len    = sizeof(reg_addr),
        },
        [1] = {                                                         //第二个数据包
            .addr   = slave_addr,  
            .flags  = 1,                                                //进行读的操作
            .buf    = &data, 
            .len    = sizeof(reg_addr),
        },
    };

    i2c_read_lcd.msgs = msg;
    i2c_read_lcd.nmsgs = 2;

    ret = ioctl(fd, I2C_RDWR, &i2c_read_lcd);

    if(ret < 0){
        perror("ioctl error/n");
        return ret;
    }

    return data;

}

int main(int argc, char *argv[])
{
    int TD_STATUS;
    fd = open("/dev/i2c-3", O_RDWR);                                    // 打开节点时候触发open函数

    if(fd < 0){

        perror("open error\n");                                         // perror在应用中打印
        return fd;
    }
    while(1){
        TD_STATUS = i2c_read_data(0x48, 0x02);
        printf("TD_STATUS value is %d\n", TD_STATUS);
        sleep(1);
    }

    return 0;
}

TD_STATUS = i2c_read_data(0x48, 0x02);这句代码有问题,我没有找到tsc2007对应的触摸寄存器的位置,所以就读不到数在这里插入图片描述
不过问题不大,这只是其中一种方法,还有其他的方法,现在主流的方法是使用设备树

设备树

在设备树文件中,搜索tsc2007,看到i2c3下面的节点,就是我们的触摸芯片的节点
在这里插入图片描述
打开开发板,查看目录

/sys/bus/i2c/devices/

在这里插入图片描述
因为我们已经知道了是0x48地址,所以打开2-0048,然后cat name
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值