Microchip社のI2C-EEPROMに対応するライブラリを作ってみた。
全ての製品を試したわけではないが基本的にページサイズとメモリサイズが合っていれば動作するはず。容量拡大のために同一仕様のEEPROMを複数搭載した回路にも対応している。
begin/read/writeの3関数しかないので説明しなくても簡単に使えると思う。
【スケッチ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <Wire.h> #include "eeprom24.h" DECLARE_AT24C32(Wire) eeprom; #define MEM_ADDR 0 void setup(void) { uint8_t conf[32]; eeprom.begin(0); /* device address is 0x50 */ /* read eeprom */ eeprom.read(MEM_ADDR, conf, sizeof(conf)); /* write eeprom */ eeprom.write(MEM_ADDR, conf, sizeof(conf)); } void loop(void) { } |
【ライブラリ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/* eeprom24.h - Microchip I2C EEPROM Library for ARDUINO Copyright (c) 2024 Sasapea's Lab. All right reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ #pragma once #include <stdint.h> #include <stdbool.h> #define DECLARE_AT24C01(instance) EEPROM24<typeof(instance), instance, 8, 7> #define DECLARE_AT24C02(instance) EEPROM24<typeof(instance), instance, 8, 8> #define DECLARE_AT24C04(instance) EEPROM24<typeof(instance), instance, 16, 9> #define DECLARE_AT24C08(instance) EEPROM24<typeof(instance), instance, 16, 10> #define DECLARE_AT24C16(instance) EEPROM24<typeof(instance), instance, 16, 11> #define DECLARE_AT24C32(instance) EEPROM24<typeof(instance), instance, 32, 12> #define DECLARE_AT24C64(instance) EEPROM24<typeof(instance), instance, 32, 13> #define DECLARE_AT24C128(instance) EEPROM24<typeof(instance), instance, 64, 14> #define DECLARE_AT24C256(instance) EEPROM24<typeof(instance), instance, 64, 15> #define DECLARE_AT24C512(instance) EEPROM24<typeof(instance), instance, 128, 16> #define DECLARE_AT24CM01(instance) EEPROM24<typeof(instance), instance, 256, 17> #define DECLARE_AT24CM02(instance) EEPROM24<typeof(instance), instance, 256, 18> #define DECLARE_EEPROM24(instance, page_size, addr_bits) EEPROM24<typeof(instance), instance, page_size, addr_bits> template<typename T, T& WIRE, size_t PAGE_SIZE, size_t ADDR_BITS> class EEPROM24 { public: static constexpr uint32_t WIRE_CLOCK = 400000; enum { ERR_NONE = 0, ERR_IO = 4, ERR_ARG = 8, }; void begin(uint8_t index = 0, uint8_t nchips = 1) { /* Initialize Wire with setup() */ uint8_t mchips; if (ADDR_BITS <= 16) { index &= 7; mchips = 8 - index; _address = DEVICE | index; } else if (ADDR_BITS <= 18) { index &= (1 << (19 - ADDR_BITS)) - 1; mchips = (20 - ADDR_BITS) - index; _address = DEVICE | (index << (ADDR_BITS - 16)); } else { mchips = 0; _address = DEVICE; } _romsize = (1UL << ADDR_BITS) * (nchips <= mchips ? nchips : mchips); _errcode = 0; } bool read(uint32_t addr, void *buf, size_t len) { if ((addr + len > _romsize) || (!buf && len)) { _errcode = ERR_ARG; return false; } uint8_t *ptr = (uint8_t *)buf; while (len) { size_t n = PAGE_SIZE - (addr & (PAGE_SIZE - 1)); if (len < n) n = len; if (!read0(addr, ptr, n)) return false; ptr += n; addr += n; len -= n; } _errcode = ERR_NONE; return true; } bool write(uint32_t addr, const void *buf, size_t len) { if ((addr + len > _romsize) || (!buf && len)) { _errcode = ERR_ARG; return false; } const uint8_t *ptr = (const uint8_t *)buf; while (len) { size_t n = PAGE_SIZE - (addr & (PAGE_SIZE - 1)); if (len < n) n = len; if (!write0(addr, ptr, n)) return false; ptr += n; addr += n; len -= n; delay(20); } _errcode = ERR_NONE; return true; } int errcode(void) { return _errcode; } private: uint8_t devaddr(uint32_t addr) { return (_address & ~7) | ((_address + (addr >> (ADDR_BITS <= 16 ? ADDR_BITS : 16))) & 7); } bool read0(uint32_t addr, void *buf, size_t len) { if (!write0(addr, nullptr, 0, false)) return false; WIRE.requestFrom(devaddr(addr), len); return (_errcode = WIRE.readBytes((uint8_t *)buf, len) == len ? ERR_NONE : ERR_IO) == ERR_NONE; } bool write0(uint32_t addr, const void *buf, size_t len, uint8_t sendStop = true) { WIRE.beginTransmission(devaddr(addr)); if ((_errcode = WIRE.endTransmission(false)) != ERR_NONE) return false; if (ADDR_BITS < 12) { /* AT24C01 - AT24C16 */ uint8_t wordaddr[] = { (uint8_t)addr }; WIRE.beginTransmission(devaddr(addr)); WIRE.write(wordaddr, sizeof(wordaddr)); } else { /* AT24C32 - AT24CM02 */ uint8_t wordaddr[] = { (uint8_t)(addr >> 8), (uint8_t)addr }; WIRE.beginTransmission(devaddr(addr)); WIRE.write(wordaddr, sizeof(wordaddr)); } if (buf && len) WIRE.write((const uint8_t *)buf, len); return (_errcode = WIRE.endTransmission(sendStop)) == ERR_NONE; } static constexpr uint8_t DEVICE = 0x50; uint8_t _address; uint32_t _romsize; int _errcode; }; |