I2C 使用
前言
AIO-3128C 開(kāi)發(fā)板上有 4 個(gè)片上 I2C 控制器。本文主要描述如何在該開(kāi)發(fā)板上配置 I2C。
配置 I2C 可分為兩大步驟:
定義和注冊(cè) I2C 設(shè)備
定義和注冊(cè) I2C 驅(qū)動(dòng)
下面以配置 lt8641ex 為例。
定義和注冊(cè) I2C 設(shè)備
在注冊(cè)I2C設(shè)備時(shí),需要結(jié)構(gòu)體 i2c_client 來(lái)描述 I2C 設(shè)備。然而在標(biāo)準(zhǔn)Linux中,用戶只需要提供相應(yīng)的 I2C 設(shè)備信息,Linux就會(huì)根據(jù)所提供的信息構(gòu)造 i2c_client 結(jié)構(gòu)體。
用戶所提供的 I2C 設(shè)備信息以節(jié)點(diǎn)的形式寫到 dts 文件中,如下所示:
&i2c0 { status = "okay"; lt8641ex@3f { compatible = "firefly,lt8641ex"; gpio-sw = <&gpio7 GPIO_B2 GPIO_ACTIVE_LOW>; reg = <0x3f>; }; };
定義和注冊(cè) I2C 驅(qū)動(dòng)
定義 I2C 驅(qū)動(dòng)
在定義 I2C 驅(qū)動(dòng)之前,用戶首先要定義變量 of_device_id 和 i2c_device_id 。of_device_id 用于在驅(qū)動(dòng)中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
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指示該驅(qū)動(dòng)所支持的設(shè)備。
注冊(cè) I2C 驅(qū)動(dòng)
使用i2c_add_driver函數(shù)注冊(cè) I2C 驅(qū)動(dòng)。
i2c_add_driver(<8641ex_device_driver);
在調(diào)用 i2c_add_driver 注冊(cè) I2C 驅(qū)動(dòng)時(shí),會(huì)遍歷 I2C 設(shè)備,如果該驅(qū)動(dòng)支持所遍歷到的設(shè)備,則會(huì)調(diào)用該驅(qū)動(dòng)的 probe 函數(shù)。
通過(guò) I2C 收發(fā)數(shù)據(jù)
在注冊(cè)好 I2 C 驅(qū)動(dòng)后,即可進(jìn)行 I2C 通訊。
向從機(jī)發(fā)送信息
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; }
向從機(jī)讀取信息
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] 是要向從機(jī)發(fā)送的信息,告訴從機(jī)主機(jī)要讀取信息。msgs[1] 是主機(jī)向從機(jī)讀取到的信息。
至此,主機(jī)可以使用函數(shù) i2c_master_reg8_send 和 i2c_master_reg8_recv 和從機(jī)進(jìn)行通訊。
實(shí)際通訊示例
例如主機(jī)和 LT8641EX 通訊,主機(jī)向 LT8641EX 發(fā)送信息,設(shè)置 LT8641EX 使用通道 1:
int channel=1;i2c_master_reg8_send(g_lt8641ex->client, 0x00, &channel,1, 100000);
注:通道寄存器的地址為0x00。 主機(jī)向從機(jī) LT8641EX 讀取當(dāng)前使用的通道:
u8 ch = 0xfe;i2c_master_reg8_recv(g_lt8641ex->client, 0x00, &ch,1, 100000);
注:ch用于保存讀取到的信息。
-
Linux
+關(guān)注
關(guān)注
87文章
11459瀏覽量
212786 -
嵌入式主板
+關(guān)注
關(guān)注
7文章
6096瀏覽量
36138 -
Firefly
+關(guān)注
關(guān)注
2文章
541瀏覽量
7398
發(fā)布評(píng)論請(qǐng)先 登錄
I2C的簡(jiǎn)介
i2c總線ppt(I2C總線器件應(yīng)用)
I2C總線規(guī)范與I2C器件C51讀寫程序
I2C Guid I2C指南
英創(chuàng)信息技術(shù)JAVA操作英創(chuàng)主板I2C接口簡(jiǎn)介

Firefly-RK3128主板I2C控制器

fireflyAIO-3288C主板I2C簡(jiǎn)介
fireflyAIO-3288J主板I2C簡(jiǎn)介
fireflyAIO-3128C主板啟動(dòng)模式介紹
fireflyAIO-3128C主板串口調(diào)試介紹

硬件I2C與模擬I2C

ESP32 之 ESP-IDF 教學(xué)(六)——I2C數(shù)據(jù)總線(I2C)

評(píng)論