i2c 使用
前言
aio-3288j 开发板上有 6 个片上 i2c 控制器。本文主要描述如何在该开发板上配置 i2c。
配置 i2c 可分为两大步骤:
定义和注册 i2c 设备
定义和注册 i2c 驱动
下面以配置 lt8641ex 为例。
定义和注册 i2c 设备
在注册i2c设备时,需要结构体 i2c_client 来描述 i2c 设备。然而在标准linux中,用户只需要提供相应的 i2c 设备信息,linux就会根据所提供的信息构造 i2c_client 结构体。
用户所提供的 i2c 设备信息以节点的形式写到 dts 文件中,如下所示:
&i2c1 { status = okay; lt8641ex@3f { compatible = firefly,lt8641ex; gpio-sw = ; reg = ; }; rtc@51 { compatible = nxp,pcf8563; reg = ; }; };
定义和注册 i2c 驱动
定义 i2c 驱动
在定义 i2c 驱动之前,用户首先要定义变量 of_device_id 和 i2c_device_id 。of_device_id 用于在驱动中调用dts文件中定义的设备信息,其定义如下所示:
static const struct of_device_id of_rk_lt8641ex_match[]={ { .compatible = firefly,lt8641ex }, { /* sentinel */ } };
定义变量 i2c_device_id:
static const struct i2c_device_id lt8641ex_id[] = { { lt8641ex, 0 }, { } }; module_device_table(i2c, lt8641ex_id);
i2c_driver 如下所示:
static struct i2c_driver lt8641ex_device_driver = { .driver = { .name = lt8641ex, .owner = this_module, .of_match_table = of_rk_lt8641ex_match, }, .probe = lt8641ex_probe, .remove = lt8641ex_remove, .suspend = lt8641ex_suspend, .resume = lt8641ex_resume, .id_table = lt8641ex_id,};
注:变量id_table指示该驱动所支持的设备。
注册 i2c 驱动
使用i2c_add_driver函数注册 i2c 驱动。
i2c_add_driver(<8641ex_device_driver);
在调用 i2c_add_driver 注册 i2c 驱动时,会遍历 i2c 设备,如果该驱动支持所遍历到的设备,则会调用该驱动的 probe 函数。
通过 i2c 收发数据
在注册好 i2 c 驱动后,即可进行 i2c 通讯。
向从机发送信息
static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate) { struct i2c_adapter *adap=client->adapter; struct i2c_msg msg; int ret; char *tx_buf = (char *)kzalloc(count + 1, gfp_kernel); if(!tx_buf) return -enomem; tx_buf[0] = reg; memcpy(tx_buf+1, buf, count); msg.addr = client->addr; msg.flags = client->flags; msg.len = count + 1; msg.buf = (char *)tx_buf; msg.scl_rate = scl_rate; ret = i2c_transfer(adap, &msg, 1); kfree(tx_buf); return (ret == 1) ? count : ret; }
向从机读取信息
static int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate) { struct i2c_adapter *adap=client->adapter; struct i2c_msg msgs[2]; int ret; char reg_buf = reg; msgs[0].addr = client->addr; msgs[0].flags = client->flags; msgs[0].len = 1; msgs[0].buf = ®_buf; msgs[0].scl_rate = scl_rate; msgs[1].addr = client->addr; msgs[1].flags = client->flags | i2c_m_rd;msgs[1].len = count; msgs[1].buf = (char *)buf; msgs[1].scl_rate = scl_rate; ret = i2c_transfer(adap, msgs, 2); return (ret == 2)? count : ret; }
注:msgs[0] 是要向从机发送的信息,告诉从机主机要读取信息。msgs[1] 是主机向从机读取到的信息。
至此,主机可以使用函数 i2c_master_reg8_send 和 i2c_master_reg8_recv 和从机进行通讯。
实际通讯示例
例如主机和 lt8641ex 通讯,主机向 lt8641ex 发送信息,设置 lt8641ex 使用通道 1:
int channel=1; i2c_master_reg8_send(g_lt8641ex->client, 0x00, &channel,1, 100000);
注:通道寄存器的地址为0x00。 主机向从机 lt8641ex 读取当前使用的通道:
u8 ch = 0xfe; i2c_master_reg8_recv(g_lt8641ex->client, 0x00, &ch,1, 100000);
注:ch用于保存读取到的信息。
压力变送器检定前的准备工作
苏州移动全程进行4K超清直播,通过移动的和直播全程观看工程启动仪式
苹果春季新品iPad mini 6亮点汇总
爱立信敢放出狠话底气何在
WorldVi宣布推出VizMove 2.0,一项基于位置和远程VR体验而设计的服务
fireflyAIO-3288J主板I2C简介
开博尔4KUHD蓝光播放器K9Pro评测 值不值得买
[图文]远距离遥控编解码发射接收组件电路
华为5g技术怎么样
《旭日X3派开发小技巧》-- 备份与恢复SD卡镜像
无人驾驶车新品发布频繁 行业配套技术日渐受欢迎
mpu6500和mpu6000哪个好
鑫创SSS1530 Type-c耳机、安卓耳机转接头方案
从三个角度看安防巨头为何入局智能锁市场
开尔文双电桥测电阻
怎样降低插件绕线电感发热的问题
英伟达市值暴跌 人工智能神话将要破灭
雷克沙进军内存市场,内存市场大风暴
美国宣称不在乎苹果销量,坚持封禁微信
5G与化工的结合会带来什么变化