I2C EEPROM bit-banging: Zapisuje dobrze, ale tylko jeśli pierwszy bit nie jest ustawiony

9

Obecnie pracuję nad projektem EEPROM I2C wykorzystującym bit-banging do sterowania liniami SDA i SCL.

Moja funkcja odczytu działa dobrze, ale ilekroć piszę dowolny bajt z wiodącym „1”, zawsze czytam FF z powrotem; nawet jeśli bajt był wcześniej programowany z czymś innym. Wiodące „0” jest idealne. To nie jest moja rutyna czytania; jak widzę w zakresie, zwraca FF.

Szukam sugestii, dlaczego tak może być. Czy jest coś oczywistego, co mógłbym przeoczyć, co mogłoby spowodować problem? [Nie mogę opublikować kodu - firma jest poufna ... :(]

Każdy przebieg, na który patrzę, dokładnie spełnia specyfikację. Odłączam EEPROM. Moje podciągnięcia mają 2,2 tys., Więc w ramach specyfikacji. W tym prototypie taktuję około 500 Hz. Układ wysyła potwierdzenia do każdego z moich bajtów, aby je rozpoznać. Ale to po prostu nie działa ...

Używam Microchip 24LC256 .

Uproszczony algorytm zapisu dla jednego bajtu:

wait
SDA low
SCL low
wait
for each bit
    if bit is set:   SDA high
    if bit is unset: SDA low
    wait
    SCL high
    wait
    wait
    SCL low
    wait
wait
SDA high 
SCL high
wait
wait
check ACK status
SDA low
SCL low
wait
return ACK status

Uproszczony algorytm odczytu dla jednego bajtu:

wait
SCL low
SDA high
for each bit (8 bits)
    SCL high
    wait
    wait
    SCL low
    wait
    check and store received bit
    wait
do a NACK or ACK depending on if it is the last byte
Thomas O
źródło
1
@Justin - Myślę, że mówi, że zapisywanie wartości 0x7F na dowolny adres działa, ale zapisywanie 0x80 na dowolny adres nie działa.
Rocketmagnet
1
Takie rzeczy sprawiają, że nienawidzę I2C.
Rocketmagnet
1
Mam szalone przeczucie. Czy w swoim kodzie bitowym nieumyślnie rozszerzasz znaki za pomocą operacji przesunięcia w prawo? Jeśli tak, twój wiodący ostatecznie pozostawi cię z 0xFF po 7 operacjach zmiany.
vicatcu
3
Ironią jest tutaj kod „poufnej firmy”. To jest dla nich cenne. Wszyscy inni udostępniają kod, który działa. Tym, co odróżnia kod tej firmy od innych, jest to, że nie działa.
gbarry
2
Trudno sobie wyobrazić, dlaczego firma tak desperacko musi zachować poufność niektórych kodów bitowych I2C. W Internecie jest tak wiele.
Rocketmagnet,

Odpowiedzi:

4

Odczytujesz dane, gdy zegar znów jest niski. Musisz to zrobić między podniesieniem zegara a obniżeniem go. Gdy zegar jest niski, Slave może zmieniać linię danych, nie gdy jest wysoka.

wprowadź opis zdjęcia tutaj

Czytanie powinno wyglądać tak:

wait
SCL low
SDA high
for each bit (8 bits)
    SCL high                      <--------
    wait
    check and store received bit  <--------
    wait
    SCL low                       <--------
    wait
    wait
do a NACK or ACK depending on if it is the last byte
stevenvh
źródło
Trafne spostrzeżenie; Naprawię to. Jednak moje dane nadal pokazują się jako wszystkie (FF) w moim zakresie, więc mój odczyt nie może być problemem ... :(
Thomas O
3

Ostatecznie problemem okazało się to, że w niektórych warunkach przypadkowo wysyłałem warunek STOP ze względu na zniekształcone taktowanie. Zrezygnowałem z używania lunety i wyjąłem analizator logiki i byłem w stanie naprawić problem w 15 minut, ponieważ podkreślił STOP, który nie powinien tam być. Na podstawie najbardziej pomocnej odpowiedzi wybiorę komu dać nagrodę. Dziękuję za wszystkie rozwiązania.

Thomas O
źródło
Cieszę się, że rozwiązałeś ten problem, „weryfikując czas zapisu”
3
Powiedziałem ci, że można to rozwiązać, patrząc na przebieg.
Rocketmagnet,
@Rocketmagnet Zawsze patrzyłem na przebieg, ale nigdy go nie zauważyłem.
Thomas O
Tak, ale nie pokazałeś nam kształtu fali, mimo że wielokrotnie o to prosiłeś. Mogłeś rozwiązać ten problem kilka dni temu.
Rocketmagnet,
@Rocket - Zgadzam się. Chciałbym mieć w tym czasie aparat. Używany przeze mnie Tek DPO miał napęd dyskietek, ale nie miał dyskietki. Mógłbym zamieścić zdjęcie, gdybym mógł.
Thomas O
2

OK, twój zakres pokazuje, że pierwszy bajt przychodzący do PIC jest zły, więc nie jest to funkcja odczytu PIC.

Czy sprawdziłeś, że czas zapisu jest poprawny na końcu odbierającym?

Czy to zawiedzie w obu poniższych trybach?

- Byte mode sequential
- Page mode Sequential

Specyfikacja pokazuje „Najpoważniejszy bit (MSB)„ b7 ”jest wysyłany pierwszy. Jest to również przypadek, gdy b7 = 1, że cały bajt jest odczytywany jako FF. Więc albo nie jest zapisywany i usuwany (warunek błędu), gdy b7 = 1, lub źle odczytuje jako FF bez względu na wcześniejszą treść. Ponieważ każdy zapis jest wymazywaniem całego bajtu przed zapisaniem, może to być zły zapis lub zły odczyt, lub czas pierwszego bajtu jest inny.

Sugestia: Sprawdź sygnał PTC podczas zapisu / odczytu, aby zapewnić normalne działanie. wprowadź opis zdjęcia tutaj

Istnieje możliwość użycia zewnętrznego zegara do pomiaru długości cyklu E / W za pomocą PTC. Próbowałeś tego użyć?

Czas cyklu TE / W

  • wewnętrzny oscylator 7ms typ
  • zegar zewnętrzny 4 ~ 10 ms min ~ max

Czy spełnia te kryteria?


źródło
1

Wygląda na to, że może to być kilka rzeczy:

  1. Co jeszcze jest w autobusie? Czy może istnieć spór o magistralę z innym urządzeniem, które jest resetowane lub niezainicjowane?
  2. Czy prawidłowo zmieniasz kierunek styku we / wy? Jeśli działa dobrze w przypadku wyjściowym, mógłbyś przypadkowo zapomnieć o zmianie kierunku styku na wejście i zawsze będzie czytał 0xFF. Pin można zostawić jako wyjście napędzające autobus, podczas gdy ty będziesz czytać z niego.
  3. Czy masz wewnętrzne podciągnięcia na samym pinie i / lub na liniach we / wy? Mikrokontrolery zwykle dają zakres rezystancji, a nie stałą wartość. Możesz wyłączyć podciągania na mikro i po prostu użyć dyskretnych na magistrali, ponieważ możesz uzyskać bardziej precyzyjny opór na podciąganie od dyskretnych komponentów.
  4. Polaryzacja zegara - czy na pewno mierzysz prawą krawędź / fazę między zegarem / danymi? Być może odliczasz czas, co wygląda świetnie na lunecie, ale jeśli faza jest poza linią, cała pamięć EEPROM zobaczy 0xFFs (i najprawdopodobniej zwróci to samo, ponieważ prawdopodobnie jest to nieprawidłowe polecenie / warunek).
Joel B.
źródło
1. Tylko EEPROM i MCU. 2. Tak, wydaje mi się, że tak, ponieważ pamięć EEPROM jest w stanie utrzymać SDA / SCL na niskim poziomie. 3. Na płycie sąsiadującej z EEPROM znajduje się 2,2k 5% podciągnięć.
Thomas O
w przypadku # 2, czy jesteś pewien, że EEPROM utrzymuje ten autobus nisko. Czy EEPROM ma jakieś warunki w arkuszu danych, w których zwróci wszystkie 0xFFs? Zobacz też moje zmiany powyżej.
Joel B
# 4. EEPROM „POTWIERDZA” moje prośby i działa z niektórymi słowami, ale nie wszystkimi.
Thomas O
0

Przedstawiłem to jako komentarz powyżej, ale moje zaufanie do odpowiedzi rośnie cicho w głębokich zakamarkach mojego umysłu, więc promuję ją na odpowiedź.

Mam szalone przeczucie, że prawie na pewno jest to błąd oprogramowania niskiego poziomu związany z podpisywaniem niektórych zmiennych. Czy w swoim kodzie bitowym nieumyślnie rozszerzasz znaki za pomocą operacji przesunięcia w prawo? Jeśli tak, twój wiodący ostatecznie pozostawi cię z 0xFF po 7 operacjach zmiany.

Steven wspomniał o tym w komentarzu, ale czy byłeś świadkiem świętości swoich operacji zapisu na osilloskopie, czy tylko zakładasz, że działają one w oparciu o połowę odwróconych pleców i wyglądają dobrze? Jeśli nie próbowałeś spojrzeć na operację zapisu wartości 0xAA, warto spróbować.

Jeśli potrafisz podać rzeczywisty kod wewnętrznej pętli i powiązane deklaracje zmiennych, możemy wykryć błąd.

vicatcu
źródło
Moje pisma są dobre; Widzę to na lunecie. Kolejna dziwność: adresy z wiodącym MSB są w porządku. Tylko dane powodują problemy! Myślę o wkrótce opublikowaniu kodu.
Thomas O
1
Na poparcie tej odpowiedzi: jeśli jest to kod C, zmień wszystkie deklaracje „char” na „unsigned char” i spróbuj ponownie.
Wouter van Ooijen,