logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[c] Zasada Petit fs - pf_read()

xamrex 15 Cze 2011 19:01 3454 22
REKLAMA
  • #1 9616239
    xamrex
    Poziom 28  
    Mam taki kodzik:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jest to trochę zmodyfikowany przykład z książki pana Mirka.
    Wszystko śmiga elegancko.
    Mam pytanie odnośnie funkcji
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nie rozumiem jakie argumenty ona przyjmuje.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ja rozumiem to tak:
    Pierwszy argument(bufor)-> to tablica do jakiej polecą dane z karty
    Drugi argument -> to ilość bajtów do odczytania.
    Trzeci argument to ->No właśnie? do czego służy argument trzeci (&s1) ?
    Jest to wskaźnik do ilości przeczytanych bitów?
    Czyli on wskazuje na adres gdzie skończył czytać tak?
    Co to dokładnie jest?
  • REKLAMA
  • Pomocny post
    #2 9616461
    nsvinc
    Poziom 35  
    To działa dokładnie tak samo jak w funkcjach ReadFile lub WriteFile z WinAPI. Trzeci argument to wskaźnik na WORD, ponieważ funkcja zwraca ile bajtów faktycznie odczytano właśnie poprzez tą zmienną.
    Może być tak, że chcesz czytać 1024bajty (btr=1024) a funkcja odczyta tylko 1000 bajtów (z dowolnego powodu, np. address out of range). I jak inaczej ma Cię ta funkcja poinformować, że w buforze jest mniej danych niż byś chciał, jeśli nie właśnie poprzez 'br'? Teoretycznie prawidlowy odczyt nie wylatujący poza dozwolone zakresy adresów zawsze powinien zwrócić pod *br tą samą liczbę co podano w btr.
  • #3 9616607
    xamrex
    Poziom 28  
    A w jaki sposób mogę teraz czytać np. od piątego znaku?

    Zauważyłem, że jeśli wywołam np. 2x
    res = pf_read(bufor, sizeof(bufor), &s1);
    res = pf_read(bufor, sizeof(bufor), &s1);

    To odczyta mi on to od 2giego znaku, ale wydaje mi się że da się to w lepszy sposób zrobić...
  • Pomocny post
    #4 9617052
    drzasiek
    Specjalista CNC
    Funkcja pf_lseek. Mirek tego nie opisał czy ci się nie chciało przeczytać wszystkiego?
  • #5 9617212
    xamrex
    Poziom 28  
    Dzięki :)
    Powiem szczerze, nawet nie szukałem dokumentacji, gdyż myślałem, że to trzeba zrobić za pomocą funkcji pf_read(); a nie że jest dodatkowa pf_lseek();
    Tak czy siak dzięki :)


    Mam jeszcze jedno pytanko

    Ja w kodzie to zakomentowałem, bo wydaje mi się, że to nic nie robi.
    Chodzi mi o zapis:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wiesz może w jakim celu to zostało użyte?
  • Pomocny post
    #6 9617696
    drzasiek
    Specjalista CNC
    W zmiennej sl masz wartość odczytanych bajtów (sl jako trzeci argument funkcji pf_read)
    zatem co robi zapis
    
    bufor[s1+1] = 0;
    


    ??
    No zeruje element bufora następny za tym, w którym został zapisany ostatni bajt. Czasem tam lubią zostawać jakieś śmieci i przy wyświetlaniu potem takiego "cudoka" wyświetla.
  • REKLAMA
  • #7 9619945
    xamrex
    Poziom 28  
    no, ale coś mi tu nie pasuje.
    Załóżmy, że bufor jest 100elementowy
    char bufor[100];
    No i teraz mam tę funkcję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czyli odczytuje mi się 100 bajtów.

    I potem mam ten kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jeśli wszystko odczyta się poprawnie, to wykona się kod
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Czyli wyskoczy mi poza bufor ..
  • #8 9620033
    drzasiek
    Specjalista CNC
    Nikt nie powiedział, że bufor musi być taki duży, jak liczba bajtów które odczytujesz. A jak i przyjdzie odczytać różnej długości ciągi? Będziesz tworzył wiele buforów tymczasowych? Zamiast tego daje się jeden większy, można dać na wszelki wypadek o 1 większy niż max liczba bajtów jaką kiedykolwiek będziesz odczytywał. Przynajmniej ja tak rozumiem ten fragment, o dokładnym znaczeniu dobrze by było gdyby się wypowiedział autor kodu.
  • #9 9620570
    nsvinc
    Poziom 35  
    Tragedia!!
    xamrex napisał:
    Jeśli wszystko odczyta się poprawnie, to wykona się kod
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Czyli wyskoczy mi poza bufor ..

    bufor[100] już sam w sobie wyskakuje poza bufor! Deklarując bufor[100], dostępne indeksy tablicy to 0..99 (i żebym to ja musiał tobie to tłumaczyć...)

    Po drugie, ten sizeof... 'bufor' nie jest TYPEM, tylko wskaznikiem na tablicę 100elementową rezerwowaną na etapie kompilacji. Nie wiem na jakiej podstawie ten kod ogólnie ma rację bytu...

    drzasiek napisał:
    Nikt nie powiedział, że bufor musi być taki duży, jak liczba bajtów które odczytujesz. A jak i przyjdzie odczytać różnej długości ciągi? Będziesz tworzył wiele buforów tymczasowych? Zamiast tego daje się jeden większy, można dać na wszelki wypadek o 1 większy niż max liczba bajtów jaką kiedykolwiek będziesz odczytywał.

    A da się zdefiniować max liczbę bajtów jaka kiedykolwiek będzie czytana? Jak, skoro z karty czytasz pliki? Najbardziej opłaca się czytać całymi sektorami. To tylko 512 bajtów, a o ile prościej?
  • #10 9620665
    drzasiek
    Specjalista CNC
    nsvinc napisał:

    A da się zdefiniować max liczbę bajtów jaka kiedykolwiek będzie czytana? Jak, skoro z karty czytasz pliki? Najbardziej opłaca się czytać całymi sektorami. To tylko 512 bajtów, a o ile prościej?

    Właśnie to samo napisałem, tylko innymi słowami.
    Ale jeśli do odczytania jest np tylko jedno krótkie słowo z pliku txt to po co czytać cały sektor, skoro można parę bajtów?
  • REKLAMA
  • #11 9620718
    xamrex
    Poziom 28  
    nsvinc napisał:
    Po drugie, ten sizeof... 'bufor' nie jest TYPEM, tylko wskaznikiem na tablicę 100elementową rezerwowaną na etapie kompilacji. Nie wiem na jakiej podstawie ten kod ogólnie ma rację bytu...


    Nie wiem co chciałeś przez to powiedzieć, ale wydaje mi się, że
    deklarując tablicę
    char tablica[100]
    i potem wpisując sizeof(tablica) to zmiast tego sizeof(tablica) ukaże się tam po prostu liczba (100)
    więc w czym problem?


    2.Nie rozumiem czemu czytanie po 512 bajtów jest prostsze i lepsze niż czytanie np. po 98
    Przecież można utworzyć tablice
    char bufor[100];
    i w kodzie pisać coś takiego:
    res = pf_read(bufor, (sizeof(bufor)-2), &s1);

    w rzeczywistości będzie odczytywał 98 bajtów i teraz dzięki kodowi:

    bufor[s1+1] = 0;
    Zapisze 0 w ostatnim miejscu w tablicy..


    czemu odczytywanie 98 bajtów jest gorsze niż odczytywanie 512?
    Ja tu widzę zaletę, gdyż będziemy mieli więcej pamięci wolnej.
  • #12 9620741
    nsvinc
    Poziom 35  
    Ja tu widzę read access time ktory wyniesie 5x więcej jeśli czytasz po 100 bajtów niż jakbyś czytał raz 512...
    A dodatkowo, po co ci 0 w ostatnim miejscu tablicy? Czyżbyś chciał tą tablicę przetwarzać pętlą która idzie bajt po bajcie w poszukiwaniu zera(?); i zakładasz, że w wlasciwych danych w buforze nigdy przenigdy nie wystąpi 0?
  • #13 9620767
    xamrex
    Poziom 28  
    nsvinc napisał:
    A dodatkowo, po co ci 0 w ostatnim miejscu tablicy?

    Na początku tematu zadałem właśnie pytanie po co te zero tam ma być.
    Odpowiedział mi kolega drzasiek

    drzasiek napisał:
    No zeruje element bufora następny za tym, w którym został zapisany ostatni bajt. Czasem tam lubią zostawać jakieś śmieci i przy wyświetlaniu potem takiego "cudoka" wyświetla.


    Więc chyba po to.

    Co do czasu odczytu, rzeczywiście będzie dłuższy ale będzie za to więcej dostępnej pamięci w uC
  • #14 9620860
    drzasiek
    Specjalista CNC
    Ja odpowiedziałem tylko to co widzę, czyli zeruje element o jeden większy niż liczba odczytanych bajtów. A po co to? Już chyba sam autor kodu czyli Pan Mirek wie..
    Mi czasem wyświetlało jakieś krzaczki tuż za ostatnim odczytanym elementem wyświetlając potem ten bufor, mimo, że przed odczytem był on wyzerowany. Ale tak jak mówię, zdarzyło się to parę razy, nie zastanawiałem się nad tym i nie wiem od czego to zależy.
  • #15 9622591
    mirekk36
    Poziom 42  
    tak jak ktoś już wyżej powiedział - ten cały zapis:

    bufor[s1+1] = 0;

    posłużył TYLKO i wyłącznie do tego żeby zrobić taki sztuczny C-String. Czyli kolejnym razem odczytuję wszystko po kolei z bufora ale nie więcej niż rozmiar sektora, aż napotkam ZERO. I to wszystko .... to nie jest "nie potrzebne" ale tak samo można powiedzieć, że "jest potrzebne". Wszystko zależy od koncepcji tego co robimy co zapisujemy i jak chcemy odczytywać. Przecież nie ma uniwersalnej metody. Każdy zrobi jak chce. Dlatego ja też się nie zgodzę do końca z tezą że np najlepiej jest odczytywać cały bufor 512b jeśli ja tam sobie zapisałem akurat i przetrzymuję tylko jakąś postać tekstową danych....

    Reasumując - nie ma to nic wspólnego z zerowaniem ostatniej komórki bufora - tylko jak wyżej pisze drzasiek - w dalszych częściach na nowej karcie mogą być "krzaczki" więc wyraźnie ZEREM sobie to oddzielam i potem jak pisałem wyżej odczytuję po kolei aż napotkam to własnie ZERO - czyli niezależnie ile bajtów tam zapisałem zawsze będzie dobrze......

    Ale przy zapisie binarnym byłoby to oczywiście totalnie bez sensu - wtedy zrobiłbym inaczej i prawdopodobnie odczytywał cały sektor.... albo tyle konkretnie bajtów ile bym sobie wcześniej wymyślił żeby tam zapisywać. Wsio.
  • #16 9622685
    xamrex
    Poziom 28  
    Dam może cały kod niezmieniony:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zastanawia mnie jeszcze
    	
    s1=4;
    res = pf_write(bufor, sizeof(bufor), &s1);


    Jak było powiedziane wyżej zmienna s1 zwraca wartość ile rzeczywiście bitów zostało odczytanych/zapisanych

    Więc po co ty na sztywno wpisujesz tam 4
    Przecież jeśli zamiast s1=4, wpiszemy s1=2 to to nic (chyba) nie zmieni...
  • #17 9623131
    mirekk36
    Poziom 42  
    ;) .... dlaczego 4 ? ;) spójrz co się wyświetla - TEST albo test

    pewnie że możesz dać s1=2

    albo s1=1

    czy s1=3

    tak samo to zadziała bo sprawdzana jest tylko pierwsza litera

    if(bufor[0]=='t')

    - żeby po kolejnym resecie wyświetlić(zapisać)/odczytać inne dane

    cały ten przykład jest tylko po to, żeby pokazać że jednak jakikolwiek zapis i odczyt się odbywa. Można to zrobić jak pisałem na milion sposobów

    więc jak dasz s1=2 zamiast te s1=4 to w efekcie na wyświetlaczu raz uzyskasz tekst:

    TEST

    TEst
    teST

    i takie tam kombinacje bez sensu ;) ... to w ogóle nie ma żadnego związku z obsługą PetitFat...

    co więcej nie opisywałem właśnie już wyższych funkcji bo one są jasno dosyć opisane na stronie autora - wszystkie te pf_seek, pf_write, pf_read itd .....

    przecież początkującej osobie zwykle więcej problemów sprawia w ogóle uruchomienie całości niż dalsze etapy. Wystarczy sobie przypomnieć opis jak zamienić USI na SPI w przykładzie PetitFat.

    Reasumując - nie ma co rozbijać na drobne dlaczego tu jest s1=4 czy może być s1=2 bo może być ;)

    a powyżej z tym

    bufor[s1+1] = 0;

    to jak widać jeszcze inna idea była - chodziło TYLKO o to, żeby w razie czego po odczycie do bufora zakończyć C-String ZEREM ... nic innego.
  • #18 9623268
    xamrex
    Poziom 28  
    mirekk36 napisał:
    więc jak dasz s1=2 zamiast te s1=4 to w efekcie na wyświetlaczu raz uzyskasz tekst:

    TEST

    TEst
    teST


    A i tu zonk, bo tak się nie dzieje.
    Za każdym razem mam TEST **** bądź test ----
    Próbowałem przy s1=2 i s1=3 i zawsze są tylko te 2 werjsie, nie ma jakiś udziwnień (TEst lub teST )

    nsvinc napisał że ta zmienna
    nsvinc napisał:
    zwraca ile bajtów faktycznie odczytano


    Więc jeśli ona ZWRACA, to dlaczego ty ustawiasz ją na 4.

    Co zmienia w ogóle ta zmienna s1?
    Przecież funkcja przybiera wartości ->
    1) co zapisac (np. dane z tablicy)
    2) Ile zapisac (ile bajtów zapisać z tablicy; ile znaków)
    3) Zwraca ile rzeczywiście zapisała.

    Więc jeśli ty ustawisz s1=4 to wg. mnie nie ma to ŻADNEGO wpływu na to co się wykona bo przecież s1 zwraca wartość, a nie ją ustawia..

    Bardzo proszę o łopatologiczne wytłumaczenie do czego w końcu jest używany ten argument s1.
  • Pomocny post
    #19 9623476
    mirekk36
    Poziom 42  
    No tak to jest jak staram się wytłumaczyć z doskoku na szybko - a nie zerknę w dokumentaqcję bo czasu nie mam. A jeszcze na dokładkę nie mam układu przed sobą.

    poniżej to co mówi dokumentacja, chyba dosyć wyraźnie:

    Cytat:


    pf_write

    The pf_write function writes data to the file.
    FRESULT pf_write (
    const void* Buffer, /* Pointer to the data to be written */
    WORD ByteToWrite, /* Number of bytes to write */
    WORD* BytesWritten /* Pointer to the variable to return number of bytes written */
    );


    Parameters
    Buffer Pointer to the data to be wtitten. A NULL specifies to finalize the current write operation. ByteToWrite Number of bytes to write. BytesWritten Pointer to the WORD variable to return number of bytes read.


    Więc masz rację w tym co piszesz wyżej.

    A zatem tajemniczy zapis

    s1=4;

    jest w tym przypadku w ogóle zbędny, niepotrzebny - ot może została mi jakaś niewykasowana linijka z jakiejś poprzedniej wersji kodu?

    Dodano po 3 [minuty]:

    Jeszcze raz podkreślę - wyrzuciłem te testy z oryginału, które bazowały na połączeniu przez UART i postarałem się zrobić jakąś wizualizację, tego, że ładnie działają zapisy i odczyty na wyświetlaczu LCD.

    Nie było moim celem opisywanie działań tych kilku poleceń pf_**** bo one wydają się być proste jak widać.
  • #20 9623574
    xamrex
    Poziom 28  
    To się wyjaśniło ;D
    Dzięki
  • #21 10241474
    sbruski
    Poziom 11  
    Witam,

    PetitFS śmiga bez problemu, ale funkcja pf_read czyta tylko do pierwszego 0x00. (String z zerem jako EOF?). Jak się tego pozbyć? przeszkadza, bo czytam dane pomiarowe zapisane na karcie, gdzie bajt 0x00 trafia się dość często.
    Dzięki z góry za pomoc...

    Pozdrawiam
    Staszek
  • REKLAMA
  • #22 10242045
    mirekk36
    Poziom 42  
    sbruski napisał:
    .... ale funkcja pf_read czyta tylko do pierwszego 0x00. (String z zerem jako EOF?). Jak się tego pozbyć? przeszkadza, bo czytam dane pomiarowe zapisane na karcie, gdzie bajt 0x00 trafia się dość często.
    ....


    No to ciekawe jak udałoby się zrealizować np takie projekty jak niżej:

    https://www.elektroda.pl/rtvforum/topic2133447.html

    https://www.elektroda.pl/rtvforum/topic2094762.html

    gdyby tak było jak kolega pisze ?

    Nie ma takiego zjawiska w PetitFat żeby czytał coś tam do pierwszego napotkanego zera. Można czytać wszystkie bajty o dowolnej wartości w tym zero, czytać jak ci się żywnie podoba.
  • #23 10242606
    sbruski
    Poziom 11  
    Witam,
    mirekk36 napisał:
    Nie ma takiego zjawiska w PetitFat żeby czytał coś tam do pierwszego napotkanego zera. Można czytać wszystkie bajty o dowolnej wartości w tym zero, czytać jak ci się żywnie podoba.

    Święta racja - chyba przedświąteczne zmęczenie.... Błąd był mój w procedurze:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    i nie mogło być inaczej niż było. Teraz działa. Dzięki za pomoc...

    Pozdrowienia
    Staszek

    edit:
    Idąc za ciosem - mam problem:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    sygnalizuje "write error", ale w pliku jest wszystko OK. Jeżeli zmienię ilość bajtów na 511 to res=0, ale oczywiście brakuje ostatniego bajtu. O co chodzi?

    edit1:
    "Zabiłem" wątek?
    Dalej nie wiem :cry: ...
    Wszystkiego najlepszego z okazji Świąt Bożego Narodzenia :D ...
REKLAMA