FRAM
- Войдите на сайт для отправки комментариев
Пт, 08/11/2019 - 00:25
Здравствуйте.
первоисточник https://github.com/nw-wind/FM24I2C https://habr.com/ru/post/319336/
библиотеки
#include "Wire.h"
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#ifndef _FM24I2C_H_
#define _FM24I2C_H_
class FM24I2C {
private:
int id;
public:
FM24I2C(int id_addr);
~FM24I2C();
void pack(int addr, void* data, int len); // Pack data into FRAM
int unpack(int addr, void* data, int len); // Unpack data from FRAM. Returns number of bytes read.
void inline writeUnsignedLong(int addr, unsigned long data) {
pack(addr, (void*)&data, sizeof(unsigned long));
}
unsigned long inline readUnsignedLong(int addr) {
unsigned long data;
return unpack(addr, (void*)&data, sizeof(unsigned long)) == sizeof(unsigned long) ? data : 0UL;
}
};
#endif
int#include "FM24I2C.h"
FM24I2C::FM24I2C(int id_addr) {
id=id_addr;
}
FM24I2C::~FM24I2C() {}
void FM24I2C::pack(int addr, void* data, int len) {
Wire.beginTransmission(id);
Wire.write((byte*)&addr,2);
Wire.write((byte*)data,len);
Wire.endTransmission(true);
}
int FM24I2C::unpack(int addr, void* data, int len) {
int rc;
byte *p;
Wire.beginTransmission(id);
Wire.write((byte*)&addr,2);
Wire.endTransmission(false);
Wire.requestFrom(id,len);
for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) {
*p=Wire.read();
}
return(rc);
}
Продолжу во втором топике.
Начну с того, что приложенный пример неправилен, там вытряхивается в сериал не буфер, а исходные массивы.
Если вытряхивать буфер, то там ничто.
писал разные тесты, чтобы вытряхивать элементы массива структур.
#include "FM24I2C.h" #define arr 27 FM24I2C fm(0x50); struct condition { uint32_t counter; float duration; float average; uint8_t avail; uint8_t mod_reset; }; condition tpa_status[arr]; condition buff ; unsigned long rc =0; void setup() { Serial.begin(115200); uint32_t size_my = sizeof(struct condition); Serial.print("size of structure = "); Serial.println(size_my); Serial.println(" -----------------Filling array----------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = i+500; tpa_status[i].duration = i+400; tpa_status[i].average = i+300; tpa_status[i].avail = i+100; tpa_status[i].mod_reset = i; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Writing fram from array-------------------"); Wire.begin(); unsigned int adress=0; /* for (int i =0; i<arr; i++){ fm.pack(adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } */ /*for (int i =0; i<arr; i++){ buff.counter = tpa_status[i].counter; buff.duration = tpa_status[i].duration; buff.average = tpa_status[i].average; buff.avail = tpa_status[i].avail; buff.mod_reset = tpa_status[i].mod_reset; Serial.print(adress);Serial.print("-->"); fm.pack(adress,(void*)&buff,size_my); adress=adress+size_my; }*/ fm.pack(0,(void*)&tpa_status[0],size_my); fm.pack(14,(void*)&tpa_status[1],size_my); fm.pack(28,(void*)&tpa_status[2],size_my); fm.pack(42,(void*)&tpa_status[3],size_my); fm.pack(56,(void*)&tpa_status[4],size_my); Serial.println(""); delay(5); Serial.println(" -----------------Filling array by zero-------------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; tpa_status[i].avail = 0; tpa_status[i].mod_reset = 0; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Reading fram to array-------------------"); adress=0; /* //так не работает for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } */ //так не работает тоже с теми же симптомами /*for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&buff,size_my); adress=adress+size_my; tpa_status[i].counter = buff.counter; tpa_status[i].duration = buff.duration; tpa_status[i].average = buff.average; tpa_status[i].avail = buff.avail; tpa_status[i].mod_reset = buff.mod_reset; }*/ rc = rc + fm.unpack(0,(void*)&tpa_status[0],size_my); // так нормально пишется эта запись rc = rc + fm.unpack(14,(void*)&tpa_status[1],size_my); rc = rc + fm.unpack(28,(void*)&tpa_status[2],size_my); rc = rc + fm.unpack(42,(void*)&tpa_status[3],size_my); // и почему то эта rc = rc + fm.unpack(56,(void*)&tpa_status[4],size_my); for (int i =0; i<arr; i++){ Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" ------------------alles------------------------"); Serial.print("rc = "); Serial.println(rc); } void loop() { // put your main code here, to run repeatedly: }уже от отчаяния стал закидывать по одной структуре (лимит 32 байта для Wire). все равно какая то хрень.
такое ощущение, что неправильно адресуется сама микросхема FRAM, лопатил библиотеку по принципу EEPROMовских, все равно не пашить.
это вроде что то делает , но делает и за пределами адресного пространства 8192
/* * \brief Check consistency of I2C EEPROM * * It will write test values in the entire EEPROM and try to read them. * All errors will be displayed. * * \author Quentin Comte-Gaz <quentin@comte-gaz.com> * \date 29 June 2016 * \license MIT License (contact me if too restrictive) * \copyright Copyright (c) 2016 Quentin Comte-Gaz * \version 1.0 */ #include <I2CEEPROM.h> #define CHIP_ADDRESS 0x50 // Address of EEPROM chip (24LC256->0x50) #define EEPROM_BYTES 8191 // Number of bytes in EEPROM chip I2CEEPROM i2c_eeprom(CHIP_ADDRESS); // Create I2C EEPROM instance void setup(void) { Serial.begin(115200); // Variables Serial.print("CHIP_ADDRESS=0x"); Serial.print(CHIP_ADDRESS, HEX); Serial.print("\n"); Serial.print("EEPROM_BYTES="); Serial.print(EEPROM_BYTES, DEC); Serial.print("\n\n"); Serial.print("This test will: \n -Write all the EEPROM\n -Read all the EEPROM and check consistency\n\n"); // For even more extended test, you may write values ("writeTest()"), reboot and read values ("readTest()") // This would ensure that the EEPROM is holding values even after a reboot. Serial.print("Beginning EEPROM check-up...\n"); writeTest(); Serial.print("EEPROM check-up done\n"); } void loop() { } /*! * \brief Write all bytes in I2C EEPROM for test scenario */ void writeTest(void) { unsigned int data = 0; unsigned int errors = 0; Serial.print("Writing test values in EEPROM...\n"); for (unsigned int address = 0; address < EEPROM_BYTES; address++) { // i2c_eeprom.write(address, address & 0xFF); data = i2c_eeprom.read(address); Serial.print(data , HEX); Serial.print(" "); if ((data%256) == 0) Serial.print("\n"); if ((address%1024) == 0) { Serial.print(address, HEX); Serial.print("/"); Serial.print(EEPROM_BYTES, HEX); Serial.print(" bytes done\n"); } /* if (data != address & 0xFF) { errors++; Serial.print("Error on address "); Serial.print(address, HEX); Serial.print(" : data in EEPROM is "); Serial.print(data, HEX); Serial.print(" while it should be "); Serial.print(address & 0xFF, HEX); Serial.print("\n"); }*/ if ((address%1024) == 0) { Serial.print(address, HEX); Serial.print("/"); Serial.print(EEPROM_BYTES, HEX); Serial.print(" bytes done\n"); } } }памажите чем можите :) сильно хочется писать состояние много много раз, не думая о ресурсе записей
Может просто микроскхема нерабочая? И вообще что именно и как подключено?
как писал первоисточник, "Протокол i2c для FRAM сильно проще, чем для EEPROM"
так попробуйте как для EEPROM, поскольку под видом фрам часто продают перемаркер
Подключена обычно , i2c- 5 и 6 ноги, 1,2,3,4 ноги вместе дабы 50 адрес, 8 нога питание.
Вроде в чипдипе покупал, не должен быть перемаркер.
Еепром библиотеку попробовал , выше написано.
Подключена обычно , i2c- 5 и 6 ноги, 1,2,3,4 ноги вместе дабы 50 адрес, 8 нога питание.
Ну, пин 1 вообще-то лучше никуда не подключать. Пины адреса (2 и 3) pulled down, так что их можно к земле и не подключать. А как это все к ардуине подключено и есть pull-up резисторы на линиях I2C?
inspiritus - какого обьема микросхема?
Адресация на ФРАМках разного обьема делается по разному - похоже пейсатели библиотек этого не подозревают...
8kх8
конечно же i2c подтянуты.
эта библиотека вообще ея не видит
посмотрел даташит - похоже что библиотека правильная.
Есть подозрение, что у вас проблемы с выравниванием данных в структуре. Попробуйте для начала писать и читать однородный массив. скажем
uint16_t data[8]
Если ошибки пропадут - значит делов том, что ваша структура на самом деле не 14 байт
Добавлю - с год назад мы с sadman41 тестировали FRAM на число перезаписей. Никаких библиотек не использовали, писали напрямую через Wire. Сейчас посмотрел свой тогдашний код - он практически совпадает с кодом библиотеки в первом сообщении. Думаю, должен работать
#137
#137
Ух ты!
А что на этом модуле fram стоит? Или eeprom?
eeprom
посмотрел даташит - похоже что библиотека правильная.
Есть подозрение, что у вас проблемы с выравниванием данных в структуре. Попробуйте для начала писать и читать однородный массив. скажем
uint16_t data[8]
Если ошибки пропадут - значит делов том, что ваша структура на самом деле не 14 байт
Хм.. странно
какая то мистика
увеличил вычисленную длину записи на 1, тк. у автора библы strlen(sabj)+1,
при этом если писать по одной записи в адреса 0, 14,28... но с увеличенной длиной, все ок,
а в автомате лажа
#include "FM24I2C.h" #define arr 27 FM24I2C fm(0x50); struct condition { uint32_t counter; float duration; float average; uint8_t avail; uint8_t mod_reset; }; condition tpa_status[arr]; condition buff ; unsigned long rc =0; void setup() { Serial.begin(115200); unsigned int adress=0; uint32_t size_my = sizeof(struct condition)+1; Serial.print("size of structure = "); Serial.println(size_my); Serial.println(" -----------------Filling array----------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = i+500; tpa_status[i].duration = i+400; tpa_status[i].average = i+300; tpa_status[i].avail = i+100; tpa_status[i].mod_reset = i; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Writing fram from array-------------------"); Wire.begin(); //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ fm.pack(adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } /*for (int i =0; i<arr; i++){ buff.counter = tpa_status[i].counter; buff.duration = tpa_status[i].duration; buff.average = tpa_status[i].average; buff.avail = tpa_status[i].avail; buff.mod_reset = tpa_status[i].mod_reset; Serial.print(adress);Serial.print("-->"); fm.pack(adress,(void*)&buff,size_my); adress=adress+size_my; }*/ /* fm.pack(0,(void*)&tpa_status[0],size_my); fm.pack(14,(void*)&tpa_status[1],size_my); fm.pack(28,(void*)&tpa_status[2],size_my); fm.pack(42,(void*)&tpa_status[3],size_my); fm.pack(56,(void*)&tpa_status[4],size_my); fm.pack(70,(void*)&tpa_status[5],size_my);*/ Serial.println(""); delay(5); Serial.println(" -----------------Filling array by zero-------------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; tpa_status[i].avail = 0; tpa_status[i].mod_reset = 0; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Reading fram to array-------------------"); adress=0; //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } //так не работает тоже с теми же симптомами /*for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&buff,size_my); adress=adress+size_my; tpa_status[i].counter = buff.counter; tpa_status[i].duration = buff.duration; tpa_status[i].average = buff.average; tpa_status[i].avail = buff.avail; tpa_status[i].mod_reset = buff.mod_reset; }*/ rc = rc + fm.unpack(0,(void*)&tpa_status[0],size_my); // так нормально пишется эта запись rc = rc + fm.unpack(14,(void*)&tpa_status[1],size_my); rc = rc + fm.unpack(28,(void*)&tpa_status[2],size_my); rc = rc + fm.unpack(42,(void*)&tpa_status[3],size_my); // и почему то эта rc = rc + fm.unpack(56,(void*)&tpa_status[4],size_my); rc = rc + fm.unpack(70,(void*)&tpa_status[5],size_my); for (int i =0; i<arr; i++){ Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" ------------------alles------------------------"); Serial.print("rc = "); Serial.println(rc); } void loop() { // put your main code here, to run repeatedly: }но только до 7 элемента, далее ок
чуть исправил, но все равно странно - сначала криво, потом как надо.
#include "FM24I2C.h" #define arr 27 FM24I2C fm(0x50); struct condition { uint32_t counter; float duration; float average; uint8_t avail; uint8_t mod_reset; }; condition tpa_status[arr]; condition buff ; unsigned long rc =0; void setup() { Serial.begin(115200); unsigned int adress=0; uint32_t size_my = sizeof(struct condition); Serial.print("size of structure = "); Serial.println(size_my); Serial.println(" -----------------Filling array----------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = i+500; tpa_status[i].duration = i+400; tpa_status[i].average = i+300; tpa_status[i].avail = i+100; tpa_status[i].mod_reset = i; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Writing fram from array-------------------"); Wire.begin(); //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ fm.pack(adress,(void*)&tpa_status[i],size_my+1); adress=adress+size_my; } /*for (int i =0; i<arr; i++){ buff.counter = tpa_status[i].counter; buff.duration = tpa_status[i].duration; buff.average = tpa_status[i].average; buff.avail = tpa_status[i].avail; buff.mod_reset = tpa_status[i].mod_reset; Serial.print(adress);Serial.print("-->"); fm.pack(adress,(void*)&buff,size_my); adress=adress+size_my; }*/ /* fm.pack(0,(void*)&tpa_status[0],size_my); fm.pack(14,(void*)&tpa_status[1],size_my); fm.pack(28,(void*)&tpa_status[2],size_my); fm.pack(42,(void*)&tpa_status[3],size_my); fm.pack(56,(void*)&tpa_status[4],size_my); fm.pack(70,(void*)&tpa_status[5],size_my);*/ Serial.println(""); delay(5); Serial.println(" -----------------Filling array by zero-------------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; tpa_status[i].avail = 0; tpa_status[i].mod_reset = 0; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Reading fram to array-------------------"); adress=0; //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&tpa_status[i],size_my+1); adress=adress+size_my; } //так не работает тоже с теми же симптомами /*for (int i =0; i<arr; i++){ rc = rc + fm.unpack(adress,(void*)&buff,size_my); adress=adress+size_my; tpa_status[i].counter = buff.counter; tpa_status[i].duration = buff.duration; tpa_status[i].average = buff.average; tpa_status[i].avail = buff.avail; tpa_status[i].mod_reset = buff.mod_reset; }*/ rc = rc + fm.unpack(0,(void*)&tpa_status[0],size_my); // так нормально пишется эта запись rc = rc + fm.unpack(14,(void*)&tpa_status[1],size_my); rc = rc + fm.unpack(28,(void*)&tpa_status[2],size_my); rc = rc + fm.unpack(42,(void*)&tpa_status[3],size_my); // и почему то эта rc = rc + fm.unpack(56,(void*)&tpa_status[4],size_my); rc = rc + fm.unpack(70,(void*)&tpa_status[5],size_my); for (int i =0; i<arr; i++){ Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" ------------------alles------------------------"); Serial.print("rc = "); Serial.println(rc); } void loop() { // put your main code here, to run repeatedly: }хм, а кто вас учил вот так вот ссылку на элемент массива записывать?
(void*)&tpa_status[i]
Компилятор не ругается, случаем?
чуть исправленный пример автора
#include "FM24I2C.h" FM24I2C fm(0x50); void setup() { Wire.begin(); Serial.begin(115200); char str1[]="12345678901234567890"; char str2[]="qwertyuiopasdfghjklzxcvbnm"; int a1=0x00; int a2=0x40; fm.pack(a1,str1,strlen(str1)+1); delay(5); fm.pack(a2,str2,strlen(str2)+1); delay(5); char buf[80]; fm.unpack(a1,buf,strlen(str1)+1); Serial.println(buf); fm.unpack(a2,buf,strlen(str2)+1); Serial.println(buf); } void loop() { // put your main code here, to run repeatedly: }тоже показывает кривизну в адресации
кстати автор ответил, что есть непофикшенный баг в адресации, проблему он нашел, но некогда
и более на связь не выходил
такой способ обращения взял из примера для структуры с авторского поста с гитхаба, тоже удивился.
компилятор вообще молчок, даже если сообщения все включены
баг в адресации может быть двух видов
- формирование адреса для обращения к чипу
- передача сформированного адреса чипу
эти направления и ковыряю уже два дня.
inspiritus - зачем вам эта кривая библиотека? Добро бы там было что-то сложное - а то вся либа - это буквально 10 строк.
есть же даташит, возьмите да напишите прямо по нему. Жалко у меня FRAM на 4к бита - там принцип адресации чуть другой, а то я бы сам написал
нашел полезное обсуждение по теме
http://forum.amperka.ru/threads/Советую-детальку-eeprom-fram.16761/page-2
Ну разумеется лучше организовать жёсткий диск с файлами, именами и расширением.
В итоге, вкуривши, по совету мудрейшего b707, даташит и дискуссию , по указанной выше ссылке написал такой пример для своей заморочки, который работает именно так, как мне необходимо.
#include <Wire.h> #define arr 80 #define fm_addr 0x50 struct condition { uint32_t counter; float duration; float average; uint8_t avail; uint8_t mod_reset; }; condition tpa_status[arr]; condition buff ; unsigned long rc =0; void setup() { Wire.begin(); Serial.begin(115200); unsigned int adress=0; uint32_t size_my = sizeof(struct condition); Serial.print("size of structure = "); Serial.println(size_my); Serial.println(" -----------------Filling array----------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = i+500; tpa_status[i].duration = i+400; tpa_status[i].average = i+300; tpa_status[i].avail = i+100; tpa_status[i].mod_reset = i; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Writing fram from array-------------------"); Wire.begin(); //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ fram_pack(fm_addr, adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } Serial.println(""); delay(5); Serial.println(" -----------------Filling array by zero-------------------"); for (int i =0; i<arr; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; tpa_status[i].avail = 0; tpa_status[i].mod_reset = 0; Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" -----------------Reading fram to array-------------------"); adress=0; //так заработало, но с 7 элемента for (int i =0; i<arr; i++){ rc = rc + fram_unpack(fm_addr, adress,(void*)&tpa_status[i],size_my); adress=adress+size_my; } for (int i =0; i<arr; i++){ Serial.print(i);Serial.print("-->"); Serial.print(tpa_status[i].counter);Serial.print(" "); Serial.print(tpa_status[i].duration);Serial.print(" "); Serial.print(tpa_status[i].average);Serial.print(" "); Serial.print(tpa_status[i].avail);Serial.print(" "); Serial.print(tpa_status[i].mod_reset);Serial.print(" "); Serial.println(); } Serial.println(" ------------------alles------------------------"); Serial.print("rc = "); Serial.println(rc); } void loop() { } void fram_pack(byte disk, uint16_t startAddress, void *data, uint16_t len) { // disk - 0x50-0x57, startAddress - 0x00 - 0xFF, &data - первый байт данных, len - колво байт данных (sizeof(data)) Wire.beginTransmission(disk); Wire.write(startAddress >> 8); Wire.write(startAddress & 0xFF); Wire.write((byte*)data, len); Wire.endTransmission(); delay(1); } int fram_unpack(byte disk, uint16_t startAddress, void *data, uint16_t len) { // возвращаем кол-во считанных байт byte rdata; byte *p; Wire.beginTransmission(disk); Wire.write(startAddress >> 8); Wire.write(startAddress & 0xFF); Wire.endTransmission(); Wire.requestFrom(disk, len); for (rdata = 0, p = (byte*)data; Wire.available() && rdata < len; rdata++, p++) { *p = Wire.read(); } return (rdata); }то есть две функции - читающую и пишущую во FRAM FM24LC64 массив структур
микросхема куплена в чипдипе за 84 рубля и предполагается к применению в модуле мониторинга состояния станка для постоянной записи статусов на случай отказа питания вместо eeprom, системы поддержания питания на аккумуляторе и детектирования перехода на него.
по возможности запакую в виде библиотеки и выложу.
еще раз благодарность b707 за волшебное побуждение к творчеству и sadman41 за помощь.
ну и отлично
Верно я понял, что вся разница заключается в очередности передачи байтов адреса?
было
стало
ЗЫ а что более конкретно не помог - извиняйте, болею....
Некоторые правки, которые бы сделал я, оставаясь в авторской концепции:
... for (uint8_t i = 0; i < arr; i++) { // sizeof() will calculated on compile stage fram_pack(fm_addr, adress, (uint8_t*)&tpa_status[i], sizeof(condition)); adress = adress + size_my; } ... for (uint8_t i = 0; i < arr; i++) { uint16_t recieved = fram_unpack(fm_addr, adress, (uint8_t*)&tpa_status[i], sizeof(condition)); if (recieved != sizeof(condition)) { Serial.println(F("Read errrrror!!!111")); } rc = rc + recieved; adress = adress + size_my; } ... uint16_t fram_pack(uint8_t disk, uint16_t startAddress, uint8_t* data, uint16_t len) { Wire.beginTransmission(disk); Wire.write(startAddress >> 8); Wire.write(startAddress & 0xFF); uint16_t written = Wire.write(data, len); Wire.endTransmission(); // delay(1); // no delay really need for FRAM return written; } uint16_t fram_unpack(uint8_t disk, uint16_t startAddress, uint8_t* data, uint16_t len) { Wire.beginTransmission(disk); Wire.write(startAddress >> 8); Wire.write(startAddress & 0xFF); Wire.endTransmission(); uint16_t recieved = Wire.requestFrom(disk, len); // Read error detected if (recieved != len) { return 0x00; } for (recieved = 0x00; recieved < len; recieved++) { *data = Wire.read(); data++; } return (recieved); }Ага, согласен :) спасибо sadman41!
в очередности передачи байтов адреса?
видимо да, сейчас в отъезде, доеду до дома, скорректирую библиотеку из хабра, наверно заработает.
Жалко у меня FRAM на 4к бита - там принцип адресации чуть другой, а то я бы сам написал
А нельзя ознакомится с вашим кодом для 4 килобит?
Я прост сейчас развлекаюсь с FM24C04A, и пока не могу понять, как оно работает. За основу взят код подобный тому, что в этой теме. Но скажем если с записью массива типа char у меня вопросов не возникает, то банальная побайтовая работа приводит к сбоям и зависаниям. И логику пока понять не могу. Хоть убей. :(
Увидеть бы гарантированно рабочий код, чтобы было от чего оттолкнуться.
Чип отвечает по адресам 0x50, 0x51 если что. Судя по сканеру. Что меня уже чутка озадачивает, с учетом 8 страниц.
К сбоям и зависаниям чего и какого вида?
Чип отвечает по адресам 0x50, 0x51 если что. Судя по сканеру. Что меня уже чутка озадачивает, с учетом 8 страниц.
4 мегабита - это 2 страницы, как раз с адресами 0x50, 0x51 если что.
Увидеть бы гарантированно рабочий код, чтобы было от чего оттолкнуться.
посмотрите в этой ветке начиная со страницы 4 - там люди в итоге разобрались, что к чему
http://forum.amperka.ru/threads/%D0%A1%D0%BE%D0%B2%D0%B5%D1%82%D1%83%D1%8E-%D0%B4%D0%B5%D1%82%D0%B0%D0%BB%D1%8C%D0%BA%D1%83-eeprom-fram.16761/page-4
если не поможет - позже поищу свой код, сейчас на работе запарка...
Подобная картина обычно бывает, когда ошибаемся в границах массива, например. Т.е. просто шаманские глюки. Или скажем читаем не из того места и не в том количестве, куда писали. И получаем мусор. Я подозреваю, что где-то я косячу по глупому скорее всего. Код покажу сейчас,не весь, но все что связано.
//адрес страницы памяти FRAM #define FM_addr 0x51 char hs_c1[5]="-----"; byte hs_ccc2=0; void FM_Write(int addr, void* data, int len) { Wire.beginTransmission(FM_addr); Wire.write((byte*)&addr,2); Wire.write((byte*)data,len); Wire.endTransmission(true); delay(1); } int FM_Read(int addr, void* data, int len) { int rc; byte *p; Wire.beginTransmission(FM_addr); Wire.write((byte*)&addr,2); Wire.endTransmission(false); Wire.requestFrom(FM_addr,len); for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) { *p=Wire.read(); } return(rc); }Так вот если я работаю с массивом hs_c1 - все отлично и корректно:
К краху приводит именно чтение, не запись. Но при этом тоже самое чтение с массивом hs_c1 замечательно работает.
Чечако, та же ошибка, что у всех - в строке 10 длина адреса ОДИН байт. а не два.
У микросхем с обьемом памяти до, если правильно помню, 16 кбит - адрес однобайтный, выше - два байта
Странно, конечно, что с массивом нормально. Выше inspiritus выяснил, что надо в адресе байты переворачивать.
Странно, конечно, что с массивом нормально. Выше inspiritus выяснил, что надо в адресе байты переворачивать.
для 4 Кбит нечего переворачивать. адрес 1 байт
Но для более других-то надо же, как я понимаю. А ошибка присутствует и такая в исходнике.
Странно, конечно, что с массивом нормально. Выше inspiritus выяснил, что надо в адресе байты переворачивать.
для 4 Кбит нечего переворачивать. адрес 1 байт
Переворачивать я пробовал - пофигу. Как правильно поправить код? Если я тупо 2 поменяю на 1, ничего не меняется. массив работает корректно как и раньше, байт приводит к сбоям.
Но для более других-то надо же, как я понимаю. А ошибка присутствует и такая в исходнике.
для разных обьемов - разный вид адреса. Я об этом твержу уже в третьей ветке...
Дак я спорю что ли?
Если не разберетесь - попозжа могу в ящике поискать свою фрамку.
Как правильно поправить код?
void FM_Write(uint8_t addr, void* data, int len) { Wire.beginTransmission(FM_addr); Wire.write(addr); Wire.write((byte*)data,len); Wire.endTransmission(true); }как-то так. Обратите внимание на тип переменной addr - это ансигнед байт. а не инт
Да, еще, len - максимум 31 байт, как я помню.
Как правильно поправить код?
void FM_Write(uint8_t addr, void* data, int len) { Wire.beginTransmission(FM_addr); Wire.write(addr); Wire.write((byte*)data,len); Wire.endTransmission(true); }как-то так. Обратите внимание на тип переменной addr - это ансигнед байт. а не инт
Да, еще, len - максимум 32 байта
len у меня 1 в случае байта, я выше показывал код. Ничего не меняется. Массив по прежнему работает корректно, байт по прежнему приводит к сбоям. И по факту или не сохраняется, или не оттуда читается. Ибо я счетчик туда пишу, в текстовый массив преобразую туда и обратно через string. Адрес я исправил в обоих функциях, понятное дело.
Вот код, который крутится в цикле - по сути два счетчика, вызов раз в секунду.
unsigned long hs_ccc1=0; byte hs_ccc2=0; .... Цикл, раз в секунду примерно FM_Read(10,hs_c1,5); Serial.print("Read: "); Serial.println(FM_Read(30,hs_ccc2,1)); hs_ccc1=String(hs_c1).toInt(); hs_ccc1++; hs_ccc2++; if(hs_ccc1>9999)hs_ccc1=0; if(hs_ccc2>100)hs_ccc2=0; Serial.print("hs_ccc1="); Serial.println(hs_ccc1); Serial.print("hs_ccc2="); Serial.println(hs_ccc2); hs_str=String(hs_ccc1); hs_str.toCharArray(hs_c1,hs_str.length()+1); FM_Write(10,hs_c1,5); FM_Write(30,hs_ccc2,1);Соответственно, счетчик сохраняемый через массив работает корректно, после перезагрузки контроллера продолжает с того же места. Счетчик на byte - где-то на 15-16 цикле приводит к сбоям, ну и всегда начинается с нуля, что говорит о том, что его значение или не сохраняется, или не считывается.
Я понимаю, что это какая-то глупость скорее всего, но глаз видимо замылился.
len у меня 1 в случае байта, я выше показывал код.
выше вы показывали код, где адрес был 2 байта.
Извините, что я с вами как с новичком - но, пожалуйста, выложите актуальную версию кода с правильным адресом и правильной длиной....
Извините, что я с вами как с новичком - но, пожалуйста, выложите актуальную версию кода с правильным адресом и правильной длиной....
Извиняться не надо, я действительно туплю: Сейчас вот так:
void FM_Write(uint8_t addr, void* data, int len) { Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); Wire.write((byte*)data,len); Wire.endTransmission(true); delay(1); } int FM_Read(uint8_t addr, void* data, int len) { int rc; byte *p; Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); Wire.endTransmission(false); Wire.requestFrom(FM_addr,len); for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) { *p=Wire.read(); } return(rc); }По len - я про вашу фразу о ограничении длинной буфера по умолчанию в 32 (31). По факту у меня оно или всегда 5 для массива, или всегда 1 для байта. Код вызова функций в посту выше на один. :) Фрагмент вызывается по контролю millis примерно раз в секунду, если это важно.
С этим кодом сбой происходит стабильно на 39 секунде примерно с момента перезапуска контроллера по reset
в строках 7 и 19 false и true попробуйте убрать.
в строках 7 и 19 false и true попробуйте убрать.
Монопенисуально. Вот текущий код - я вообще сделал отдельный скетч, привожу целиком.
#include "Wire.h" //******************************************************************************************************************************** //*** работа с FRAM //******************************************************************************************************************************** unsigned long timer_stat; char hs_c1[5]="-----"; String hs_str; unsigned long hs_ccc1=0; byte hs_ccc2=0; //адрес страницы памяти FRAM #define FM_addr 0x51 void setup() { Wire.begin(); Serial.begin(19200); } void loop() { if (micros()-timer_stat>1000000) { FM_Read(10,hs_c1,5); Serial.print("Read: "); Serial.println(FM_Read(110,hs_ccc2,1)); hs_ccc1=String(hs_c1).toInt(); hs_ccc1++; hs_ccc2++; if(hs_ccc1>9999)hs_ccc1=0; if(hs_ccc2>100)hs_ccc2=0; Serial.print("hs_ccc1="); Serial.println(hs_ccc1); Serial.print("hs_ccc2="); Serial.println(hs_ccc2); hs_str=String(hs_ccc1); hs_str.toCharArray(hs_c1,hs_str.length()+1); FM_Write(10,hs_c1,5); FM_Write(110,hs_ccc2,1); timer_stat=micros(); } } void FM_Write(uint8_t addr, void* data, int len) { Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); Wire.write((byte*)data,len); //Wire.endTransmission(true); Wire.endTransmission(); delay(1); } int FM_Read(uint8_t addr, void* data, int len) { int rc; byte *p; Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); //Wire.endTransmission(false); Wire.endTransmission(); Wire.requestFrom(FM_addr,len); for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) { *p=Wire.read(); } return(rc); }На 29 итерации все умирает. Выглядит в сериале вот так:
При этом сбой идет и при чтении ccc1 из fram - он вероятно возвращает ноль. Далее 30 у ccc2 и привет. Висим до резета. После резета ccc1 2524, значит считал 2523.
Адрес записи байта я поменял на 110 вместо 30 просто ради эксперимента.
Если закомментировать чтение байта с адреса 110, т.е. 34 строку скетча - все работает без проблем.
на строку 52 вставьте вывод hs_str в Сериал
Чечако, в 34 строке добавь & перед hs_ccc2
на строку 52 вставьте вывод hs_str в Сериал
На первых 30 сбойнула судя по выводу, на вторых повисли - фрагмент сериала прилагаю:
Я добавил вывод количества считанных байт, вот текущий код:
#include "Wire.h" //******************************************************************************************************************************** //*** работа с FRAM //******************************************************************************************************************************** unsigned long timer_stat; char hs_c1[5]="-----"; String hs_str; unsigned long hs_ccc1=0; byte hs_ccc2=0; //адрес страницы памяти FRAM #define FM_addr 0x51 void setup() { Wire.begin(); Serial.begin(19200); } void loop() { if (micros()-timer_stat>1000000) { Serial.print("Read ccc1: "); Serial.println(FM_Read(10,hs_c1,5)); Serial.print("Read ccc2: "); Serial.println(FM_Read(110,hs_ccc2,1)); hs_ccc1=String(hs_c1).toInt(); hs_ccc1++; hs_ccc2++; if(hs_ccc1>9999)hs_ccc1=0; if(hs_ccc2>100)hs_ccc2=0; Serial.print("hs_ccc1="); Serial.println(hs_ccc1); Serial.print("hs_ccc2="); Serial.println(hs_ccc2); Serial.println("----------"); hs_str=String(hs_ccc1); hs_str.toCharArray(hs_c1,hs_str.length()+1); Serial.print("hs_str="); Serial.println(hs_str); FM_Write(10,hs_c1,5); FM_Write(110,hs_ccc2,1); timer_stat=micros(); } } void FM_Write(uint8_t addr, void* data, int len) { Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); Wire.write((byte*)data,len); //Wire.endTransmission(true); Wire.endTransmission(); delay(1); } int FM_Read(uint8_t addr, void* data, int len) { int rc; byte *p; Wire.beginTransmission(FM_addr); //Wire.write((byte*)&addr,2); Wire.write(addr); //Wire.endTransmission(false); Wire.endTransmission(); Wire.requestFrom(FM_addr,len); for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) { *p=Wire.read(); } return(rc); }Чечако, в 34 строке добавь & перед hs_ccc2
Если так сделать - hs_ccc2 обнуляется каждую итерацию.
Но вот если & добавить не только в 34, но и в строку записи тоже - которая 54 в том примере примере, то все работает и не виснет... :-/
Можно объяснить, в чем магия?
Можно объяснить, в чем магия?
какая магия? у вас же в процедуразх записи и считывания используется указатель...
какая магия?
Как какая? Разве третий закон Кларка уже отменили?
Исходник (не сильно красивый):
#include "Wire.h" //******************************************************************************************************************************** //*** работа с FRAM //******************************************************************************************************************************** unsigned long timer_stat; char arrayOne[] = "ABCDEF"; uint8_t varOne = 0; //адрес страницы памяти FRAM #define FM_addr 0x51 void i2cScan() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for (address = 1; address < 127; address++ ) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); Serial.println(" !"); nDevices++; } else if (error == 4) { Serial.print("Unknown error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); } void FM_Write(const uint8_t addr, uint8_t* data, const uint8_t len) { Wire.beginTransmission(FM_addr); Wire.write(addr); Wire.write(data, len); Wire.endTransmission(true); } int16_t FM_Read(const uint8_t addr, uint8_t* data, const uint8_t len) { uint16_t readed; Wire.beginTransmission(FM_addr); Wire.write(addr); Wire.endTransmission(false); readed = Wire.requestFrom(FM_addr, len); if (len != readed) { return -1; } for (uint8_t i = 0; i < len; i++) { *data = Wire.read(); data++; } return (readed); } void setup() { Wire.begin(); Serial.begin(115200); i2cScan(); } void loop() { if (millis() - timer_stat > 1000UL) { timer_stat = millis(); int8_t readed; char arrayTwo[sizeof(arrayOne)]; memset(arrayTwo, 0x00, sizeof(arrayTwo)); Serial.print("["); Serial.print(timer_stat); Serial.println("]"); Serial.println("Write array to FRAM"); FM_Write(10, arrayOne, sizeof(arrayOne)); Serial.println("Read array from FRAM"); readed = FM_Read(10, arrayTwo, sizeof(arrayTwo)); if (0x00 < readed) { Serial.println("Report: "); for (uint8_t i = 0x00; sizeof(arrayTwo) > i; i++) { Serial.print((arrayOne[i] == 0x00) ? (char)0x20 : arrayOne[i]); Serial.print(" => "); Serial.println((arrayTwo[i] == 0x00) ? (char)0x20 : arrayTwo[i]); } } else { Serial.println("Read Error"); } uint8_t varOne = random(255); uint8_t varTwo = 0x00; Serial.println("Write variable to FRAM"); FM_Write(1, &varOne, sizeof(varOne)); Serial.println("Read variable from FRAM"); readed = FM_Read(1, &varTwo, sizeof(varTwo)); if (0x00 < readed) { Serial.println("Report: "); Serial.print(varOne); Serial.print(" => "); Serial.println(varTwo); } else { Serial.println("Read Error"); } } }Лог: