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

Jak skonfigurować SPI dla ATMega32 i pamięci 25C040?

Mystik 04 Mar 2006 17:23 1695 1
REKLAMA
  • #1 2373993
    Mystik
    Poziom 11  
    Posty: 88
    Ocena: 5
    Witam

    Od jakiegos czasu probuje pożenić ATMege32 i pamieć 25C040 za pomocą wbudowanego interfejsu SPI.
    Przykłady w manualu do ATMegi sa proste jak gwizdek i w ogóle wszystko wygląda bardzo łatwe, ale jakoś nie mogę tego przeskoczyć.
    Zacząłem tak:

    
     SPCR = 0x72; //setup SPI
     SPSR = 0x00; //setup SPI
    

    no i potem zacząłem próbę zapisu i odczytu danej do i z pamięci:

    Zapis
    
    void SPI_WyslijZnak(char data)
    {
    PORTB&=~0b00010000;               //PortB.4 jako CS = poziom niski
    SPDR=data;
    while (!(SPSR & (1<<SPIF)) );
    SPSR &=~SPIF;                          //kasowanie znacznika końca transmisji
    PORTB|=0b00010000;                //PortB.4 jako CS poziom wysoki
    }
    
    void SPI_WyslijDane(char adres, char data)
    {
    SPSR &=~SPIF;
    SPI_WyslijZnak(0b00000010);   //instrukcja zapisu danej do pamięci
    SPI_WyslijZnak(adres);            //przesłanie adresu
    SPI_WyslijZnak(data);             //przesłanie danej
    }
    

    no i odczyt danej z pamięci:
    
    char SPI_OdbierzData(char adres)
    {
    SPSR &=~SPIF;                          //kasowanie znacznika końca transmisji
    PORTB&=~0b00010000;             //CS=poziom niski
    SPDR=0b00000011;                  //instrukcja odbioru danej z pamięci
    while (!(SPSR & (1<<SPIF)) );   
    
    SPSR &=~SPIF;                       //skasowanie znacznika końca transmisji
    SPDR=adres;                          //przasłanie adresu danej
    while (!(SPSR & (1<<SPIF)) );
    
    SPSR &=~SPIF;                       //skasowanie znacznika końca transmisji
    SPDR=33;                               //wysłanie czegokolwiek, zeby w SPDR 
                                                   znalazła się wartość danej
    while (!(SPSR & (1<<SPIF)) );
    
    SPSR &=~SPIF;                       //skasowanie znacznika końca transmisji
    PORTB|=0b00010000;             //CS=poziom wysoki
    return SPDR;
    }
    

    Oczywiście powyższe jest jedną z wielu prób. Niestety żadna z nich nie zakończyła się sukcesem. Dlatego zdecydowałem się zwrócić do Was o pomoc. Jeżeli ktoś zrobił obsługę wbudowanego portu SPI w języku C to może mógłby mi pomóc?

    pozdrawiam
    Mystik
  • REKLAMA
  • #2 2378554
    Mystik
    Poziom 11  
    Posty: 88
    Ocena: 5
    Mystik napisał:
    Witam

    Od jakiegos czasu probuje pożenić ATMege32 i pamieć 25C040 za pomocą wbudowanego interfejsu SPI.
    Przykłady w manualu do ATMegi sa proste jak gwizdek i w ogóle wszystko wygląda bardzo łatwe, ale jakoś nie mogę tego przeskoczyć.


    Wiem, że mogę zmienić posta, ale może dla potomnych lepiej będzie jak odpowiem sam sobie. Problem bowiem przeskoczyłem.
    Poniżej podaje działające u mnie procedury w C odczytujące i zapisujące dane do pamięci 25C040. Zegar SCK ustawiony był na 2MHz.
    
    void spi_init(void)
    {
     PORTB|=0b00010000;
     SPCR = 0b01010000; //setup SPI
    }
    
    void SPI_WyslijDane(char adres, char data)
    {
    SPI_Zapis();
    PORTB&=~0b00010000;		 			 	  //CS = stan niski
    SPDR=0b00000010;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=adres;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=data;
    while (!(SPSR & (1<<SPIF)) );
    PORTB|=0b00010000;		   	 			  //CS = stan wysoki
    while (SPI_OdbierzRejestr()==3);	  //Czekaj dopóki pamięć jest zajęta
    }
    
    char SPI_OdbierzData(char adres)
    {
    PORTB&=~0b00010000;		  				  //CS = stan niski
    SPDR=0b00000011;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=adres;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=0;
    while (!(SPSR & (1<<SPIF)) );
    PORTB|=0b00010000;		   	 			  //CS - stan wysoki
    return SPDR;
    }
    
    char SPI_OdbierzRejestr(void)
    {
    PORTB&=~0b00010000;			 			 //CS = stan niski
    SPDR=0b00000101;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=0;
    while (!(SPSR & (1<<SPIF)) );
    PORTB|=0b00010000;		   	 			//CS = stan wysoki
    return SPDR;
    }
    
    void SPI_ZapiszRejestr(char rejestr)
    {
    char x;
    SPI_Zapis();
    PORTB&=~0b00010000;						//CS = stan niski
    SPDR=0b00000001;
    while (!(SPSR & (1<<SPIF)) );
    SPDR=rejestr;
    while (!(SPSR & (1<<SPIF)) );
    PORTB|=0b00010000;		   	 			// CS = stan wysoki
    while (SPI_OdbierzRejestr()==3);  //Czekaj dopóki pamięć jest zajęta
    }
    
    void SPI_Zapis(void)			  		//Zezwolenie na zapis do pamięci
    {
    PORTB&=~0b00010000;						//CS = stan niski
    SPDR=0b00000110;
    while (!(SPSR & (1<<SPIF)) );
    PORTB|=0b00010000;		   	 			//CS = stan wysoki
    }
    


    i użycie procedur w programie:

    
    void main(void)
    {
    char x=0;
    
    init_devices();                     //tu również odpalana jest Spi_init();
    
    SPI_WyslijDane(1,'Q');
    SPI_WyslijDane(2,'L');
    
    x=SPI_OdbierzData(1);
    x=SPI_OdbierzData(2);
    }
    

    Zwracam szczególną uwagę na procedurę SPI_Zapis(), która w ogóle pozwala na jakikolwiek zapis do pamięci. Musi być ona użyta przed każdym zapisem.
    Drugą rzeczą jest sprawdzanie, czy pamięć nie jest zajęta zapisem. Bez sprawdzenia tego kolejne operacje na pamięci będą nieudane.
    Procedury SPI_ZapiszRejestr( ) dołączyłem jako coś extra :).

    Mam nadzieję, że moje wypociny komuś się przydadzą.

    pozdrawiam
    MYSTIK
REKLAMA