迅为iTOP-i.MX6ULL开发板I2C驱动程序实现 I2C通信

news/2024/11/8 0:39:16/

在第 67.1 章节学习 i2c 的时候,我们是在应用层操作设备节点对 i2c 设备进行读写的,那么如果我们在

驱动里面对 i2c 设备进行读写要怎么办呢?本章节我们将来学习。

我们复制第 67.3 章节的代码,在此基础上进行修改。我们在应用里面对 i2c 进行读写,最重要的是对

我们数据包的封包的操作,封装了一个 i2c_rdwr_ioctl_data 数据包,才对 i2c 进行读写,同样在驱动里面,

我们也可以使用这种方法。

本章内容对应视频讲解链接(在线观看):

驱动程序实现 I2C 通信 → https://www.bilibili.com/video/BV1Vy4y1B7ta?p=47

我们对某个可读可写的寄存器进行读写操作,我们打开触摸芯片 ft5x06 的数据手册,打开 2.1 章节,如

下图所示:

完整的代码如下所示:

#include <linux/init.h>

#include <linux/module.h>

#include <linux/i2c.h>

static struct i2c_client *ft5x06_client;

static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len);

static int ft5x06_read_reg(u8 reg_addr);

//读寄存器函数

static int ft5x06_read_reg(u8 reg_addr)

{

u8 data;

struct i2c_msg msgs[] = {

[0] = {

.addr = ft5x06_client->addr,

.flags = 0,

.len = sizeof(reg_addr),

.buf = &reg_addr,

},

[1] = {

.addr = ft5x06_client->addr,

.flags = 1,

.len = sizeof(data),

.buf = &data,

},

};

i2c_transfer(ft5x06_client->adapter, msgs, 2);

return data;

}

//写寄存器函数

static void ft5x06_write_reg(u8 reg_addr, u8 data, u8 len)

{

u8 buff[256];

struct i2c_msg msgs[] = {

[0] = {

.addr = ft5x06_client->addr,

.flags = 0,

.len = len + 1,

.buf = buff,

},

};

buff[0] = reg_addr;

memcpy(&buff[1], &data, len);

i2c_transfer(ft5x06_client->adapter, msgs, 1);

}

//与设备树的 compatible 匹配

static const struct of_device_id ft5x06_id[] = {

{.compatible = "edt,edt-ft5306", 0},

{.compatible = "edt,edt-ft5x06", 0},

{.compatible = "edt,edt-ft5406", 0},

{}};

// 无设备树的时候匹配 ID 表

static const struct i2c_device_id ft5x06_id_ts[] = {

{"xxxxx", 0},

{}};

/* i2c 驱动的 remove 函数 */

int ft5x06_remove(struct i2c_client *i2c_client)

{

return 0;

}

/* i2c 驱动的 probe 函数 */

int ft5x06_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id)

{

int ret;

printk("This is ft5x06_probe\n");

//因为我们要在别的函数里面使用 client,所以我们要把他复制出来

ft5x06_client = i2c_client;

//往地址为 0x80 的寄存器里面写入数据 0x4b

ft5x06_write_reg(0x80, 0x4b, 1);

//读出 0x80 寄存器的值

ret = ft5x06_read_reg(0x80);

//打印 0x80 寄存器的值

printk("ret is %#x\n", ret);

return 0;

}

//定义一个 i2c_driver 的结构体

static struct i2c_driver ft5x06_driver = {

.driver = {

.owner = THIS_MODULE,

.name = "ft5x06_test",

// 采用设备树的时候驱动使用的匹配表

.of_match_table = ft5x06_id,

},

.probe = ft5x06_probe,

.remove = ft5x06_remove,

.id_table = ft5x06_id_ts};

/* 驱动入口函数 */

static int ft5x06_driver_init(void)

{

int ret;

//注册 i2c_driver

ret = i2c_add_driver(&ft5x06_driver);

if (ret < 0)

{

printk(" i2c_add_driver is error \n");

return ret;

}

printk("This is ft5x06_driver_init\n");

return 0;

}

/* 驱动出口函数 */

static void ft5x06_driver_exit(void)

{

i2c_del_driver(&ft5x06_driver);

printk("This is ft5x06_driver_exit\n");

}

module_init(ft5x06_driver_init);

module_exit(ft5x06_driver_exit);

MODULE_LICENSE("GPL");

我们参考第三十九章 Linux 内核模块将刚刚编写的驱动代码编译为驱动模块,编译完如下图所示:

我们进入共享目录并且加载驱动模块,共享目录的搭建参考第三十七章 37.2.3 搭建 nfs 共享目录,

如下图所示:

如上图所示,我们可以看到读写函数是没问题的,可以对寄存器进行正常的读写操作。


http://www.ppmy.cn/news/53113.html

相关文章

Dockere-Compose迁移Gitea部署

Dockere-Compose迁移Gitea部署 ps: 江湖不是打打杀杀&#xff0c;江湖是人情事故。 解释&#xff1a; Gitea&#xff1a;类似于Git的代码版本管理工具。Docker&#xff1a;Docker-Compose&#xff1a; Docker命令&#xff1a; 查看镜像&#xff1a;docker images 删除镜像…

【离散系统】传递函数和状态空间方程离散化

本文如有错误&#xff0c;恳请指正。 目录 离散系统 采样控制系统 数字控制系统 信号采样 采样定理&#xff08;香农定理&#xff09; 信号保持—零阶保持器 Z变换 Z 变换方法 级数求和法 部分分式法 基本定理 Z反变换 Z反变换方法 长除法 部分分式法&#xff0…

一文技术解析ART虚拟机method tracing

一、method tracing介绍 概述 这个是谷歌提供的对java的函数级trace工具&#xff0c;和systrace只支持打点不同&#xff0c;method tracing能支持到函数&#xff0c;看到具体的函数执行时间&#xff0c;准确的分析出来执行的时间短板。 1.生成trace的方式 sampling方式&…

云计算的未来发展趋势与优势,你是否了解?

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一、企业痛点 1.企业信息技术应用痛点 二、云计算的基础概念 1.什么是云计…

【Python】Python学习笔记(三)条件语句

条件语句 Python中的条件语句与c/cpp基本无异。 if语句 基本结构见以下代码。 Python使用缩进控制if/else语句之间的嵌套关系。 #判断两数是否相等。a int(input(a:)) b int(input(b:))if a b:print(Same) else:print(No Same)elif 代替了cpp中“else if”的写法&#…

Basics of Container Isolation 容器隔离的实现原理

目录 容器隔离的实现原理 1. 使用cgroups实现资源隔离 自定义一个cgroup 设置进程的内存使用 启动一个docker 容器&#xff0c;观察cgroup的创建情况 2. 使用Namespaces进行资源分区 namespace继承关系引发的问题 3. 结合来使用Namespaces 和chroot 4. 结论 参考文档…

supervisor安装

说明 Supervisor翻译过来是监管人&#xff0c;在Linux中Supervisor是一个进程管理工具&#xff0c;当进程中断的时候Supervisor能自动重新启动它。可以运行在各种类Linux/unix的机器上&#xff0c;supervisor就是用Python开发的一套通用的进程管理程序&#xff0c;能将一个普通…

[Daimayuan] 倒数第n个字符串(C++,进制)

给定一个完全由小写英文字母组成的字符串等差递增序列&#xff0c;该序列中的每个字符串的长度固定为 L L L&#xff0c;从 L L L 个 a a a 开始&#xff0c;以 1 1 1 为步长递增。例如当 L L L 为 3 3 3 时&#xff0c;序列为 a a a , a a b , a a c , . . . , a a z ,…