// Podprogramy pro praci s EEPROM //================================================ //---------------------------------------------- // provedeni jednoho zaznamu do EEPROM (pocatecni adresa zaznamu je uvedena v promenne 'adr_dalsiho_zaznamu') // na zaver (pokud je potreba) prepise bit7 nasledujici pametove bunky hodnotou '0' a tim pripravi prostor pro dalsi zaznam void zaznam_EEPROM(void) { unsigned int pomprom = (256 * pole_EEPROM[5]) + pole_EEPROM[6]; // zmerene svetlo v tisicinach mag/arcsec2 if (pomprom / 100 >= hranice_ukladani) // do EEPROM se zaznam uklada jen v pripade, ze je vetsi tma, nez hodnota v promenne hranice_ukladani { hranice_ukladani = EEPROM_read(19); // protoze se pri kalibraci ukladaji vsechny zaznamy nezavisle na nastavene hranici svetla // (hranice se umele prepisuje na 0), je nutne po kazdem ulozeni nastavenou hranici zase obnovit adr_posl_zaznamu = adr_dalsiho_zaznamu; for (byte i = 0 ; i < delka_zaznamu ; i++) { EEPROM_write(adr_posl_zaznamu + i , pole_EEPROM[i]); } adr_dalsiho_zaznamu = adr_dalsiho_zaznamu + delka_zaznamu; if (adr_dalsiho_zaznamu >= max_EEPROM) adr_dalsiho_zaznamu = min_EEPROM; // pokud by dalsi zaznam zacinal nad adresou maximalni pouzitelne EEPROM, tak se vrati zpatky na zacatek byte pomprom = EEPROM_read(adr_dalsiho_zaznamu); if ((pomprom & 0b10000000) > 0) EEPROM_write(adr_dalsiho_zaznamu , (pomprom & 0b01111111)); // bit7 se nastavi na '0' if (((adr_dalsiho_zaznamu-min_EEPROM) % (delka_zaznamu * 100)) == 0 ) { EEPROM_update(18, (adr_dalsiho_zaznamu-min_EEPROM) / delka_zaznamu / 100UL ); } } priprav_1_zaznam(adr_posl_zaznamu); // pripraveni jednoho formatovaneho retezce se vsemi namerenymi udaji #ifdef pouzit_modbus EEPROM_to_MOD(); // prevede "pole_EEPROM[]" do modbusoveho pole "MODdata[]" #endif SD_save(); // pokus o ulozeni zaznamu na SD kartu (na SD kartu se zapisuji vsechny hodnoty nezavisle na urovni svetla) } //---------------------------------------------- //---------------------------------------------- // prazdne misto se nemusi pokazde hledat od adresy 'min_EEPROM'. // pri ukladani dochazi po kazdem 100. zapisu do EEPROM k ulozeni "zachytneho bodu", od ktereho se pak pri zapnuti napajeni zacne hledat volne misto unsigned long najdi_prazdne_misto(byte start_hledani) { unsigned long adresa; for (adresa = min_EEPROM + (100UL * delka_zaznamu * start_hledani); adresa <= max_zaznam_EEPROM ; adresa = adresa + delka_zaznamu) { if ((EEPROM_read(adresa) & 0b10000000) == 0 ) break; // prazdny blok bunek pripraveny pro zapis } if (adresa > max_zaznam_EEPROM) adresa = min_EEPROM; // kdyz se zadna volna adresa nenasla, tak se pro zapis pripravi prvni blok v EEPROM (na adrese 100) adr_posl_zaznamu = adresa - delka_zaznamu; if (adr_posl_zaznamu < min_EEPROM ) adr_posl_zaznamu = max_zaznam_EEPROM; if (EEPROM_read_int(adr_posl_zaznamu) == 0) // vypocteny posledni zaznam neobsahuje zadny cas { adr_posl_zaznamu = 0; // specialni pripad, pri kterem se nevypisuje posledni zaznam } return adresa; } //---------------------------------------------- //---------------------------------------------- // zapis jednoho bajtu do externi EEPROM void EEPROM_write(unsigned long adresa, byte data) { byte stara_hodnota = EEPROM_read(adresa); if (adresa > 65535UL) // pro adresy vetsi nez 65535 se meni I2C adresy EEPROM { adresa = adresa & 0xFFFF; I2C_ADDR = I2C_ADDR_EEPROM_RW_1; } else { I2C_ADDR = I2C_ADDR_EEPROM_RW_0; } if ( stara_hodnota != data) // k zapisu dochazi jen v pripade, ze se ukladana data lisi od puvodni hodnoty { delay(5); Wire.beginTransmission(I2C_ADDR); // zacatek komunikace s EEPROM Wire.write(byte(adresa >> 8)); // MSB z adresy Wire.write(byte(adresa % 256)); // LSB z adresy delay(1); Wire.write(data); // ulozeni hodnoty byte err = Wire.endTransmission(); // konec komunikace if (err > 0) chyba(1); delay(5); #ifndef omezeni_funkci_4 // pokud je logovani povoleno (neni omezena funkce 4) ... if (adresa < min_EEPROM) SD_log(adresa , data); // ... ukladaji se do zvlastniho logovaciho souboru na SD karte zmeny v systemovem nastaveni #endif } } //---------------------------------------------- //---------------------------------------------- // zapis 2 bajtu do externi EEPROM void EEPROM_write_int(unsigned long adresa, unsigned int data) { EEPROM_write(adresa , data >> 8); EEPROM_write(adresa + 1, data % 256); } //---------------------------------------------- //---------------------------------------------- // zapis 4 bajtu do externi EEPROM void EEPROM_write_long(unsigned long adresa, unsigned long data) { EEPROM_write(adresa , (((unsigned long)data >> 24) & 0xFFUL)); EEPROM_write(adresa + 1 , (((unsigned long)data >> 16) & 0xFFUL)); EEPROM_write(adresa + 2 , (((unsigned long)data >> 8) & 0xFFUL)); EEPROM_write(adresa + 3 , (((unsigned long)data ) & 0xFFUL)); } //---------------------------------------------- //---------------------------------------------- // cteni 1 bajtu z externi EEPROM byte EEPROM_read(unsigned long addr) { if (addr > 65535UL) // pro adresy vetsi nez 65535 se meni I2C adresy EEPROM { addr = addr & 0xFFFF; I2C_ADDR = I2C_ADDR_EEPROM_RW_1; } else { I2C_ADDR = I2C_ADDR_EEPROM_RW_0; } delayMicroseconds(7); Wire.beginTransmission(I2C_ADDR); // zacatek komunikace s EEPROM Wire.write(byte(addr >> 8)); // MSB z adresy Wire.write(byte(addr % 256)); // LSB z adresy byte err = Wire.endTransmission(); // konec komunikace if (err > 0) chyba(1); delayMicroseconds(2); Wire.requestFrom(I2C_ADDR, 1); return Wire.read(); } //---------------------------------------------- //---------------------------------------------- // cteni 2 bajtu z externi EEPROM unsigned int EEPROM_read_int(unsigned long adresa) { return (256 * EEPROM_read(adresa)) + EEPROM_read(adresa + 1); } //---------------------------------------------- //---------------------------------------------- // cteni 4 bajtu z externi EEPROM uint32_t EEPROM_read_long(unsigned long adresa) { byte bajt3 = EEPROM_read(adresa); // MSB byte bajt2 = EEPROM_read(adresa + 1); byte bajt1 = EEPROM_read(adresa + 2); byte bajt0 = EEPROM_read(adresa + 3); // LSB return (((unsigned long)bajt3 << 24)) | (((unsigned long)bajt2 << 16)) | (((unsigned long)bajt1 << 8)) | ((unsigned long)bajt0); } //---------------------------------------------- //---------------------------------------------- // zapisuje do EEPROM, ale jen v pripade, ze se data v EEPROM lisi od vkladanych dat // (zpomaluje se tim sice zapis, ale prodluzuje se tim trvanlivost bunek) void EEPROM_update(unsigned long addr, byte data) { byte pomprom = EEPROM_read(addr); if (pomprom != data) EEPROM_write(addr,data); } //---------------------------------------------- //---------------------------------------------- // Test zasunute pridavne EEPROM pro specialni rezimy. // I2C adresa zasouvaci EEPROM je vzdycky 0b1010111 (= 0x57 = 87). // Na pridavne desce GPS je osazena EEPROM 24xx512 a adresovaci SolderJumpery jsou nastaveny na: A=propojeno; B=propojeno; C=rozpojeno. // Konkretni funkce zasunuteho zarizeni se cte z adresy 0, jejiz hodnotu tato funkce vraci. byte test_zasunuti() { delayMicroseconds(7); Wire.beginTransmission(87); // zacatek komunikace s EEPROM Wire.write(0); // MSB z adresy Wire.write(0); // LSB z adresy delay(1); Wire.endTransmission(); // konec komunikace delayMicroseconds(2); Wire.requestFrom(87, 1); return Wire.read(); } //----------------------------------------------