No, treba to robit tak, ze prijem dat bude prebiehat cez prerusenia. Popisem najjednoduchsi scenar:
V prerusovacom handleri nebude nic viac, nez len vyzdvihnutie znaku z RCREG a strcenie na koniec buffera (tam kam ukazuje nejaky ukazovatel) a kontrolovanie, ci je buffer plny - teda ci ma povedzme 64 znakov zapisanych - resp. ci je ukazovatel na konci bufferu.
Ak je plny, nastavi sa nejaky bit indikujuci, ze buffer je plny. V tejto chvili je cas prijmu jedneho RS232 znaku na to, aby sa data z bufferu odpratali a ukazovatel sa nastavil opat na nulu. Tym padom pri prijme dalsieho znaku sa interrupt handler nemusi o nic starat, len strci znak na koniec bufferu (medzicasom ukazuje opat na zaciatok bufferu) a inkrementuje ukazovatel. Otazka je, ako upratat tie data. Su v zasade dve moznosti:
1, Rychlo ich zapisat do EEPROM a vynulovat ukazovatel. Tu si treba spocitat, ci sa stiha v priebehu prijmu jedneho znaku (to je cas, kym treba odsunut data) vsetko nacvakat do EEPROM - myslim tym len cas samotheho presunu dat po zbernici. Cas zapisu po tomot presune, tych znamych 5ms nas mezaujima, lebo pocas tohoto casu sa bude plnut dalsi buffer a s EEPROM sa nebude manipulovat. Povedzme, ze IIC bezi na 400kHz, cas prenosu 9-tich bitov je asi 22us, presnos vsetkych dat (64bajtov dat + dva bajty adresa + jeden bajt adresa zariadenia = 67 bajtov) je 1522us, teda 1,5ms. Teda bude trvat asi 1,5ms kym sa data odpracu prec. To by zodpovedalo rychlosti 666 B/s. Teda nic moc. Situaciu som zjednodusil, lebo v skutocnosti nie je problem cakat aj viac, ako zodpoveda casu prijatia jedneho bajtu, pretoze zatialco je jednen znak prijaty a caka v RCREG, druhy sa moze prijmat do shitheregistra v UART-e, ale akonahle bude prijaty STOP bit, bude ho chciet UART presunut do RCREG - a tu nastane pretecenie (OERR bit). Takze, s vypnutymi preruseniami mozeme cakat dobu dvoch prijmov cez USART, co posuva situaciu na 1332 B/s.
2, Zakazat prerusenia, vynulovat ukazovatel, zacat zapisovat data do EEPROM, po zapise prveho bajtu povolit prerusenia a potom zapisat zvysok. Tu ide o to, ze ukazovatel sa vynuluje hned ako je to mozne, teda prijimanie je mozne hned, dalsi prijaty byte z USART-u sa zapise na poziciu 0. To je problem, lebo to moze prepisat data ktore sa prave idu zapisovat do EEPROM. Preto treba zakazat prerusenia, zacat zapisovat data, po presune prveho bajtu do EEPROM povolit prerusenia, aby prijimaci “stroj” mohol pokracovat ako ma. Buffer sa bude prepisovat prijimanymi datami este v dobe, ked bude prebiehat ich presun do EEPROM, ale kedze tento je rychlejsi ako prijimanie dat, moze byt ovplyvnani prinajhorsom prvy bajt - preto je treba pocas jeho presunu do EEPROM vypnut prerusenia.
Teda prerusenia budu zakazane po dobu presunu prych styroch bajtov (adresa zaraidenia, dv abajty adresy, jeden bajt dat), co znamena 4x22us pri 400kHz, to je 88us. Teda znaky z UART-u sa mozu sypat kazdych 88us, co je rychlost asi 11300 B/s, teda takmer 115k baud. Vzhladom k tomu, ze prijimac moze cakat aj o nieco dlhsie, ako som pisal hore, realne je ta prijimacia rychlost este vyssia. Pre SPI EEPROM to bude podstatne lepsie, odhadujem tak o jeden rad.
Inou moznostou je pouzitie viac ako jedneho bufferu - tu su opat dve moznosti:
1, Po prijati celeho bufferu v preruseni sa tento buffer prenesie do pomocneho buffera, z ktoreho sa potom v hlavnej slucke svojim tempom zapise do EEPROM. Kedze presun z buffera do buffera (dva buffery v RAM) je rychly, netreba ani zakazovat prerusenia - prenos sa da pri 20MHz PIC16 zvladnut za nejakych 25us (64 bajtov), co bohato na baudove rychlosti ~0,4Mbaud.
2, Ping-pong buffering: teda zapisuje sa do bufferu 1, po jeho zaplneni sa pokracuje v zapise do bufferu 2, v hlavnej slucke zacne zapis do EEPROM z buffera 1, po zaplneni buffera 2 sa zacne zapis do buffera 1 a zacne sa zapis do EEPROM z buffera 2 atd… Teda zapisuje sa vzdy do ineho buffera nez ten, z ktoreho sa cita a posuva do EEPROM a tento atribut sa prepina z jedneho buffera na druhy - preto ten ping-pong.
Resume:
Osobne by som Vam pre zaciatok radil pouzit metodu 1 s dvomi buffermi, je to asi najjednoduchsie na napisanie a odladenie, pre rychlost 9600 - ak si dobre spominam - je to uplne trivialne.
Odhadujem, ze ani nebude treba velkost buffera 64B, stacilo by aj 32B, takze sa Vam oba buffery zmestia do jednej banky RAM. Potom to bude pomerne jednoduche. V preruseni sa zapisuje do buffera a inkrementuje sa ukazovatel. Ked sa buffera zaplni, bude to indikovane nejakym flagom. Ten sa strazi v hlavnej slucke. Ked sa zisti, ze flag je nastaveny, zakazu sa prerusenia, buffer sa rychlo prekopiruje do pomocneho buffera, vynuluje sa ukazovatel, povolia sa prerusenia - aby prijimanie mohlo pokracovat dalej. Potom sa v hlavnej slucke zacne zapis do EEPROM (ten trva tych povedzme 6ms, ale pocas jeho priebehu sa prijem do bufferu deje cez prerusenia), po skonceni zapisu sa opat bude cakat na flag indikujuci zaplnenie hlavneho buffera…
Este dodatok - pre 32 B buffery (z horeuvedenych dovodv) a 6ms zapis vychadza priepustnost systemu asi na 5,3kB/s, teda asi 53000baudov. Ak zapocitame rezervy, tak do 38400 baudov je to uplne v pohode. Predtym som cital, ze chcete 9600 baudov, takze ste este vo velkej rezerve.