驱动程序实现i2c通讯

编程入门 行业动态 更新时间:2024-10-26 13:33:01

驱动程序实现i2c通讯

i2c对寄存器的读写

​ 在 I2C 设备驱动中首先要完成 i2c_driver 结构体的创建、初始化和注册,当设备和驱动匹配成功后,就会执行 probe 函数,probe 函数中就是执行字符设备驱动的一套流程。

​ 一般需要在 probe 函数里面初始化 I2C 设备,要初始化 I2C 设备就必须能够对 I2C 设备寄存器进行读写操作,这里就要用到 i2c_transfer 函数了。i2c_transfer 函数最终会调用 I2C 适配器中 i2c_algorithm 里面的 master_xfer 函数,对于 I.MX6U 而言就是 i2c_imx_xfer 这个函数。

i2c_transfer 函数

原型如下

  int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs,int  num)  

作用:

能够对 I2C 设备寄存器进行读写操作

参数:

函数int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs,int num)adap所使用的 I2C 适配器,i2c_client 会保存其对应的 i2c_adapter。msgsI2C 要发送的一个或多个消息num消息数量,也就是 msgs 的数量返回值负值,失败,其他非负值,发送的 msgs 数量

i2c传递树据的数据包

我们重点来看一下 msgs 这个参数,这是一个 i2c_msg 类型的指针参数,I2C 进行数据收发说白了就是消息的传递,Linux内核使用i2c_msg 结构体来描述一个消息。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			*/
};

代码

i2c_client.c
#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 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,},// [1] = {//     .addr   = ft5x06_client->addr,//     .flags  = 1,//     .len    = sizeof(data),//     .buf    = &data,// }};buff[0] = reg_addr;memcpy(&buff[1], &data, len);i2c_transfer(ft5x06_client->adapter, msgs, 1);}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;}struct of_device_id  ft5x06_id[] = {{.patible = "edt,ft5x0x_ts", 0},{.patible = "edt,ft5x0x_ts", 0},{.patible = "edt,ft5x0x_ts", 0},{}
};struct i2c_device_id  ft5x06_id_ts[] = {{"xxxxx", 0},{},
};int ft5x06_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id){int ret;printk("this is  ft5x06_probe \n ");ft5x06_client = i2c_client;//因为我们要在别的函数里面用到这个client,所以我们要把他们复制进来//地址为0x80的寄存器里面写入0x4b的数据ft5x06_write_reg(0x80, 0x4a, 1);ret = ft5x06_read_reg(0x80);printk("ret is %#x \n", ret);return 0;
}int ft5x06_remove(struct i2c_client *i2c_client){printk("ft5x06_remove \n ");return 0;
}static struct i2c_driver ft5x06_driver = {.probe = ft5x06_probe,.remove = ft5x06_remove,.id_table = ft5x06_id_ts,.driver = {.owner = THIS_MODULE,.name = "ft5x06_test",.of_match_table = ft5x06_id,},
};static int ft5x06_driver_init(void){int ret;printk("ft5x06_driver_init \n");ret = i2c_add_driver(&ft5x06_driver);if (ret < 0){printk("i2c_add_driver is error \n ");return  ret ;}printk("i2c_add_driver is suess \n");return 0;}static void ft5x06_driver_exit(void){printk("ft5x06_driver_exit \n");i2c_del_driver(&ft5x06_driver);}module_init(ft5x06_driver_init);
module_exit(ft5x06_driver_exit);
MODULE_LICENSE("GPL");

更多推荐

驱动程序,通讯,i2c

本文发布于:2023-05-20 23:53:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/156751.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:驱动程序   通讯   i2c

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!