2021年7月11日星期日

Arduino 讀寫外部EEPROM AT24C256


今天來實驗下IIC 讀寫外部EEPROM,這邊可能有部分讀者會覺得奇怪,阿arduino 本身不是就有了嗎?這句話是沒錯拉,但是畢竟是在MCU內部的,所以內部的EEPROM 也會有大小上的限制,先來看一下資料手冊,由於我是使用arduino NANO,我查NANO 上面的atmel MCU EEPROM的大小



這邊我們可以看到內建只有1kbytes,其實也不小了拉,但是總是有其他時候會需要,那我們先了解起來,萬一哪天需要紀錄一堆變數資料且,需要斷電再開啟時不被清除,就很需要了

 

開發環境

Arduino IDE 1.8.2

 

材料

1.      at24c256 模組

2.      Arduino Nano + Nano擴展板

3.      杜邦線 n

4.      邏輯分析儀 一台

 

接線說明

NANO

At24C256

Vcc

Vcc

A5

SCL

A4

SDA

Gns

Gnd

 

 

這邊說一下,再使用arduino IIC library 時,有些時候我們不知道是否是真的有把資料寫進去,所以需要使用邏輯分析儀(下次有空來寫一下使用教學),確認寫入讀取行為是符合時序。

Step1 模組認識

在使用模組前,一定要先大致上看一下資料手冊喔

使用電壓為DC 5V















設定晶片的位址是透過設定A1 A0 腳位





腳位功能描述




對應到模組上面腳位

模組腳位

功能

Vcc

電源

SCL

通訊用

SDA

通訊用

GND

電源

A0

設定位址

A1

設定位址

A2

沒功能

WP

寫入保護


 

大略看完資料手冊後,會發現A2?A2要做甚麼?其實A2沒功能啦


模組上面的接腳,可以透過使用短路帽來決定設備位址



這邊先用預設,如下圖



接下來如果At24C256 模組與NANO 接好後如下


 

Step2 寫程式-寫入資料

要怎麼寫入AT24C256,要看一下資料手冊的協定,如下圖


紅色的地方是晶片的位置,藍色的地方是晶片內部欲存放資料的位址,Data就是要存入的資料

如果模組上面的短路帽有照我的方式接的話,Device Address 0x50 ,接下來我們嘗試在晶片的

0x00位址寫入一個字元’H’

 

#include <Wire.h>

#define DeviceAddress 0x50

 void setup() {

  Wire.begin();

  Serial.begin(9600);

}

void loop() {

  I2C_write('H');

}

void I2C_write(unsigned char data)

{

  Wire.beginTransmission(0x50); // transmit to device

  Wire.write(0x00);              // sends one byte

  Wire.write(0x00);              // sends one byte

  Wire.write(data);              // sends one byte

  Wire.endTransmission();    // stop transmitting

}

燒錄進去後,我們用邏輯分析儀看是不是真的有arduino Nano是否有送出命令,寫入資料到

位址0x00 0x00的地方。

寫入資料到AT24C256(二進制顯示)


(hex ASCII顯示)

這邊我們可以看到已經將命令及資料設定出去了,且資料的通訊格式與資料手冊一樣,接下來開始寫讀回資料的功能。

  

Step3 寫程式-讀回資料

要從AT24C256讀取資料時的通訊方式,其實有兩種方式,但我是使用下圖的方式,先告訴AT24C256我要讀取的資料位址,再進行讀取該位址的資料。



根據上面Step2的程式碼,替換成下面

#include <Wire.h>

#define DeviceAddress 0x50

 

void setup() {

  Wire.begin();

  Serial.begin(9600);

}

void loop() {

  Serial.println((char)I2C_read());//將讀回來的資料轉成char 型態,並從序列埠印出

  delay(1000);

}

unsigned char I2C_read()

{

  unsigned char re_char;

  Wire.beginTransmission(0x50); // transmit to device #8

  Wire.write(0x00);              // sends one byte

  Wire.write(0x00);              // sends one byte

  Wire.endTransmission();    // stop transmitting

  Wire.requestFrom(0x50,1);  //Send Read requestFrom

  if (Wire.available())re_char = Wire.read();

  return re_char;

}

 

void I2C_write(unsigned char data)

{

  Wire.beginTransmission(0x50); // transmit to device

  Wire.write(0x00);              // sends one byte

  Wire.write(0x00);              // sends one byte

  Wire.write(data);              // sends one byte

  Wire.endTransmission();    // stop transmitting

}

從邏輯分析儀讀到的資料


(二進制)


hex + ASCII

你可以在圖片中發現,讀取時控制讀寫的位元變成1,紅線處

參考資料

 

使用到的函式說明

WireBeginTransmission

https://www.arduino.cc/en/Reference/WireBeginTransmission

WireEndTransmission

https://www.arduino.cc/en/Reference/WireEndTransmission

WireRequestFrom

https://www.arduino.cc/en/Reference/WireRequestFrom

 

  

參考資料

Atmel 328P AU

https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

At24c256

https://ww1.microchip.com/downloads/en/DeviceDoc/doc0670.pdf

Arduino 資料

https://playground.arduino.cc/Code/I2CEEPROM/

https://www.arduino.cc/en/Tutorial/LibraryExamples/MasterWriter

    https://www.hobbytronics.co.uk/arduino-external-eeprom


  



沒有留言:

發佈留言

打賞按讚