Skocz do zawartości

Kurs STM32L4 – #12 – zewnętrzna pamięć EEPROM (I2C)


Pomocna odpowiedź

Kurs STM32L4 – #12 – zewnętrzna pamięć EEPROM (I2C)

Do tej pory omówiliśmy dwa interfejsy szeregowe na STM32L4, czyli UART i SPI. Pierwszy wymagał dwóch linii, ale był dość powolny. Drugi pracował szybciej, ale wykorzystywał więcej wyprowadzeń. Teraz zajmiemy się I2C, czyli kolejnym interfejsem komunikacyjnym, dzięki któremu do tych samych linii możemy łatwo podłączyć wiele urządzeń.

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

  • Lubię! 1
Link to post
Share on other sites

Przypominamy: w komentarzach do kursów rozmawiamy wyłącznie na tematy związane z konkretnym kursem. Mile widziane są również informacje od osób, które korzystały wcześniej z naszych poradników. Wszystko po to, aby kursanci, którzy mają zamiar korzystać z tego kursu nie musieli "przedzierać" się przez dziesiątki postów na inne tematy. Pytania na tematy, które nie są związane z kursem można zadawać na naszym forum o mikrokontrolerach.

Link to post
Share on other sites

Zachęcam do lektury kolejnej części kursu STM32L4 - to już dwunasty odcinek! Tym razem o komunikacji przez I2C na przykładzie małej pamięci EEPROM. W następnym odcinku wykorzystamy tę widzę do komunikacji z precyzyjnym czujnikiem wysokości, dzięki czemu będzie mogli mierzyć wysokość (tak jak robią to np. sportowe zegarki) 😉

Link to post
Share on other sites

Ten odcinek polecam z czystym sumieniem również wszelkiej maści Arduinowcom - może nie muszą czytać o tym jak się gmera po rejestrach STM-a, ale jaka jest zasada transmisji, dlaczego są potrzebne rezystory, słówko o prędkościach - warto wiedzieć.

Natomiast w całej części o EEPROM-ie zabrakło jednej ważnej informacji.

Ale wyjaśnijmy najpierw, skąd te tajemnicze 5 milisekund.

Otóż zapis w pamięci EEPROM działa dwuetapowo. W czasie transmisji dane są zapisywane w jej wewnętrznym buforze roboczym, a dopiero po zakończeniu następuje przepisanie zawartości bufora do właściwej pamięci. Według producenta czas tej operacji nie przekroczy 5 msec.

I tu możemy się naciąć na pewną nieprzyjemną cechę zwaną "wielkością bufora".

Otóż w omawianym typie pamięci bufor ma wielkość 8 bajtów. I tyle maksymalnie możemy zapisać jednym poleceniem. Maksymalnie - to jednak nie znaczy, że zawsze będziemy mogli zapisywać dane do pamięci w 8-bajtowych sekwencjach.

Pamięć ma oczywiście odpowiedni licznik wewnętrzny, i ten jest inkrementowany po przyjęciu każdego bajtu. Ale nie całkiem - inkrementowane są tylko najmłodsze bity w ilości odpowiadającej rozmiarowi strony w pamięci (w tym przypadku, dla 8-bajtowej strony mamy trzy bity). Co z tego wynika - otóż jeśli będziemy wpisywać dane pod adres przekraczający wyrównanie do wielkości strony (czyli w naszym przypadku niepodzielny przez 8), licznik w pewnym momencie po prostu się przekręci i np. następnym adresem po 15 będzie nie 16 a 8! I dlatego przy próbie zapisu dwóch bajtów pod adres 15 w rzeczywistości owe bajty będą zapisane pod adresami 15 i 8 (co oczywiście nie jest naszym celem). To samo stanie się w przypadku próby zapisania więcej niż 8 bajtów nawet pod adres podzielny przez wielkość strony: zapisane zostanie tylko tyle bajtów, na ile pozwala wielkość bufora (przy czym z reguły nie będą to te bajty, na których nam zależy).

Dla dociekliwych proponuję więc zadanie: napisanie funkcji zapisującej dane w EEPROM-ie z uwzględnieniem wielkości strony. Przy czym należy pamiętać, że w różnych typach pamięci wielkość strony może być różna!

Oczywiście problem nie występuje w czasie odczytu, możemy odczytać tyle danych ile chcemy (i oczywiście na ile nam pozwala architektura naszego mikrokontrolera i używane biblioteki).

  • Lubię! 2
Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

@ethanak może najpierw małe wyjaśnienie - celem tej części kursu było głównie pokazanie sposobu działania interfejsu I2C oraz jego obsługi z poziomu biblioteki HAL dla STM32. Sama pamięć EEPROM jest tylko prostym i popularnym przykładem. Masz oczywiście w pełni rację odnośnie bufora zapisu, postanowiliśmy jednak świadomie nie opisywać tego w tej części kurs. Ograniczyliśmy się tylko do uwagi: "Na dodatek, przesyłając więcej niż jeden bajt, należy brać pod uwagę wielkość licznika oraz adresowanie stron. Szczegóły na ten temat znaleźć można oczywiście w dokumentacji tego układu". Po prostu nie chcieliśmy już dodawać tutaj informacji, które nie są związane ściśle z głównym bohaterem kursu, czyli STM32. Temat, który przytoczyłeś sprawdzi się jednak świetnie w kwestii zadania domowego lub ewentualnej kontynuacji tego kursu 😉 

  • Lubię! 1
Link to post
Share on other sites

@Elvis a więc niech mój post pozostanie inspiracją dla młodych padawanów ST 🙂

