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

Komunikacja z kartą SD w trybie SPI na ATmega168 w C++ - kod i komendy

qutrit 26 Lip 2011 23:22 3420 26
REKLAMA
  • #1 9762866
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Witam.
    Otóż mam taki kod, do próby nawiązania komunikacji z kartą SD podłączoną w trybie SPI
    
    #include <avr/io.h>
    #include <util/delay.h>
    
    											//Komendy dostepne w trybie SPI
    
    #define go_idle_state			0x40 //0
    #define send_op_cond 			0x41 //1
    #define cend_csd				0x49 //9
    #define send_cid				0x4a //10//01001010
    #define send_status				0x4d //13
    #define set_blocken				0x50 //16
    #define read_single_block		0x51 //17
    #define write_block				0x58 //24
    #define program_csd				27
    #define set_write_port			28
    #define clr_write_port			29
    #define send_write_port			30
    #define tag_sector_start		0x60 //32
    #define tag_sector_end			0x61 //33
    #define untag_sector			0x62 //34
    #define tag_erase_group_start	0x63 //35
    #define tag_erase_group_end		0x64 //36
    #define untag_erase_group		0x65 //37
    #define erase					0x66 //38
    #define crc_on_off				0x7b //59
    
    												//odpowiedzi
    
    #define r1_busy					128
    #define r1_parametr				64
    #define r1_address				32
    #define r1_erase_seq			16
    #define r1_com_crc				8
    #define r1_illegal_com			4
    #define r1_erase_reset			2
    #define r1_idle_state			1
    								
    	#define Finish 1
    	#define leave 0
    								
    								#define pincs 			0
    								#define portcs 			PORTB
    								
    								#define dir_cs_in			DDRB&=~(1<<pincs);
    								#define dir_cs_out			DDRB|= (1<<pincs);
    								
    								#define out_cs_low 		portcs &=~(1<<pincs);
    								#define out_cs_hi		portcs |= (1<<pincs);
    
    										
    #ifndef mmc_asm
    
    											//deklaracje typow
    
    		typedef unsigned char u08;
    		typedef unsigned short u16;
    		typedef unsigned long u32;
    
    											//prototypy funkcji
    
    		u08 reset(void);
    		u08 read_sector(u32 sector);
    		u08 write_sector(u32 sector);
    		u32 capacity(void);
    		u08 get_cid(void);
    #endif
    
    
    u08 mmc_sbuf[512]; //bufor sektora
    
    
    //procedury pomocnicze
    
    void spi_init(void)
    {
    DDRB |= (( 1 << PB5 ) | ( 1 << PB3 ) | ( 1 << PB2 )); //MOSI, SCK, SS' jako wyjścia
    SPCR = (( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR1 ) | ( 1 << SPR0 ));   //Włączamy SPI,    
    }					//układ Master, najmniejsza częstotliwość SCK fosc / 128
    
    
    u08 spi_tx_rx(u08 byte)					//wysylanie i odbior przez spi
    {
    SPDR = byte;
    while((SPSR & 128)!=128) 				//czekaj na zakonczenie transmisji 
    return (SPDR);
    }
    
    void finish(void)						//zakonczenie trasmisji
    {
    dir_cs_out;				//cs wyjscie
    out_cs_hi;				//cs wysoki
    spi_tx_rx(0xff);				//wysli 8 imp zegarowych
    }
    
    void flush_mmc(u08 count)
    {
    while(count--)
    spi_tx_rx(0xff);
    }				
    
    									//wysylanie komendy i odbior potwierdzenia		
    u08 mmccmd(u08 cmd, u32 param, u08 state)
    {
    u08 i, tmp;
    dir_cs_out;						//cs wyscie
    out_cs_low;	 					//cs niski
    	spi_tx_rx(cmd);					//wysli komende
    	spi_tx_rx(param>>24);				//wysli 4 bajty argumentu
    	spi_tx_rx(param>>16);	
    	spi_tx_rx(param>>8);
    	spi_tx_rx((u08)param);				//lsb
    	spi_tx_rx(0x95);				// wysli crc
    	
    	for(i=0;i<10;i++) 
    	{
    		tmp=spi_tx_rx(0xff);  			  //odbierz odpowiedz, wysylajac cokolwiek np 0xff
    	}
    		PORTD=tmp;   //Caly czas 0xFF !!! a powinno byc 0x01 -co oznacza in idle state 	
    		finish();
    			
    		return tmp;
    
    }
    						
    						
    						
    							//inicjalizacja spi oraz reset
    u08 reset(void)
    {
    u08 tmp;
    dir_cs_out;					//cs wyjscie
    out_cs_hi;	 					//cs niski
    spi_init();						// inicjalizacja spi
    flush_mmc(10);					//80 pustych cykli zegarowych
    tmp=(mmccmd(go_idle_state, 0, Finish));
    return 1;								
    
    }
    
    main()
    {
    DDRD = 0xff;
    reset();
    }
    


    Do PORTD mam podłączonych 8diód za pomocą których monitoruję sobie, co odpowiada mi karta. Cały problem w tym, ze w funkcji mmccmd, PORTD cały czas równa się 0xFF (wszystkie diody świecą). A powinno choćby raz na jakiś czas być 0x01, co oznaczałoby prawidłowe przełączenie się w tryb "in idle state".
    Kartę mam 512MB mikroSD z telefonu Nokia, włożoną do adapteru który jest podłączony do płytki stykowej. Procesor oraz karta zasilana jest z portu USB za pomocą stabilizatora LM1117T 3.3V. Karta jest prawidłowo wykrywana i daje się formatować w komputerze.
    Nie mam już pojęcia ani pomysłów, co może być nie tak :( Czy hardware czy software ? Moze ktoś z forumowiczów wie, co może być nie tak, lub widzi jakiś "głupi" błąd w sofcie ?
    Pozdrawiam
  • REKLAMA
  • Pomocny post
    #2 9766423
    drzasiek
    Specjalista CNC
    Posty: 2212
    Pomógł: 106
    Ocena: 3233
    A schemat?
    Tylko kompletny a nie jakieś wycinki.
  • #3 9766812
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Jeszcze uprościłem kod:
    
    
    #include <avr/io.h>
    #include <util/delay.h>
    								
    	#define Finish 1
    	#define leave 0
    								
    								#define pincs 			0
    								#define portcs 			PORTB
    								
    								#define dir_cs_in			DDRB&=~(1<<pincs);
    								#define dir_cs_out			DDRB= (1<<pincs);
    								
    								#define out_cs_low 		portcs &=~(1<<pincs);
    								#define out_cs_hi		portcs |= (1<<pincs);
    
    										
    #ifndef mmc_asm
    
    											//deklaracje typow
    
    		typedef unsigned char u08;
    		typedef unsigned short u16;
    		typedef unsigned long u32;
    
    											//prototypy funkcji
    
    		u08 reset(void);
    		u08 read_sector(u32 sector);
    		u08 write_sector(u32 sector);
    		u32 capacity(void);
    		u08 get_cid(void);
    #endif
    
    
    
    
    
    
    
    u08 spi_tx_rx(u08 byte)					//wysylanie i odbior przez spi
    {
    SPDR = byte;
    while(!(SPSR & (1<<SPIF))) 				//czekaj na zakonczenie transmisji 
    return (SPDR);
    }
    
    void finish(void)						//zakonczenie trasmisji
    {
    dir_cs_out;				//cs wyjscie
    out_cs_hi;				//cs wysoki
    spi_tx_rx(0xff);				//wysli 8 imp zegarowych
    }				
    
    main()
    {
    _delay_ms(3);	
    DDRB |= (1 << PB3) | (1 << PB5)| ( 1 << PB2 ); //MOSI, SCK, SS' jako wyjścia
    SPCR = (( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR1 ) | ( 1 << SPR0 ));   //Włączamy SPI,    
    					//układ Master, najmniejsza częstotliwość SCK fosc / 1
    u08 i, tmp;
    DDRD = 0xff;
    dir_cs_out;						//cs wyjscie
    out_cs_hi;
    _delay_ms(1);		 	 		// inicjalizacja spi
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    dir_cs_out;						//cs wyscie
    out_cs_low;	 	
    //_delay_ms(1); 					//cs niski
    	spi_tx_rx(0x40);					//wysli komende
    	spi_tx_rx(0x00);			//wysli 4 bajty argumentu
    	spi_tx_rx(0x00);
    	spi_tx_rx(0x00);
    	spi_tx_rx(0x00);				//lsb
    	spi_tx_rx(0x95);				// wysli crc dla komendy cmd64
    	
    	for(i=0;i<10;i++)
    		{
    		tmp=spi_tx_rx(0xff);
    		}
    			
    			finish();
    			PORTD=tmp;   //JAKIEŚ PRZYPADKOWE KOMBINACJE,  NAJCZĘŚCIEJ 0XFF tj. wszystkie diody świecą
    		return tmp;
    
    }
    

    Schemat:
    Komunikacja z kartą SD w trybie SPI na ATmega168 w C++ - kod i komendy
    Oczywiście do zasilania podłączone są również pin 20 i 22.
    Pozdr.
  • Pomocny post
    #4 9767063
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    A rezystory (około 100 Ω) w szereg z LED to gdzie... ?
    Jakiej karty właściwie używasz ?
  • REKLAMA
  • #5 9767194
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    :arrow: Light-I
    W pierwszym poście jest napisane:
    Kartę mam 512MB mikroSD z telefonu Nokia, włożoną do adapteru który jest podłączony do płytki stykowej.
    Chyba, ze potrzebne są jakieś inne informacje :?: Ale z tego co pamiętam(piszę z pracy) to na obudowie był tylko jakiś długi numer, nic po za tym.
    Rezystory do diod podłączę, jeżeli miałoby to coś zmienić.

    Znalazłem podobny temat i autor tez ma problem z kartą od telefonu nokia.
    AVR - karta MMC NOKIA - nie obsługuje SPI?
    Będę musiał sprawdzić na innej karcie.
    Ale swoją drogą uwagi, co do programu lub schematu chętnie poczytam.

    Pozdr.
  • #6 9780009
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Witam,
    sprawdziłem program na 2 innych kartach 32MB oraz 1GB i żadna nie działa :cry: Dodatkowo linie DI, DO podłączyłem przez rezystory 56k do plusa zasilania. Również wstawiłem kondensator 100uF na zasilaniu. Sprawdzam program na wszystkie sposoby i nadal nic :cry:
    Pozdr.
  • Pomocny post
    #7 9785527
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    1. Daj te rezystory, o których pisałem - narażasz się na resetowanie poprzez zanik napięcia w momencie zaświecenia LED, nie mówiąc o możliwości przeciążenia portu - sprawdzałeś jaki prąd jest pobierany ? ...
    2. Sprawdź ustawienia BOD w fusebitach.
    3. Po stronie 3,3 V za stabilizatorem daj chociaż 47 µF. Przy karcie pamięci bezpośrednio też dodaj 100nF. to się nazywa filtrowanie szpilek obciążeniowych w zasilaniu.
    4. Nie zadawałem pytania "skąd masz tą kartę", tylko jaka ona jest - w domyśle - jakie ma oznaczenia producenta...
  • #8 9809013
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Witam,
    Rezystory i kondensatory podłączyłem. Efektu brak, więc wziąłem się za fusebity.
    BOD = BODLEVEL ??? Jeśli tak, to jaka wartość powinna być ustawiona ? 1,8V 2,7V 4,3V ?
    Pytam, bo nie znam się na tych fusebitach i nie chciałbym uwalić uC.
    Karta SD to np. Panasonic 16MB i dalsze oznaczenia: D020 BP4LA260803 RP-SD016B MADE IN JAPAN.
    Pozdrawiam.
  • REKLAMA
  • Pomocny post
    #9 9830065
    hacker17
    Poziom 17  
    Posty: 304
    Pomógł: 6
    Ocena: 49
    a takie pytanie a nie powinieneś podpiąć pin CS z karty do SS z mikroprocesora ???? Może się mylę ale może będzie to jakaś podpowiedzi :)
  • #10 9830178
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Prawie we wszystkich postach (99.9%) jakie przeczytałem CS było podłączane do osobnego portu sterowanego programowo. Z tego co pamiętam tez łączyłem CS z SS ale nic to nie dało. Spróbuje jeszcze raz podłączyć może teraz zadziała.
    Program już tak okroiłem, ze mam prawie wszystko w main(). I nadal coś jest nie tak :(

    
    #include <avr/io.h>
    #include <util/delay.h>
                            
                            #define pincs          0
                            #define portcs          PORTB
                            
                            #define dir_cs_in         DDRB&=~(1<<pincs);
                            #define dir_cs_out         DDRB= (1<<pincs);
                            
                            #define out_cs_low       portcs &=~(1<<pincs);
                            #define out_cs_hi      portcs |= (1<<pincs);
    
          typedef unsigned char u08;
       
    
    u08 spi_tx_rx(u08 byte)               //wysylanie i odbior przez spi
    {
    SPDR = byte;
    while(!(SPSR & (1<<SPIF)))             //czekaj na zakonczenie transmisji
    return (SPDR);
    }
    
    void finish(void)                  //zakonczenie trasmisji
    {
    dir_cs_out;            //cs wyjscie
    out_cs_hi;            //cs wysoki
    spi_tx_rx(0xff);            //wysli 8 imp zegarowych
    }            
    
    main()
    {
    _delay_ms(3);   
    DDRB |= (1 << PB3) | (1 << PB5)| ( 1 << PB2 ); //MOSI, SCK, SS' jako wyjścia
    SPCR = (( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR1 ) | ( 1 << SPR0 ));  
    
    u08 i, tmp;
    DDRD = 0xff;
    dir_cs_out;   //reset karty             
    out_cs_hi;
    _delay_ms(1);               
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    spi_tx_rx(0xff);
    dir_cs_out;                  
    out_cs_low;       
    //_delay_ms(1);                //cs niski
       spi_tx_rx(0x40);             //wysli komende go idle state 
       spi_tx_rx(0x00);       
       spi_tx_rx(0x00);
       spi_tx_rx(0x00);
       spi_tx_rx(0x00);          
       spi_tx_rx(0x95);      
       
       for(i=0;i<10;i++)             //czekaj na odpowiedź
          {
          tmp=spi_tx_rx(0xff);
          if(tmp==0x01)
             {
             PORTD=tmp;  //JAKIEŚ PRZYPADKOWE KOMBINACJE,  NAJCZĘŚCIEJ 0XFF  tj. wszystkie diody świecą. Na podstawie dokumentacji powinna świecić tylko      jedna 0x01 - typ odpowiedzi R1 z ustawionym najmłodszym bitem !!!
             finish();
             }
         } 
               
          return tmp;
    
    } 
    
  • #11 9836685
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Eh... Znalazłem błąd pisząc kod od nowa. Wszystko przez to, ze do tej pory używając while() podobnie jak for(), if() przy programowaniu software nie używałem średnika. A w programowaniu sprzętowy przy operacjach na bitach okazuje się, ze jest on nie zbędny. Więc
    jest:
    
    u08 spi_tx_rx(u08 byte)               //wysylanie i odbior przez spi
    {
    SPDR = byte;
    while(!(SPSR & (1<<SPIF)))             //czekaj na zakonczenie transmisji
    return (SPDR);
    } 
    


    powinno być:

    
    u08 spi_tx_rx(u08 byte)               //wysylanie i odbior przez spi
    {
    SPDR = byte;
    while(!(SPSR & (1<<SPIF))) ;            //czekaj na zakonczenie transmisji
    return (SPDR);
    } 
  • #12 9857121
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Witam ponownie
    Tak więc po nawiązaniu kontaktu z moją kartą np. poprzez odczytywanie CID, przeszedłem do następnego etapu jakim jest jest implementacja FAT16. Zaczynając oczywiście od szukania info w internecie.
    Więc FAT16 oznacza, iz mamy do dyspozycji 2^16 adresów do adresowania klastrów (jednostek alokacji).
    Jak wiadomo klastry składają się z sektorów których rozmiar najczęściej wynosi 512Bajtów.
    Dysponując kartą 16MB wychodzi (16MB/2^16), ze mój klaster ma rozmiar ok. 245 Bajtów, czyli pół sektora. Gdy założę sobie wielkość klastra=wielkości sektora tj. jeden klaster składa się z jednego sektora (na karcie mamy możliwość ustawienia wielkości sektora) otrzymam (16MB/512B) 31250 klastrów.
    Pytania:
    1. Gdy ustawiam wielkość sektora na karcie SD na 512B "system" sam obliczy ile potrzebuje klastrów ?
    2. Jaka będzie wielkość tych klastrów ? Czy "system" sam przyjmie w tym przypadku 1 klaster=1 sektor, ponieważ ma dość zapasu w tablicy ?
    3. Dlaczego na stronie http://technet.microsoft.com/en-us/library/cc958073.aspx przy volume size 7-16MB przyjęto wielkość klastra = 2KB tj. 4 sektorów ? Skoro jak wspomniałem jest dość miejsca w tablicy aby adresować klaster składający się z jednego sektora ?
    Dziękuję za ewentualne rozwianie wątpliwości :)
  • REKLAMA
  • Pomocny post
    #13 9858302
    maly_elektronik
    Poziom 23  
    Posty: 777
    Pomógł: 35
    Ocena: 5
    System sam ustali ile przypada sektorów na klaster i sam obliczy ile jest klastrów:)
    Ilość klastrów odczytasz z tablicy alokacji FAT saź to ile sektorów przypada na klaster odczytasz z BootSectora:) Tak samo z BootSectora odczytasz ile bajtów przypada na sektor ale przy kartach sd jest to chyba zawsze 512 bo tyle ma sam sektor karty :) odczytasz tam także ilość ReservedSectors oraz adres Root Directry :)
  • #14 9864452
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Powiedzmy ze sformatowałem sobie kartę w winXp i w głównym katalogu \ utworzyłem plik test.txt Przekładam kartę do uC i jak mam go otworzyć (skąd mam wiedzieć w jakim klastrze się on utworzył) i powiedzmy zapisać w nim napis "hallo world", tak żeby ujrzeć ten tekst później w kompie ? Kurcze niby wszystkie podstawowe procedury mi działają, a nie wiem za bardzo jak się za to zabrać. Wiem ze są biblioteki PetitFat ale jak dla mnie są za bardzo skomplikowane. Poza tym myślę sobie ze do otwarcia i zmiany zawartości już wcześniej utworzonego pliku nie potrzeba aż tak rozbudowanej biblioteki-chyba ze się mylę.
    Domyślnie obsługa kart jest mi potrzebna do akwizycji danych z czujnika temperatury.
  • Pomocny post
    #15 9864743
    maly_elektronik
    Poziom 23  
    Posty: 777
    Pomógł: 35
    Ocena: 5
    Mylisz się :) Aby znaleźć plik to już trzeba trzeba trochę kodu (czyli wystarczy petitFatFs) :)
    Ale żeby już zmienić jego zawartość to już sporo zabawy :)
    Należy:
    1. Wyliczyć wielkość danych które chcesz zapisać (pestka)
    2. Zlokalizować plik w RootDirectry (trochę trudniej)
    3. Wyciągnąć interesujące nas informacja o pliku z RootDirectry
    3. Zmienić rozmiar pliku w RootDirectry (bo przecież coś do niego wpisujesz)
    4. Wykorzystać informacje z RootDirectry i odnaleźć plik w tablicy alokacji FAT
    5. Jeśli wartość do zapisania przekracza 1klaster znaleźć nowy pusty klaster w FAT
    5.1 Jeśli nie przekracza czyliczyć nr 1 sektora istniejącego klastra i tam zapisać

    6. Wpisać adres nowej komurki FAT (klastra) do poprzedniej komórki (wówczas ostatniej)
    7. Wyliczyć gdzie znajduje się określona ilość sektorów przypadająca na nowo dodany klaster
    8. Wpisać dane :)
    9. Pamiętać że wszystko musi współgrać z zaimplementowaną obsługą karty SD lub innego nośnika danych :)

    Jeżeli się jeszcze tym nie zajmowałeś skorzystaj z gotowych bibliotek :)
    Wierz mi nie jest to takie proste (chodź bardo trudne też nie) bo sam pisałem taką bibliotekę i wiem ile to zajmuje czasu :)

    Dodano po 50 [sekundy]:

    Acha pamiętaj że nie możesz tworzyć katalogów na karcie w rozwiązaniu opisanym przeze mnie bo wówczas musisz jeszcze dopisać obsługę katalogów co znacznie bardziej skomplikuje Ci życie :)

    Dodano po 2 [minuty]:

    Radze skorzystanie z fat32 jest bardzo podobny tylko bardziej rozbudowany :) a skoro już piszesz bibliotekę to wykorzystasz ja w przyszłości na większych kartach SD :)
    Nawet kartę 128MB (chyba nie ma mniejszych) sformatujesz na fat32 i będzie działać poprawnie :)
  • #16 9873996
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Witam ponownie.
    Poniżej przedstawiam mój kod póki co do odczytu rejestrów CID oraz CSD. Mam taki problem ponieważ według dokumentacji w CID pierwszy bit=1. Czyli czytam sobie wszystkie 16bajtów do tablicy buf[i]; a na PORTD podaję pierwszy tzn.PORTD|=buf[0]; co oznacza, ze powinna mi się zapalić dioda na najmłodszy bicie, a tak nie jest. Pozostałe 7bitów (CRC) również się nie świeci.
    Posiadam kartę firmy SanDisc. W CID ostatni bajt zwany Manufacturer ID MID i dla SanDisc powinien wynosić 0b00000011 (0x03) a u mnie jest 0b10000001 (0x81). Po wyjęciu i wkładaniu karty cały czas otrzymuję te same wartości bajtów, więc to nie są przypadkowe wartości w związku z czym wykluczam przekłamania. Moze ktoś mógłby wskazać mi ewentualny błąd, lub zasugerować w jaki inny sposób można upewnić się, ze komunikacja z kartą jest poprawna.

    Kod: text
    Zaloguj się, aby zobaczyć kod
    [/img]
  • #17 9874245
    elektryk101
    Poziom 23  
    Posty: 524
    Pomógł: 57
    Ocena: 15
    Jeżeli wszystko masz podłączone tak jak na schemacie który wcześniej podałeś, to powinieneś jeszcze podłączyc zasilanie części analogowej procesora(piny 20 i 22). To też jest ważne.
  • Pomocny post
    #18 9874314
    maly_elektronik
    Poziom 23  
    Posty: 777
    Pomógł: 35
    Ocena: 5
    widzę ustawiłeś blocklen na 0x200 (zamiast 0x0200 możesz napisać 0x200 -> wg mnie wygląda przejrzyściej) :)
    Skoro ustawiłeś blok/sektor danych na 512 to jak chcesz je zmieścić do bufora 16B :?:

    Oczywiście jest to możliwe,można odczytać pozostałe 498B w powietrze, ale czy Ty tak robisz :?: Czy po prostu próbujesz upchać 512B do tablicy 16B :?:

    Dodano po 2 [minuty]:

    Pomyłka ty chcesz odczytać CID (powyższe w tym przypadku nie ważne ale zostawiam bo przyda się do czego innego) :)

    Przy odczycie CID dzieją się różne cuda (najlepiej wychodzi to przy transmisji SD bus), masz ustawioną prędkość SPI przy odczycie na 100-400kHz jak podaje nota :?:

    Dodano po 1 [minuty]:

    A sprawdzanie CID i CSD nie jest konieczne do sprawdzenie czy karta działa poprawnie z programem :) Wystarczy sprawdzić czy karta przeszła z trybu IDLE do trybu pracy :) Jeśli tak znaczy że jest gotowa i można działać :D
  • #19 9874410
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Patrząc na moją funkcję GO IDLE STATE:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    wydaje się ze jest dobra ponieważ zapala mi się dioda, tylko wtedy jeżeli jest spełniony warunek if(tmp==0x01). Inne warunki np. if(tmp==0x04) nie powodują zapalenia się diody. Podobnie rzecz się ma z pozostałymi funkcjami :)
    Tylko ten CID mnie zaniepokoił. Sprawdzę tą prędkość, ale z tego co pamiętam to ustawiłem ją na najnizszą SPCR = ( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR0 ) | ( 1 << SPR1 ); Chyba, ze chodzi o jakąś inną prędkość ?
  • Pomocny post
    #20 9874430
    maly_elektronik
    Poziom 23  
    Posty: 777
    Pomógł: 35
    Ocena: 5
    Nie tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    tylko tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #21 9875585
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Poprawiłem zapis SPCR:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Kurcze mam trzy karty i z żadnej nie mogę odczytać rejestru CID czy tez CSD tak aby zgadzał się z dokumentacją :( Będę "walczył" ale jakby komuś z użytkowników przyszedł jakiś pomysł, to z chęcią bym go sprawdził. Bo wydaje mi się, ze mimo wszystko coś jest nie tak. Moze czyta to użytkownik który ma jakieś doświadczenie w czytaniu CID-u i CSD, czy miał podobne problemy ??
  • #22 9899880
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Postanowiłem inaczej przetestować zapis/odczyt. Sformatowałem kartę SD w komputerze. Zainstalowałem WinHexa i widzę bajt po bajcie jak ona wygląda.
    Komunikacja z kartą SD w trybie SPI na ATmega168 w C++ - kod i komendy

    Funkcja do odczytu pojedyńczego bloku wygląda następująco:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Podając w argumencie komendy 0 powinienem odczytać cały pierwszy sektor czyli MBR. Program jednak "zawiesza" się w pętli for(). Tablica buf[i] jest 512 elementowa tupu char. Ma może ktoś pomysł co może być źle ?
  • Pomocny post
    #23 9900151
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Popraw to:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #24 9900170
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    poprzednio było poprostu:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    i tez nie działało :(
  • Pomocny post
    #25 9900267
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    W 8 bitach nie policzysz do 512!
  • #26 9900298
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Upsss ale gamoń ze mnie. Jak tylko wrócę do domku zaraz sprawdzę. Zasugerowałem się tym, ze odczyt CID działał, ale tam przecież jest do odczytania tylko 16 bajtów.
  • #27 9918673
    qutrit
    Poziom 20  
    Posty: 432
    Pomógł: 33
    Ocena: 26
    Więc, małymi kroczki (ze względu przede wszystkim na czas) doszedłem do momentu prawidłowego odczytu/zapisu informacji z/na kartę. Odebrane dane wyświetlane za pomocą diod zgadzają się z tym, co pokazuje WinHex :)
    Teraz przyszedł czas na FAT, Kupiłem sobie książkę w której jest gotowy PetitFAT. Z internetu tez mam sporo artykułów, ale to wszystko (jak dla mnie) jest pobieżnie opisane, nie mogę się w tym połapać. W związku z tym czy ktoś z forumowiczów zna może ciekawe strony, książki, gdzie byłoby to opisane w przejrzysty sposób krok po kroku. Oczywiście w języku c. Byłbym bardzo wdzięczny :) Mógłbym wgrać jakiegoś gotowca i pewnie z waszą pomocą bym go uruchomił:) Ale tez chciałbym co nie co wiedzieć, jak i dlaczego to działa :)

Podsumowanie tematu

✨ W dyskusji poruszono problem nawiązywania komunikacji z kartą SD w trybie SPI przy użyciu mikrokontrolera ATmega168. Użytkownik przedstawił kod oraz komendy do komunikacji, a także napotkał trudności w odczycie rejestrów CID i CSD. W odpowiedziach zasugerowano m.in. dodanie rezystorów w szereg z diodami LED, sprawdzenie ustawień BOD w fusebitach oraz poprawne podłączenie pinów. Użytkownik testował różne karty SD, w tym mikroSD z telefonu Nokia oraz karty Panasonic, jednak napotkał problemy z odczytem danych. Po poprawkach w kodzie i podłączeniach, udało się nawiązać komunikację i odczytać dane, co potwierdzono przez porównanie z danymi w WinHex. Użytkownik planuje implementację systemu plików FAT16 i poszukuje materiałów edukacyjnych na ten temat.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA