本章內容對應視頻講解鏈接(在線觀看):![]() 我們可以先來體驗一下,在 Linux 上操作 I2C 是多么的容易,我們可以先來看一下系統里面都有哪些 I2C的節點,這里以終結者 imx6ull 開發板為例。如下圖所示: ![]() Linux 有一個非常重要的概念叫一切皆文件,那么我們能不能在應用層通過 open 這些節點來操作 I2C 來跟外設 I2C 通信的芯片進行一個數據交流呢?當然是可以的,我們來一起看一下,這里我們以 7 寸 RGB 屏幕上的觸摸芯片 FT5X06 為例,迅為所有開發板都是支持迅為 7 寸 RGB 屏幕屏的,所有都是可以進行這個驗的。迅為的屏幕除了 4.3 寸和 10.1 寸屏外,其他尺寸的屏幕的觸摸芯片都是 FT5X06,都是可以進行這個實驗的。 本次實驗我們使用的從機為 FT5X06 觸摸芯片。 FT5x06 系列 ICs 是單芯片電容式觸摸屏控制器 IC,帶有一個內置的 8 位微控制器單元(MCU)。采用互電容的方法,在配合的相互的電容式觸摸面板,它支持真正的多點觸摸功能。FT5x06 具有用戶友好的輸入的功能,這可以應用在許多便攜式設備,例如蜂窩式電話,移動互聯網設備,上網本和筆記本個人電腦。FT5x06 系列 IC 包括 FT5206/FT5306/FT5406。FT5x06 可以捕獲 5 個觸摸點,編寫驅動時,只要去獲取這幾個點的數據,然后上報就可以了。之后我們的實驗也是讀取的其中一個寄存器,如下圖所示,我們可以在 FT5X06 的數據手冊上查找到。 ![]() 我們打開 imx6ull 開發板的底板原理圖,我們通過原理圖先來確定一下 FT5X06 使用的是哪個 I2C,通過下面的截圖我們可以看到在終結者開發板上觸摸芯片 FT5X06 使用的是 I2C2。 ![]() 我們輸入如下圖所示命令,查找 I2C2 對應的設備節點,我們查找如下圖所示: ![]() 所以 I2C2 設備的地址是 0038,對應的節點是 dev 下面的 i2c-1。如果我們要在終結者的上和觸摸芯片FT5X06 進行通信,只要操作 dev 下的 i2c-1 這個節點就可以了。 那我們怎么在應用層操作 I2C 呢?應用層操作 I2C 是以數據包進行交流的,所以我們在應用層就要進行封包的操作。數據包對應的結構體是 i2c_rdwr_ioctl_data,這個結構體定義在 include\uapi\linux\i2c-dev.h 下面:定義如下: /* 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_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 */ }; 結構體成員 addr 是我們從機的地址,flags 為讀寫標志位,如果 flags 為 1,則為讀,反之為 0,則為寫。len 為 buf 的大小,單位是字節。當 flags 為 1 是,buf 就是我們要接收的數據,當 flags 為 0 時,就是我們要發送的數據。 那么我們要怎么設計我們的程序呢?我們來看一下。 /* * @Author: topeet * @Description: 應用程序與 I2c 通信 */ #include #include #include #include #include #include #include #include #include #include int fd; int ret; /** * @description: i2c_read_data i2c 讀數據 * @param {unsignedint} slave_addr:從機設備的地址 * @param {unsignedchar} reg_addr:寄存器的地址 * @return {*} */ int i2c_read_data(unsigned int slave_addr, unsigned char reg_addr) { unsigned char data; //定義一個要發送的數據包 i2c_read_lcd struct i2c_rdwr_ioctl_data i2c_read_lcd; //定義初始化 i2c_msg 結構體 struct i2c_msg msg[2] = { [0] = { .addr = slave_addr, //設置從機額地址 .flags = 0, //設置為寫 .buf = ®_addr, //設置寄存器的地址 .len = sizeof(reg_addr)}, //設置寄存器的地址的長度 [1] = {.addr = slave_addr, //設置從機額地址 .flags = 1, //設置為讀 .buf = &data, //設置寄存器的地址 .len = sizeof(data)}, //設置寄存器的地址 }; //初始化數據包的數據 i2c_read_lcd.msgs = msg; //初始化數據包的個數 i2c_read_lcd.nmsgs = 2; //操作讀寫數據包 ret = ioctl(fd, I2C_RDWR, &i2c_read_lcd); if (ret < 0) { perror("ioctl error "); return ret; } return data; } int main(int argc, char *argv[]) { int TD_STATUS; //打開設備節點 fd = open("/dev/i2c-1", O_RDWR); if (fd < 0) { //打開設備節點失敗 perror("open error \n"); return fd; } while (1) { //i2C 讀從機地址為 0x38,寄存器地址為 0x02 的數據 //我們從數據手冊中得知 TD_STATUS 的地址為 0x02 TD_STATUS = i2c_read_data(0x38, 0x02); // 打印 TD_STATUS 的值 printf("TD_STATUS value is %d \n", TD_STATUS); sleep(1); } close(fd); return 0; } 編譯應用程序程序如下圖所示: ![]() 我們在掛載 nfs 以后,進入到共享目錄/mnt/nfs/imx6ull/38i2c 目錄下,運行應用程序,當我們沒有觸摸屏幕時,如下圖所示: ![]() 當我們用一根手指觸摸時,如下圖所示: ![]() 當我們用三根手指觸摸時,如下圖所示: ![]() 當我們用五根手指觸摸時,如下圖所示: ![]() 迅為imx6ull開發板: ![]() 核心板參數 尺寸:38mm*42mm PCB:6層 CPU:iMX6ULL ARM Cortex-A7架構 單核 iMX6ULL 商業級:內存:512M 存儲:8G EMMC iMX6ULL 工業級:內存:256M 存儲:512M FLASH 工作電壓:5V~16V 電壓供電 系統支持:Linux-QT系統;Ubuntu core系統;Youcto系統;Buildroot系統; 商業級運行溫度:-20℃ ~ +80℃ 工業級運行溫度:-40℃ ~ +80℃ 引腳間距:1.27mm 引角擴展:i.MX6功能全部引出,146PIN腳 連接方式:郵票孔 底板參數 尺寸:12*19cm PCB:2層 POWER:5V~16V電壓供電 SWITCH:電源開關 EEPROM 存儲:256字節,掉電后數據不丟失 4G模塊:1個 全網通 (選配) WIFI藍牙模塊:WIFI/藍牙二合一模塊,工作頻段 2.4GHz,支持 IEEE802.11bgn 等標準,支持藍牙 4.0 協議。 LVDS接口:1路(一個是標準HDMI 座(CON3),另一個是 30pin 的 FPC 座(J18), 兩個接口實際上是同一路 LVDS 信號,用來連接迅為電子的 LVDS 屏幕) RGB接口:1路 CAN:2 路 CAN 總線接口 RS485:1 路 RS485 總線接口 MIC:支持錄音輸入 PHONE:支持耳機輸出 USB OTG:1路 USB HOST:2路 USB-UART:1路 mini HDMI:1個(一路標準MINI-HDMI 接口,i.MX6ULL處理器本身沒有支持HDMI,通過一個 RGB 轉 HDMI 的芯片擴展出HDMI接口,通過該接口來連接HDMI顯示器。 ) 網口:2路百兆以太網,RJ45 接口 TF卡槽:1個標準TF卡接口 SIM卡槽:1個標準SIM卡接口 T&H接口:溫濕度傳感器接口 TTL/RS485接口:TTL/RS485接口二選一 BUZZER:1個蜂鳴器 IRDA:1個紅外一體化接收頭 ADC電位器:支持 DIP SWITCH:8位撥碼開關 JTAG:1個(可以通過下載/調試器來調試 i.MX6ULL 處理器) CAMERA接口:1個 支持500萬攝像頭 TTL串口接口:20PIN (gpio引出:兩個ad,一個spi,一路ttl。一路i2c,5個gpio,5v,3.3v電源) GPIO接口:20PIN(包括:兩路ADC,一路SPI,5個GPIO,一路TTL串口,一路I2C接口。) 重力加速度傳感器:支持 紅外接收模塊:支持 光環境傳感器:支持 實時時鐘:斷電后系統時間不丟失 LED:2個 按鍵:3個 |