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

Atmega32 , problem przy współpracy z zewnętrznym EEPROMEM po

super_sonic 10 Paź 2009 11:25 1265 7
REKLAMA
  • #1 7110583
    super_sonic
    Poziom 17  
    Posty: 307
    Pomógł: 7
    Ocena: 6
    Witam
    Mam problem z SPI w Atmedze32. Staram się skomunikować ją z pamięcią 25LC128.

    SPI inicjalizuję następujaco
    
    void InicjalizacjaSPI(void)
    {
        // Wyjścia SS, SCK, oraz MOSI są wyjściami
        DDRB = _BV(SPI_SS) | _BV(SPI_MOSI) | _BV(SPI_SCK);
        // Ustawiamy SS oraz SCK w stan wysoki
        PORTB = _BV(SPI_SS) | _BV(SPI_SCK);
        // Uaktywniamy SPI, tryb Master, dzielnik 64
        SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
    }
    


    Bajt pod wskazany adres wysyłam następująco:
    
    void WyslijZnakEEPROM(char ch, short int adres)
    {    
        // Ustawiam linię SS w stan niski
        PORTB &= ~_BV(SPI_SS);
        // Instrukcja zapisu zgodnie z dokumentacją pamięci EEPROM
        SPDR = 0b00000010;
        while(!(SPSR & (1<<SPIF)));  
        // Pierwsza połowa adresu
        SPDR = (adres>>8);
        while(!(SPSR & (1<<SPIF)));
        // Druga połowa adresu  
        SPDR = adres;
        while(!(SPSR & (1<<SPIF)));
        // Znak do zapisu  
        SPDR = ch;
        while(!(SPSR & (1<<SPIF)));  
        // Ustawiam linię SS w stan wysoki
        PORTB |= _BV(SPI_SS);
    }
    


    Odczyt z pamięci odbywa się tak:
    
    char OdbierzZnakEEPROM(short int addr) 
    {
        // Ustawiam linię SS w stan niski 
        PORTB &= ~_BV(SPI_SS);
        // Instrukcja odczytu z pamięci
        SPDR = 0b00000011;
        while(!(SPSR & (1<<SPIF))); 
        // Pierwsza połowa adresu
        SPDR = (addr>>8);   
        while(!(SPSR & (1<<SPIF))); 
        // Druga połowa adresu
        SPDR = addr;   
        while(!(SPSR & (1<<SPIF))); 
        // Odczyt zmiennej
        addr=SPDR; 
        // Ustawiamy linię SS w stan wysoki
        PORTB |= _BV(SPI_SS);
        return addr; 
    } 
    


    Wyjście SS procesora podpięte jest pod wejście CS pamięci, linie MISO i MOSI odpowiednio do SO i SI, SCK do SCK. Wejścia HOLD oraz WP pamięci podpięte są do +Vcc. Atmega pracuje na zewnętrznym kwarcu 16MHz. Po próbie zapisu i odczytu dowolnego znaku pod dowolny adres w EEPROMIE, zwracany jest znak '?'. Nie mam pomysłu co może być problemem, może któryś z kolegów znajdzie błąd w moim rozumowaniu.
  • REKLAMA
  • #2 7110635
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 7110655
    super_sonic
    Poziom 17  
    Posty: 307
    Pomógł: 7
    Ocena: 6
    Dziękuję za sugestię, już to sprawdzam.

    Procek do dokładnie: Atmega32 16AU

    Hmm podłączyłem wejście CS pamięci do PB2 procesora. SS Ustawiłem jako wyjście i ustawiłem w stan wysoki. Przed operacjami odczytu i zapisu ustawiam PB2 w stan niski a po operacji w stan wysoki. Efekt jest taki iż zamiast znaków zapytania otrzymuję puste znaki :-)

    W tej chwili kod wygląda następująco:
    
    #define SPI_MISO PB6
    #define SPI_MOSI PB5
    #define SPI_SS PB4
    #define SPI_SCK PB7
    #define SPI_CS PB2
    #define SPI_Disable() (PORTB |= _BV(SPI_CS));
    #define SPI_Enable() (PORTB &= ~_BV(SPI_CS));
    void InicjalizacjaSPI(void)
    {
    	DDRB = _BV(SPI_SS) | _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_CS);
    	PORTB = _BV(SPI_SS) | _BV(SPI_SCK) | _BV(SPI_CS);
    	SPCR = _BV(SPE) | _BV(MSTR);
    }
    
    char OdbierzZnakEEPROM(int addr) 
    { 
    	SPI_Enable();
    	SPDR = 0b00000011;
    	while(!(SPSR & (1<<SPIF))); 
    	SPDR = (addr>>8);   
      	while(!(SPSR & (1<<SPIF))); 
    	SPDR = (addr);   
      	while(!(SPSR & (1<<SPIF))); 
                 addr=SPDR; 
    	SPI_Disable();
                 return addr; 
    } 
    
    
    void WyslijZnakEEPROM(char ch, int adres)
    {
    	SPI_Enable();
    	SPDR = 0b00000010;
    	while(!(SPSR & (1<<SPIF))); 
    	SPDR = (adres>>8);
    	while(!(SPSR & (1<<SPIF))); 
    	SPDR = adres;
    	while(!(SPSR & (1<<SPIF)));  
    	SPDR = ch;
    	while(!(SPSR & (1<<SPIF)));  
    	SPI_Disable();
    }
    


    No już naprawdę nie wiem co jest nie tak :|
  • #4 7111174
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #5 7111448
    super_sonic
    Poziom 17  
    Posty: 307
    Pomógł: 7
    Ocena: 6
    A czy Twoim zdaniem funkcje inicjalizacji SPI i zapisu znaku do EEPROMu są w porządku? wygląda na to, że odczyt już funkcjonuje, natomiast z zapisem jest gorzej
  • REKLAMA
  • Pomocny post
    #6 7111472
    Konto nie istnieje
    Poziom 1  
  • #7 7111598
    super_sonic
    Poziom 17  
    Posty: 307
    Pomógł: 7
    Ocena: 6
    Czy pomiędzy operacjami odczytu, zapisu, czy wysyłania polecenia WREN są konieczne pauzy? A jeśli tak to jakie? :)

    Ok już wszystko działa jak należy. Dziękuję serdecznie koledze :)
  • #8 7111682
    Konto nie istnieje
    Poziom 1  

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z komunikacją SPI między mikrokontrolerem Atmega32 a zewnętrzną pamięcią EEPROM 25LC128. Głównym problemem było nieprawidłowe sterowanie linią SS, która w Atmega32 ma specyficzne zachowanie – ustawienie jej na niski poziom powoduje przejście SPI w tryb slave. Zalecane jest użycie innego pinu do sygnału CS pamięci EEPROM i utrzymanie pinu SS jako wyjścia w stanie wysokim. W trakcie odczytu danych z EEPROM konieczne jest wysyłanie impulsów zegarowych, co wymaga wysłania bajtu dummy (np. 0xFF) w celu wygenerowania zegara i odczytania danych. Przed zapisem należy wysłać polecenie WREN (Write Enable) do EEPROM, aby uaktywnić możliwość zapisu. Między operacjami wskazane jest stosowanie krótkich opóźnień (nopów) rzędu 50 ns oraz dłuższej przerwy około 5 ms po zapisie, aby umożliwić zakończenie operacji zapisu w pamięci. Po zastosowaniu tych zaleceń komunikacja z pamięcią EEPROM działa poprawnie.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA