AT24C256是一個Atmel公司的EEPROM存儲芯片,容量是256K個bit(也就是32K字節),I2C接口,而樹莓派正好有I2C接口,如下圖藍框中的4個IO口,
把AT24C256和這4個口接在一起,這樣硬件就準備好了。
本文講述如何使用樹莓派3B來讀寫AT24C256,其它樹莓派版本也是類似的。有2種方法:
- 使用樹莓派CPU的I2C控制器來讀寫
- 使用AT24C256在Linux系統中映射的文件來讀寫
讀寫AT24C256
1. 使能I2C接口
在樹莓派系統終端下運行以下命令,
sudo raspi-config
然后彈出以下界面,按上下鍵來選擇“3 Interface Options”并回車,
在新界面里選擇“I4 I2C”并回車,
在新界面里按左右鍵來選擇“Yes”
最后回到開始的界面,按左右鍵選擇Finish并回車,
這樣I2C功能就開啟了。
2. 使用I2C控制器讀寫
這里使用i2c-tools來操作,樹莓派默認已經安裝了這個工具,如果沒有就使用下面命令進行安裝,
sudo apt install i2c-tools
i2c-tools提供了好幾個工具:
- i2cdetect
- i2cdump
- i2cget
- i2cset
- i2c-stub-from-dump
- i2ctransfer
先使用i2cdetect來探測有多少I2C控制器,如下,顯示有2個,
同時在/dev/下也能看到這2個I2C控制器,連接上AT24C256后則會使用i2c-1,
i2cget,i2cset和i2ctransfer都是用來通過I2C控制器來讀寫eeprom,區別是:i2cget和i2cset適合那種地址是一個字節的eeprom芯片,如AT24C02這種,但是本文使用的是AT24C256,地址需要2個字節,所以只能使用i2ctransfer,同樣它也能讀一字節地址的eeprom,
i2ctransfer幫助信息如下,
寫數據
使用下面命令進行寫,"0x50"是芯片的I2C地址, "0x00 0x05"是eeprom內部的地址,該地址可以存放數據,
i2ctransfer 1 w6@0x50 0x00 0x05 0x55 0x66 0x77 0x88
PS:該命令意思是從eeprom的0x0005位置開始存放4個字節,0x55 0x66 0x77 0x88,不過對于i2ctransfer來說,它只是傳輸6個字節
顯示如下,
PS:如果想寫代碼來操作,可以參考i2c-tools的源碼
讀數據
寫完后再執行下面命令進行讀,注意這里先要寫2個字節,就是eeprom的內部地址0x0005,然后再讀4個字節,
i2ctransfer 1 w2@0x50 0x00 0x05 r4
顯示如下,可以看到讀取出來的數據和寫入的是一樣的,
3. 使用EEPROM在Linux系統中映射的文件來讀寫(推薦)
這個也是推薦的方法,因為EEPROM映射成一個文件,這樣可以使用常規的open, read和write來讀寫EEPROM,但是需要注意的是:這個辦法和使用控制器的辦法同時只能使用一個,因為映射之后控制器會被占用,就不能直接用控制器去讀寫了。
先執行下面的命令加載AT24的模塊,這個模塊是AT24系列芯片的驅動,
sudo modprobe at24
加載完畢后,在/sys/class/i2c-adapter/i2c-1/下會出現new_device和delete_device,
然后再運行sudo -i
進入root模式,這點很重要,最后執行下面的命令,這樣可以把芯片型號和I2C地址傳給驅動,
echo "24c256 0x50" > /sys/class/i2c-adapter/i2c-1/new_device
實際操作如下,
最后執行exit
回到用戶模式。
此時在/sys/class/i2c-adapter/i2c-1/能看到新增的目錄1-0050,"1"表示是i2c-1,"0050"表示設備的i2c地址是0x50,
cd進入1-0050目錄,可以看到有個文件eeprom,這個就是AT24C256映射的文件,
PS:如果想取消映射,可以執行下面命令進行操作,
sudo -i
echo "0x50" > /sys/class/i2c-adapter/i2c-1/delete_device
使用代碼進行讀寫
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>int main() {int fd; // 文件描述符char buffer[256]; // 用于讀寫的緩沖區off_t offset;// 以讀寫模式打開文件fd = open("/sys/class/i2c-adapter/i2c-1/1-0050/eeprom", O_RDWR, 0644);if (fd == -1) {perror("無法打開文件");exit(EXIT_FAILURE);}// 向文件寫入數據uint8_t wr_buf[4] = {0x11, 0x12, 0x55, 0x66};ssize_t bytes_written = write(fd, wr_buf, 4);if (bytes_written == -1) {perror("寫入文件時出錯");close(fd);exit(EXIT_FAILURE);}printf("成功寫入 %ld 字節\n", bytes_written);// 使用lseek改變文件讀寫位置到文件開頭offset = lseek(fd, 0, SEEK_SET);if (offset == -1) {perror("lseek失敗");close(fd);exit(EXIT_FAILURE);}// 從文件讀取數據到緩沖區ssize_t bytes_read = read(fd, buffer, 4);if (bytes_read == -1) {perror("讀取文件時出錯");} else {for (uint32_t i = 0; i < 4; ++i){printf("==> 0x%x\n", buffer[i]);}}// 關閉文件if (close(fd) == -1) {perror("關閉文件時出錯");exit(EXIT_FAILURE);}return 0;
}
代碼以0x0000位置為起始地址,寫入"0x11 0x12 0x55 0x66",編譯后運行程序并運行,
可以看到讀寫都沒問題,同時也能發現映射后對eeprom的操作和讀寫一個普通文件沒有區別。
PS:如果想修改起始地址,可以使用lseek函數來設置位置。
總結
本文講述了2種方法來讀寫AT24C256,更推薦文件方式的辦法,這種更符合Linux“萬物皆文件”的思想。