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

[ATMega16][C] Odczyt danych z pamięci AT93C56A

LosRabinos 01 Wrz 2011 11:40 1403 3
REKLAMA
  • #1 9884273
    LosRabinos
    Poziom 10  
    Witam
    Próbuję zapisać , a następnie odczytać dane z pamięci AT93C56A przez interfejs SPI.
    Po kompilacji obserwuję odczytywane dane w terminalu PC, lecz nie są one poprawne, gdyż ciągle otrzymuję wartości: 0, 0, 255, 255... itd.
    Czy mógłby mnie ktoś nakierować co powinienem zmienić w programie, żeby otrzymywać zapisywaną wartość: 7 ?
    Poniżej przedstawiam kod programu.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

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

    Z góry dziękuję za jakiekolwiek wskazówki.
  • REKLAMA
  • #2 9885469
    Andrzej__S
    Poziom 28  
    LosRabinos napisał:

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


    Nie rozumiem, dlaczego w tym fragmencie zerujesz linię CS na 1us następnie znowu ustawiasz na 10ms, potem znowu zerujesz i natychmiast po wyzerowaniu ustawiasz ponownie. Taka operacja miałaby sens, gdybyś odczytywał status READY/BUSY z pinu DO układu slave, ale to raczej nie będzie koniczne, jeśli odczekasz odpowiednią ilość czasu. Myślę, że wystarczyłoby zamiast tego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Poważniejszym problemem jest jednak to, że w czasie odbierania danych powinieneś mieć na SCK sygnał zegarowy. Aby go wymusić, funkcja SPI_Receive powinna na początku zawierać wpis do rejestru SPDR:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dodatkowo funkcja SPI_Send jest też napisana nieprawidłowo, gdyż po jej zakończeniu nie jest wyzerowana flaga SPIF.
    Atmel napisał:

    Alternatively, the SPIF bit is cleared by first reading the
    SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).

    Kolejność instrukcji w funkcji SPI_Send powinna więc być odwrotna. Zresztą gdybyś tak miał w swoim kodzie (odwrotnie), to w połączeniu z niepoprawną funkcją SPI_Receive program najprawdopodobniej zawieszałby się na tej ostatniej, czekając na ustawienie flagi, która nigdy nie zostałaby ustawiona.

    PS. Mam nadzieję, że nie zapomniałeś o podłączeniu pinu ORG pamięci do masy. Pozostawienie tego wejścia niepodłączonego ustawia organizację pamięci na 16-bitową.
  • REKLAMA
  • #3 9893524
    LosRabinos
    Poziom 10  
    Stosujc się do powyższych wskazówek uruchomiłem program, lecz teraz w terminalu nic się nie wyświetla, więc na to wygląda, że gdzieś flaga SPIF nie jest ustawiana i program się zapętla.
    Bardzo proszę o jakieś wskazówki w rozwiązaniu problemu.
    Poniżej przedstawiam poprowiony kod programu.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #4 9893886
    Andrzej__S
    Poziom 28  
    Przyznaję, że wcześniej skoncentrowałem się na poprawności obsługi sprzętowego SPI. Teraz przyjrzałem się dokładniej nocie katalogowej pamięci AT93C56. Jej obsługa może być dosyć skomplikowana, dlatego że transmisja wymaga ilości wysyłanych bitów niepodzielnej przez 8. Być może uda się to zrealizować za pomocą sprzętowego SPI, ale może też być konieczna obsługa programowa. Chyba, że ktoś na forum zna odpowiednie sztuczki i zechce się podzielić. Ja nigdy nie miałem potrzeby takiej obsługi, więc nie mam wypracowanych rozwiązań.
    Chodzi przede wszystkim o to, że jako Star Bit i Op Code wysyłasz bajt 0b000001xx, gdzie 1 to Start Bit a xx to jest 2-bitowy Op Code. Powinieneś zamiast tego wysłać 0b1xx, bez tych zer na początku. Przynajmniej tak wynika z noty, chyba, że pamięć te zera ignoruje do momentu odebrania Start Bit (1). Nie znalazłe w nocie na ten temat informacji. Można by spróbować tak spreparować dane, by miały odpowiedni format (np. poprzez przesunięcia bitowe i funkcję OR), ale i tak sprzętowe SPI wyśle wtedy 24 takty zegarowe zamiast oczekiwanych 20 (Start Bit [1] + Op Code [2] + Address [9] + Data [8]). Nie mogę jednak nigdzie znaleźć informacji, jak pamięć zareaguje na te dodatkowe takty zegarowe. Poza tym odczyt bajtu danych też wymagałby odbierania dwóch bajtów i odpowiedniej obróbki.

    No i dodatkowo zauważyłem, że nie wysyłasz przed zapisem do pamięci Op Code = EWEN. Jest to wymagane, ze względu na to, że:
    Atmel napisał:

    To assure data integrity, the part automatically goes into the Erase/Write Disable (EWDS) state when power is first applied. An Erase/Write Enable (EWEN) instruction must be executed first before any programming instructions can be carried out.


    PS. Spróbuj może zlokalizować miejsce, w którym program zawisa np. poprzez wstawianie w kolejne miejsca pętli while jakiejś instrukcji zapalającej jakąś diodę lub wysyłającej coś przez UART. Dowiesz się w ten sposób, czy program dochodzi do tej instrukcji, czy nie.
REKLAMA