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

LPC17xx - EEPROM + I2C -nie mogę uzyskać statusu innego niż 0x08

Kubbaz 05 Paź 2012 09:06 2433 13
REKLAMA
  • #1 11379089
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    Witam wszystkich Elektrodowiczów!

    Potrzebuję podłączyć do uC NXP LPC117xx zewnętrzną pamięć EEPROM ATMELa AT24C256 po I2C do przechowywania pewnych danych.
    Z tego co widzę, to NXP sugeruje, żeby wykorzystać przerwanie od I2C do celu wysyłania i odbierania danych po I2C. No i ok.
    Zainicjalizowałem I2C w trybie Master Transmit Mode z bitratem 100 kbps. Wysyłam START i program wchodzi w przerwanie z wartością rejestru statusu 0x08, czyli jak w dokumentacji. Po czym kasuje bit STA i SI (też jak w dokumentacji) i już niestety nie udaje mi się ponownie wejść do przerwania z wartością rejestru statusu 0x18 (ACK odebrane od Slave'a). No i nie wiem co jest nie tak...

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


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 11379425
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #3 11379672
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ten rejestr jest do tego stopnia write-only, że nawet z bitbandingiem nie działa... Znaczy się działa tak, że wszystko w I2CONSET się kasuje (;

    4\/3!!
  • #4 11379742
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    albertb napisał:
    I2CONCLR jest Write only

    Freddie Chopin napisał:
    Ten rejestr jest do tego stopnia write-only

    Ok, wiem (dokumentacja str. 442, rozdz. 19.8.2).
    Ale że niby
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wyczyści cały rejestr LPC_I2C0->I2CONSET ? Skoro jest wstawienie wartości bitowych z ORem... Hmmm...
  • REKLAMA
  • #6 11379902
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    Freddie Chopin napisał:
    Skoro rejestr jest write-only, to wartość jaką z niego odczytasz jest niezdefiniowana. Np będzie to 0xFFFFFFFF... Czemu by nie?

    Ok, już zaskoczyłem :D.
    Żeby zrobić ORa to najpierw trzeba odczytać wartość rejestru, który będzie ORowany z jakąś wartością....
    Zrobiłem lekkie modyfikacje:

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


    I niestety znowu program nie wchodzi w przerwanie w case'a 0x18 (brak statusu 0x18) :/.
  • #7 11379931
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Po primo zamiast używać magicznych wartości użyj makr. Nikt nie zna tego na pamięć i nikt też nie będzie przeglądał dokumentacji żeby zobaczyć co tam poustawiałeś.

    Secundo pokaż schemat.
  • #8 11380056
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    W manualu twierdzą, że powinieneś ustawiać flagę AA w każdym z dwóch trybów które używasz.

    BTW - LPC_I2C0->I2STAT & 0xF8 - maskowanie jest zbędne.

    4\/3!!
  • #9 11389265
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    gaskoin napisał:
    Secundo pokaż schemat.

    LPC17xx - EEPROM + I2C -nie mogę uzyskać statusu innego niż 0x08

    Dodatkowo przesyłam dwa zdjęcia rzeczywistego wyglądu układu:
    LPC17xx - EEPROM + I2C -nie mogę uzyskać statusu innego niż 0x08 LPC17xx - EEPROM + I2C -nie mogę uzyskać statusu innego niż 0x08
    Przewody I2C linii SDA0 i SCL0 mają długość 12 cm i są podciągnięte do VCC +3,1 V rezystorami 9,1 kΩ (0,25W). Napięcie na lini SDA0 podczas stanu wysokiej impedancji wynosi +3,1 V, natomiast na linii SCL0 +0,02 V. Pozostałe linie (A0, A1, WP) są zwarte do masy GND.

    Freddie Chopin napisał:
    W manualu twierdzą, że powinieneś ustawiać flagę AA w każdym z dwóch trybów które używasz.

    BTW - LPC_I2C0->I2STAT & 0xF8 - maskowanie jest zbędne.

    Ok, poprawiłem w kodzie źródłowym:

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


    Linie kodu źródłowego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    mają sygnalizować wejście go danego fragmentu programu.
    No i zapalają się tylko te na P2.3 i na P2.5. Program dalej nie wchodzi do case'a o wartości rejestru statusowego 0x18... :cry:.
    Załączniki:
    • LPCXpresso LPC1769 Schematic.pdf (184.18 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #10 11389342
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Nie lubię się powtarzać, ale czasem mam wrażenie, że większość osób ma dziwną chorobę objawiającą się tym, że jak napisze się do nich 5 rzeczy to zauważają tylko ostatnią...

    Cytat:
    19.10.5.3 State: 0x08
    A START condition has been transmitted. The Slave Address + R/W bit will now be
    transmitted.
    1. Write Slave Address with R/W bit to I2DAT.
    2. Write 0x04 to I2CONSET to set the AA bit.


    Przy okazji nie wiem skąd wyczarowałeś czyszczenie flagi startu... To wszystko jest w manualu!

    4\/3!!
  • #11 11389800
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    Freddie Chopin napisał:
    Przy okazji nie wiem skąd wyczarowałeś czyszczenie flagi startu... To wszystko jest w manualu!

    LPC176x I2C Driver -> Source File -> 190 linia kodu: "regs->I2CONCLR = STA | SI;"

    Cytat:
    19.10.5.3 State: 0x08
    A START condition has been transmitted. The Slave Address + R/W bit will now be
    transmitted.
    1. Write Slave Address with R/W bit to I2DAT.
    2. Write 0x04 to I2CONSET to set the AA bit
    .

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

    Bez zmian... program nie wchodzi do case'a 0x18... Ale fakt, bit AA należy ustawić na 1.
  • #12 11389880
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    1. Na rejestrze I2CONSET też nie ma sensu operować przez "|=".
    2. Dodaj sobie do switcha jeszcze "default:" bo moze po prostu występuje jakiś błąd. Może slave wcale nie wysyła Ci ACK, więc nie wejdziesz do statusu 0x18 tylko do innego - najlepiej więc dorzucić taki "catch-all" na końcu - teraz nie wiadomo w sumie czy nie wchodzi do przerwania,czy może nie wchodzi do tego warunku, czy może jeszcze coś innego.

    4\/3!!
  • #13 11390986
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    Freddie Chopin napisał:
    1. Na rejestrze I2CONSET też nie ma sensu operować przez "|=".
    2. Dodaj sobie do switcha jeszcze "default:" bo moze po prostu występuje jakiś błąd. Może slave wcale nie wysyła Ci ACK, więc nie wejdziesz do statusu 0x18 tylko do

    innego - najlepiej więc dorzucić taki "catch-all" na końcu - teraz nie wiadomo w sumie czy nie wchodzi do przerwania,czy może nie wchodzi do tego warunku, czy może

    jeszcze coś innego.


    Zmodernizowałem kod źródłowy tak, aby móc "podglądnąć" to, co się dzieje lub nie dziejew rejestrze statusowym I2C:

    6 diod LED
    LED 1 na P0.22 - Zapala się tylko wtedy, gdy program wejdzie w przerwanie od I2C0 (START) (poza wejściem w "default'a");
    LED 2 na P2.2 - Zapala się tylko wtedy, gdy program wejdzie w przerwanie od I2C0 i wejdzie w "case'a" o wartości 0x08;
    LED 3 na P2.3 - Zapala się tylko wtedy, gdy program wejdzie w przerwanie od I2C0 i wejdzie w "case'a" o wartości 0x18;
    LED 4 na P2.4 - Zapala się tylko wtedy, gdy program wejdzie w przerwanie od I2C0 i wejdzie w "case'a" o wartości 0x28;
    LED 5 na P2.5 - nie używany pojedynczo;
    LED 6 na P2.6 - nie używany pojedynczo;
    LED 7 na P2.7 - Zapala się tylko wtedy, gdy program wejdzie w przerwanie od I2C0 i wejdzie w "default'a": wówczas wartość rejestru "I2C0 Status Register" (bity 7-3) jest odwzorowana na pięciu diodach LED (b7-LED5, b6-LED5, b5-LED4, b4-LED3, b3-LED2), zatam zapalenie się kombinacji LEDów: 00000X daje wartość rejestru 0x08, 000X0X daje wartość rejestru 0x28 (wystarczy po prawej stronie dopisać bitowo trzy zera);
    LED 7 na P2.7 - Mruga tylko wtedy, gdy program wyjdzie z przerwania i wejdzie do pętli głównej "for (;;)" programu głównego;

    Aktualnie jest tak, że zapalają się diody:
    LED 1 - to znaczy, że program po nadaniu sygnału START wchodzi w przerwanie od I2C0
    LED 2 - to znaczy, że I2C0 osiąga status 0x08 (nadany sygnał START i wysyłamy Slave Address)
    LED 3 - to znaczy, że I2C0 osiąga status 0x18 (Slave Address został wysłany i odebrano od Slave'a ACK)
    LED 7 mruga - to znaczy, że program wychodzi z funkcji przerwania do programu głównego i wykonuje główną pętlę "for (;;)"
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Nie rozumiem tylko dlaczego uC nie wystawia wartości 0x28 do rejestru statusowego, żeby kontynuować nadawanie...
  • #14 11391215
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ja bym w tym defaulcie dorzucił jeszcze dwie rzeczy:
    1. najpierw proponuję wyczyścić te bity na których chcesz wyświetlić diodami status (przed "|=")
    2. na końcu tego defaulta daj "while (1);" bo nie ma specjalnie co wychodzić z tego trybu

    W obecnym stanie nie jestem pewien czy aby na pewno coś zobaczysz, bo on może w kółko wchodzić w przerwanie w przypadku błędu.

    4\/3!!

Podsumowanie tematu

✨ Użytkownik ma problem z komunikacją I2C pomiędzy mikrokontrolerem NXP LPC117xx a pamięcią EEPROM ATMEL AT24C256. Po zainicjowaniu I2C w trybie Master Transmit Mode i wysłaniu sygnału START, status rejestru I2C wynosi 0x08, co jest zgodne z dokumentacją. Jednakże, po próbie kasowania bitów STA i SI, nie udaje się uzyskać statusu 0x18 (ACK od Slave'a). Użytkownicy wskazują na błędne użycie rejestru I2CONCLR, który jest rejestrem tylko do zapisu, co prowadzi do nieprawidłowego działania. Sugerują również dodanie obsługi błędów w kodzie oraz użycie makr zamiast "magic numbers". Użytkownik poprawił kod, aby lepiej monitorować status rejestru I2C za pomocą diod LED.
Wygenerowane przez model językowy.
REKLAMA