@Treker robiłeś coś przy edytorze? Bo coraz ładniej wygląda z coraz mniej można z niego korzystać (np. na moim FX-sie nie mogę wywalić nowej linii między nickiem Elvisa a moim tekstem, XUbuntu 20.04)

 

  • Lubię! 1
Link to post
Share on other sites

@ethanak od wielu miesięcy nic w tym zakresie nie było zmieniane. Edytowałem Twój post i linijkę normalnie usunąłem za pomocą klawisza delete (Chrome) 🙂

Link to post
Share on other sites
33 minuty temu, Treker napisał:

linijkę normalnie usunąłem za pomocą klawisza delete (Chrome)

Czyli najnowszy Firefox ma jakieś własne zdanie - zauważyłem to już wcześniej, edytor wariuje nawet jak wstawię emotkę i potrafi nie reagować np. na klawisze kursora. Czyli trzeba się przyzwyczaić.

Link to post
Share on other sites

Mam jedną uwagę praktyczną do tej części kursu, a można by to wykorzystać jeszcze w innych miejscach. Chodzi mi o możliwość podglądu zapisu przebiegów z analizatora. Prezentacja w formie pliku graficznego ma swoje ograniczenia, a ładując zapisany plik do własnego programu analizującego można lepiej analizować dane, szczególnie dla takich przypadków, gdy na pliku graficznym ciężko o szczegóły. Wiem że to dodatkowa praca i pewnie jedna osoba na dziesięć z skorzysta, ale może warto to rozważyć

 

  • Lubię! 1
Link to post
Share on other sites

@Emtorek witam na forum 🙂 

9 godzin temu, Emtorek napisał:

I dlaczego typ void

void możesz napisać gdy nie podajesz w zmiennej żadnych argumentów. Ale tobie chyba chodzi o coś innego.

Wydaje mi się, że pytasz o wskaźnik na zmienną void *. Oznacza to wskaźnik na zmienną – jej adres, który nie ma informacji o tym jaki typ danych jest w tej pamięci więc nie ma informacji ile bajtów zajmują zmienne.

HAL_StatusTypeDef eeprom_read(uint32_t addr, void* data, uint32_t size)
{
    eeprom_wait();
    return HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDR, addr, 1, data, size, HAL_MAX_DELAY);
}

Widać to w kodzie, data to bufor (tablica) zmiennych typu void *, czyli wskazujemy początek obszar o rozmiarze size ale nieznanym typie danych. Dzięki temu możemy w kodzie odwołać się do dowolnego typu danych, np. 4 bajtowego countera:

eeprom_read(0x10, &counter, sizeof(counter))

I poinformować funkcję ile ma zarezerwować miejsca używajac operatora sizeof, który zwraca liczbę bajtów zajmowaną przez zmienną/typ danych ewentualnie długość tablicy jak jest bezpośrednio podana. Dla uściślenia pierwsza zmienna addr oznacza adres w przestrzeni eepromu, adres daty wskazuje na miejsce w pamięci operacyjnej STM.

Wątpliwość jak rozumiem budzi to, że w funkcji HAL jest uint8_t, to pytanie już do @Elvis

Edytowano przez Gieneq
  • Lubię! 1
Link to post
Share on other sites
37 minut temu, Gieneq napisał:

Wątpliwość jak rozumiem budzi to, że w funkcji HAL jest uint8_t

Po prostu w C (ale nie C++) typ void * oznacza "wskaźnik na cokolwiek" i można go użyć w miejsce dowolnego wskaźnika. Przykładowo jeśli mamy funkcje:
 

int cośtam(uint8_t *data, size_t count);
char *cośinnego(int size);

możemy je wywołać np. tak:
 

void *data;
int wynik;
data = cośinnego(10);
wynik = cośtam(data, 10);

W C++ już ten numer nie przejdzie 🙂

A uint8_t jest pewnie dlatego, że wygodnie się go używa (np. w iteracjach).

 

Link to post
Share on other sites

@ethanak tak zgadza się. Tylko tu podejrzane jest przejście z czegoś szczegółowego do ogólnego ale od zewnątrz. Zazwyczaj nabudowuje się w przeciwnym kierunku. Np w Javie funkcje ogólnego przeznaczenia miały u mnie argument List (interfejs, tj. abstrakcyjny), a dopiero w konkretach zastępowałem np. ArrayList który już miał swój obiekt.

 Odesłałem do wyższej instancji, bo nie jestem ekspertem, ale jednak zaryzykuję i ocenię, że w tej funkcji HAL powinien być void *. Tak przynajmniej kojarzę z prac przy OpenGl, że jak coś się wysyłało do pamięci (tam do pamięci karty graficznej) to do adresowania danych jako zlepek bytów używało się void *.

image.thumb.png.f52b2349cebc492d647cc1fc8bd8ddf8.png

Ale chyba to nie ma większego znaczenia, bo jak jesteśmy w C to void * można iterować tak jak uint8_t co 1B więc to jest chyba tylko dylemat dot. estetyki kodu.

Link to post
Share on other sites
42 minuty temu, Gieneq napisał:

void * można iterować tak jak uint8_t co 1B

Prawie... a prawie robi wielką różnicę.

Nie można np. zrobić dereferencji, a to może utrudnić życie.

Przykładowo (taka teoretyczna funkcja):
 

wypisz(void *d, int count)
{
    while (count-->0) wypisz_znak(*d++);
}

raczej słabo się skompiluje...

 

  • Lubię! 1
Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.