Skip to content

Commit b7de1f4

Browse files
committed
Added 24LC32 EEPROM I2C example
1 parent 4c3a3dc commit b7de1f4

File tree

9 files changed

+192
-0
lines changed

9 files changed

+192
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ App|Description
159159
[ht16k33_i2c](i2c/ht16k33_i2c) | Drive a 4 digit 14 segment LED with an HT16K33.
160160
[slave_mem_i2c](i2c/slave_mem_i2c) | i2c slave example where the slave implements a 256 byte memory.
161161
[slave_mem_i2c_burst](i2c/slave_mem_i2c) | i2c slave example where the slave implements a 256 byte memory. This version inefficiently writes each byte in a separate call to demonstrate read and write burst mode.
162+
[24lc32_i2c](i2c/24lc32_i2c) | Read and write data to 24LC32 EEPROM via I2C.
162163

163164
### Interpolator
164165

i2c/24lc32_i2c/24lc32_i2c.fzz

51 KB
Binary file not shown.

i2c/24lc32_i2c/24lc32_i2c.png

271 KB
Loading

i2c/24lc32_i2c/24lc32_i2c_lib.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include <stdio.h>
2+
#include "pico/stdlib.h"
3+
#include "hardware/i2c.h"
4+
5+
// This is the max number of bytes which can be written at once during a page write
6+
#define MAX_PAGE_WRITE 32
7+
8+
// Acknowledge polling can be used to see when a write cycle is complete
9+
// Wait for the i2c slave to acknowledge our empty write
10+
bool ack_poll(uint8_t i2c_addr) {
11+
int timeout = 100;
12+
for (int i = 0; i < timeout; i++) {
13+
if (i2c_write_blocking(i2c_default, i2c_addr, NULL, 1, false) == 1) {
14+
return true;
15+
}
16+
sleep_ms(1);
17+
}
18+
printf("ack timeout\n");
19+
return false;
20+
}
21+
22+
// Read num bytes of memory starting at given address into result
23+
void read_eeprom(uint16_t address, uint8_t *result, uint16_t num, uint8_t i2c_addr) {
24+
for (int i = 0; i < num; i++) {
25+
uint8_t byte1 = (uint8_t)(address >> 8);
26+
uint8_t byte2 = (uint8_t)(address);
27+
28+
uint8_t buf[2] = {byte1, byte2};
29+
30+
i2c_write_blocking(i2c_default, i2c_addr, buf, 2, true);
31+
i2c_read_blocking(i2c_default, i2c_addr, (result + i), 1, false);
32+
33+
address++;
34+
}
35+
}
36+
37+
// Write a single byte of data at a specified address in memory
38+
void byte_write_eeprom(uint16_t address, uint8_t data, uint8_t i2c_addr) {
39+
uint8_t byte1 = (uint8_t)(address >> 8);
40+
uint8_t byte2 = (uint8_t)(address);
41+
42+
uint8_t buf[3] = {byte1, byte2, data};
43+
44+
i2c_write_blocking(i2c_default, i2c_addr, buf, 3, false);
45+
46+
// ack_poll to wait for write to be complete
47+
ack_poll(i2c_addr);
48+
}
49+
50+
// Write a block of data to eeprom
51+
// Returns false if more than MAX_PAGE_WRITE bytes passed in, which would lead to overwriting of data
52+
bool page_write_eeprom(uint16_t address, uint8_t *data, uint8_t num, uint8_t i2c_addr) {
53+
if (num > MAX_PAGE_WRITE) {
54+
printf("Tried to write more than 32 bytes.\n");
55+
return false;
56+
}
57+
58+
uint8_t byte1 = (uint8_t)(address >> 8);
59+
uint8_t byte2 = (uint8_t)(address);
60+
uint8_t buf[2 + num];
61+
buf[0] = byte1;
62+
buf[1] = byte2;
63+
64+
// transfer data into buffer
65+
for (int i = 0; i < num; i++) {
66+
buf[i + 2] = data[i];
67+
}
68+
69+
i2c_write_blocking(i2c_default, i2c_addr, buf, 2 + num, false);
70+
71+
// ack_poll to wait for write to be complete
72+
ack_poll(i2c_addr);
73+
return true;
74+
}
75+
76+
// Initialise i2c for given gpio at given frequency
77+
void eeprom_init(int sda_pin, int scl_pin, int freq, i2c_inst_t *i2c_instance) {
78+
i2c_init(i2c_default, freq);
79+
80+
gpio_set_function(sda_pin, GPIO_FUNC_I2C);
81+
gpio_set_function(scl_pin, GPIO_FUNC_I2C);
82+
gpio_pull_up(sda_pin);
83+
gpio_pull_up(scl_pin);
84+
}
85+

i2c/24lc32_i2c/24lc32_i2c_lib.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef PICO_I2C_EEPROM_LIB_H
2+
#define PICO_I2C_EEPROM_LIB_H
3+
4+
#include "hardware/i2c.h"
5+
6+
void read_eeprom(uint16_t address, uint8_t *result, uint16_t num, uint8_t i2c_addr);
7+
void byte_write_eeprom(uint16_t address, uint8_t data, uint8_t i2c_addr);
8+
bool page_write_eeprom(uint16_t address, uint8_t *data, uint8_t num, uint8_t i2c_addr);
9+
bool ack_poll(uint8_t i2c_addr);
10+
void eeprom_init(int sda_pin, int scl_pin, int freq, i2c_inst_t *i2c_instance);
11+
12+
#endif

i2c/24lc32_i2c/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Add libary
2+
add_library(24lc32_i2c_lib INTERFACE)
3+
target_sources(24lc32_i2c_lib INTERFACE
4+
${CMAKE_CURRENT_LIST_DIR}/24lc32_i2c_lib.c
5+
)
6+
target_include_directories(24lc32_i2c_lib INTERFACE
7+
${CMAKE_CURRENT_LIST_DIR}
8+
)
9+
target_link_libraries(24lc32_i2c_lib INTERFACE
10+
pico_stdlib
11+
hardware_i2c
12+
)
13+
14+
# Add executable
15+
add_executable(24lc32_i2c
16+
example.c
17+
)
18+
19+
target_link_libraries(24lc32_i2c
20+
24lc32_i2c_lib
21+
pico_stdlib
22+
hardware_i2c
23+
)
24+
25+
pico_add_extra_outputs(24lc32_i2c)

i2c/24lc32_i2c/READ_ME.adoc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
= Reading and writing 24LC32 EEPROM via I2C
2+
3+
This example code demonstrates how to read and write data from 24LC32 EEPROM. It contains a library with functions for reading data, writing single bytes, and writing pages, and an example which uses these functions.
4+
5+
== Wiring information
6+
7+
[[24lc32_i2c_wiring]]
8+
[pdfwidth=75%]
9+
.Wiring Diagram for 24LC32 EEPROM via I2C.
10+
image::24lc32_i2c.png[]
11+
12+
== List of Files
13+
14+
CMakeLists.txt:: CMake file to incorporate the example into the examples build tree.
15+
24lc32_i2c_lib.c:: Library containing functions to interact with 24LC32 eeprom via I2C.
16+
24lc32_i2c_lib.h:: Header file containing function declarations for the 24LC32 library.
17+
example.c:: The example code.
18+
19+
== Bill of Materials
20+
21+
.A list of materials required for the example
22+
[[24lc32_i2c-bom-table]]
23+
[cols=3]
24+
|===
25+
| *Item* | *Quantity* | Details
26+
| Breadboard | 1 | generic part
27+
| Raspberry Pi Pico (any) | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
28+
| 24LC32-based breakout board | 1 | https://www.adafruit.com/product/5146
29+
| M/M Jumper wires | 4 | generic part
30+
|===

i2c/24lc32_i2c/example.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <stdio.h>
2+
#include "pico/stdlib.h"
3+
#include "hardware/i2c.h"
4+
#include "24lc32_i2c_lib.h"
5+
6+
// Default I2C address of 24LC32
7+
#define I2C_ADDRESS 0x50
8+
9+
int main() {
10+
stdio_init_all();
11+
12+
eeprom_init(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, 400*1000, i2c_default);
13+
14+
// Write the byte at location 0x00 to 0
15+
byte_write_eeprom(0x00, 0, I2C_ADDRESS);
16+
17+
// Make an array of integers from 1 to 31 and write the array to eeprom starting at 0x01
18+
uint8_t data_list[31];
19+
for (int i = 0; i < 31; i++) {
20+
data_list[i] = i + 1;
21+
}
22+
page_write_eeprom(0x01, data_list, 31, I2C_ADDRESS);
23+
24+
// Read eeprom, and ensure we observe ascending integers from 0 to 31
25+
uint8_t result[32];
26+
read_eeprom(0x0, result, 32, I2C_ADDRESS);
27+
28+
for (int i = 0; i < 32; i++) {
29+
printf("read: %i, expected: %i\n", result[i], i);
30+
if (result[i] != i) {
31+
printf("Unexpected read!\n");
32+
return 1;
33+
}
34+
}
35+
36+
printf("Test passed!\n");
37+
return 0;
38+
}

i2c/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ if (TARGET hardware_i2c)
1212
add_subdirectory_exclude_platforms(pcf8523_i2c)
1313
add_subdirectory_exclude_platforms(ht16k33_i2c)
1414
add_subdirectory_exclude_platforms(slave_mem_i2c)
15+
add_subdirectory_exclude_platforms(24lc32_i2c)
1516
else()
1617
message("Skipping I2C examples as hardware_i2c is unavailable on this platform")
1718
endif()

0 commit comments

Comments
 (0)