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

Sprawdzone projekty obsługi SD/MMC z Atmega8535 - błąd WinAVR

Pth 14 Lis 2007 00:51 6885 47
Najlepsze odpowiedzi

Jakie sprawdzone projekty lub biblioteki do obsługi kart SD/MMC na AVR z Atmegą8535 warto użyć zamiast projektu, który wywala WinAVR?

Sprawdzone rozwiązania to przykładowy kod z captain.at oraz biblioteka Rolanda Riegla do SD/MMC z obsługą partycji i FAT16, testowana na ATmega32 z kartą MMC/SD 128 MB [#4480003] Jeśli potrzebujesz tylko surowego dostępu blokami, przykład z captain.at działa jako odczyt/zapis 512 B; jeśli chcesz wygodnie edytować dane z PC, na karcie powinien być FAT16/FAT32, a sektory można przeglądać np. w WinHex [#4480003 #4486343]. W praktyce w tym wątku właśnie te dwie strony były wskazane jako działające i sprawdzone [#4480003]
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA
  • #1 4478841
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Szukałem trochę o obsłudze kart sd/mmc i znalazłem takie coś http://www.avrfreaks.net/index.php?func=viewItem&item_id=701&module=Freaks%20Tools .

    Niestety po otwarciu projektu win avr wywala mi błąd i się zamyka :/

    Znacie jakieś sprawdzone projekty?

    Mam atmegę8535 do tego podłączona przez CS/MISO/MOSI/CLK kartę sd 128mb
  • REKLAMA
  • #2 4480003
    Piotrek_P
    Poziom 18  
    Posty: 253
    Pomógł: 24
    Cześć;

    Też kiedyś szukałem jakiejś biblioteki do obsługi MMC/SD. Znalazłem wtedy taki link:
    http://www.captain.at/electronic-atmega-mmc.php
    Przykładowy program z tej stronki testowałem na ATMega32 + MMC 32MB. Chodzi bez problemu. Oczywiście jest to zapis/odczyt blokami po 512B. Niedawno znalazłem bibliotekę z obsługą partycji i FAT16. To już jest zupełna rewelacja :-). Można bez problemu tworzyć katalogi, pliki, pisać do pliku itd. Sprawdzone na ATMega32 + MMC 128MB, działa jak należy :-). A oto link:
    http://www.roland-riegel.de/sd-reader/index.html

    Pozdrawiam
    Piotrek[/url]
  • #3 4480040
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Super :D Dzięki!

    W sumie mi chodzi o zapisanie obrazu monochromatycznego (lub kilku = animacja) w postaci tablic, powiedzmy 640x480 wypełnionych 1 lub 0.

    Docelowo chciałbym tak zrobić, że wrzucam na kartę z PC plik (pliki) txt z przekonwertowanym obrazem do ASCII i po podłączeniu karty do procka odczytywało by te pliki.

    Jak szybki może być odczyt z karty?


    A czy karty SD też podejdą?
  • #4 4480618
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Pth napisał:

    Jak szybki może być odczyt z karty?


    Z SD można ciągnąć teoretycznie 20Mbit/s.
  • #5 4481171
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Ale mi chodzi o prędkość odczytu pomiędzy procesorem avr a właśnie tą kartą. To aż taką prędkość da się wyciągnąć Przez SPI? Nieźle :D

    Problem jest taki, że tablica 640x480 nie ma szans zmieścić się w marnej pamięci procesora

    A gdzie mieszczą się dane typu const? Wtedy jest przechowywana tylko w pamięci flash czy nadal obciąża ram?? Zastanawiam się, czy udało by się jakimś sposobem upchnąć taką wielką tablicę w procesorze. Choć jakoś średnio widzę możliwość połączenia const i tablicy :D

    Chyba jednak pozostanę przy tym sd/mmc.
  • #6 4481880
    Batmanmen
    Poziom 15  
    Posty: 205
    Pomógł: 9
    Ocena: 4
    jeżeli ma to być obraz 640x480 gdzie kolor jest czarny albo biały to zajmie ci to 38400 bajtów. Spokojnie możesz to walnąć na atmedze128 albo mniejszej. Możesz zrobić tablice która nie trzyma danych w ramie tylko we Flashu. Mowa o AVR.
  • REKLAMA
  • #7 4481902
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Pth napisał:
    Ale mi chodzi o prędkość odczytu pomiędzy procesorem avr a właśnie tą kartą. To aż taką prędkość da się wyciągnąć Przez SPI? Nieźle :D


    Na 20Mbit/s pozwala karta , z AVR możesz pociągnać max 12Mbit/s (przy przetaktowanej Atmedze) :wink:. Dochodzi jednak jeszcze obsługa LCD oraz tych danych odczytanych z SD. Realna prędkość to ~2-3Mbit/s i zależy bardzo od oprogramowania.

    Jak SD to tylko SanDisk :wink: ponieważ u innych producentów w trybie SPI są czasami przekłamania.
  • #8 4481974
    Batmanmen
    Poziom 15  
    Posty: 205
    Pomógł: 9
    Ocena: 4
    Albo jeszcze inaczej. Jeżeli nie chcesz używać SD bo zawahałeś się to użyj eepromów typu 24c512 dostępne w polskich sklepach. 64kB dla Ciebie. O ile interesuje cię mała liczba tych obrazków. I2C za szybko nie będzie chodzić.

    Jeszcze inna opcja to rozszerzenie flasha twojej atmegi. Zdaje się ze atmega8535 ma już możliwość rozszerzenia flashu - uwaga mogę się mylić. Jeżeli tak to M29W320 dostępne w polskich sklepach.
  • #9 4482139
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Cholera... Okazało się (chyba bo pierwszy raz korzystam z avrstudio i samego C), że oile mieści się sam program w mega8535 to o brakuje już ramu (Mowa o programie z http://www.captain.at/electronic-atmega-mmc.php )

    Tak wygląda log z kompilacji w avr studio

    
    Build started 14.11.2007 at 22:25:57
    avr-gcc.exe  -mmcu=atmega8535 -Wall -gdwarf-2     -DF_CPU=16000000UL -O0 -fsigned-char -MD -MP -MT mmc.o -MF dep/mmc.o.d  -c  ../mmc.c
    In file included from ../mmc.c:4:
    c:/winavr-20070525/bin/../avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete.  Use <avr/interrupt.h>."
    avr-gcc.exe -mmcu=atmega8535  mmc.o     -o mmc.elf
    avr-objcopy -O ihex -R .eeprom  mmc.elf mmc.hex
    avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex mmc.elf mmc.eep || exit 0
    c:\WinAVR-20070525\bin\avr-objcopy.exe: there are no sections to be copied!
    
    AVR Memory Usage
    ----------------
    Device: atmega8535
    
    Program:    1750 bytes (21.4% Full)
    (.text + .data + .bootloader)
    
    Data:        644 bytes (125.8% Full)
    (.data + .bss + .noinit)
    
    
    Build succeeded with 1 Warnings...
    
    

    tak z innej beczki to co znaczy ostrzerzenie
    
    #warning "This header file is obsolete.  Use <avr/interrupt.h>."


    A taki piękny układzik sobie skręciłem i nawet gniazd sd mam. W takim razie trzeba będzie się jutro wybrać do sklepu i kupić atmegę32 bo w sumie można je stosować wymiennie.

    Nie, nie chce wyświetlać obrazów na LCD. Obraz będzie wyświetlany laserem na ścianie. Jedyny czas jaki zajmuje procesorowi wyświetlenie pojedynczego punktu to konwersja liczby dziesiętnej na binarną 10-bitową (tylko że to są za każdym razem 3 operacje na liczbach ułamkowych ale przy kwarcu 16MHz to chyba nie problem).

    W sumie można by kręcić procka. podwyższyć napięcie zasilania (mam nadzieję, że jądro procka nie ma wewnętrznej stabilizacji napięcia) no i dać większy kwarc albo podać zewnętrzny zegar.


    Powiedzcie mi jak skonfigurować avrstudio żeby korzystać z zewnętrznego programatora? Bo teraz używam USBaspa i w bascomie śmiga świetnie i korzysta z avrdude. TE same parametry wystarczy wrzucić pewnie do avrstudio, tylko pytanie brzmi, gdzie?!

    Posiedziałem trochę nad tym programem i jak się przekroczy dostępną pamięć to i tak kompiluje program i można go wgrać ale program już nie rusza. Jutro zobaczymy co będzie jak kupię większy procesor.

    PS. MASAKRA... Tyle dziś czas spędziłem programując i ucząc się C dla procesorów, że teraz zamiast kliknąć "Wyślij" aby zapisać tą wiadomośc na forum naciznałem "F7" czyli kompiluj np w avrstudio... HAHAHA :P



    NO. Mam już atmege32 i wszytko pięknie działa na tym procku..

    Nie wiem tylko jak wybrać inny sektor bo wszytko spokow ypełniam sobie te 512 bajtów ale co z cała resztą karty?!
  • #10 4485949
    Tomek-85
    Poziom 14  
    Posty: 86
    Pomógł: 7
    Ocena: 1
    Cześć!
    Po przeanalizowaniu kodu doszedłem do wniosku,
    że kluczową rolę odgrywa tu funkcja Command()
    i parametry funkcji AdrH, AdrL.
    
    char Command(char befF, uint16_t AdrH, uint16_t AdrL, char befH )
    {	// sends a command to the MMC
    	SPI(0xFF);
    	SPI(befF);
    	SPI((uint8_t)(AdrH >> 8));
    	SPI((uint8_t)AdrH);
    	SPI((uint8_t)(AdrL >> 8));
    	SPI((uint8_t)AdrL);
    	SPI(befH);
    	SPI(0xFF);
    	return SPI(0xFF);	// return the last received character
    }
    

    Niestety mogę się mylić dlatego proszę kogoś
    obeznanego w temacie o zweryfikowanie informacji.
    Mam jeszcze jedno drobne pytanie.
    Czy z tych kart trzeba koniecznie czytać/zapisywać informacje
    blokami o długości 512B , czy tą wielkość można sobie
    dowolnie ustawić?
  • #11 4486025
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Pth napisał:
    Nie wiem tylko jak wybrać inny sektor bo wszytko spokow ypełniam sobie te 512 bajtów ale co z cała resztą karty?!


    Poprostu zwiększasz adres o 1 :wink:. Weź pod uwagę że dla karty adres 0 nie oznacza sektora pierwszego, zawsze isnieje offset np: dla kart SanDisk przesuniecie sektora pierwszego to 0x33 tzn. podając adres sektora jako 0x33 mamy fizyczny dostęp do pierwszego sektora na karcie i każdy nastepny adres to następny sektor. Skąd się to bierze....nie wiem :( , w dokumentacji tego nie znalazłem.
    Cytat:

    Czy z tych kart trzeba koniecznie czytać/zapisywać informacje
    blokami o długości 512B


    To jest standardowy blok danych, czytać możesz więcej ale po odczycie 512 bajta musisz wysłać CRC (dla trybu SPI wystarczy 0xFF) natomiast zapisywać tylko blokami po 512B.
  • #12 4486283
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Wielkie dzięki za pomoc :)

    Em... Zwiększ adres o 1 czyli którą zmienną?

    Już prawie wszytko jest tak jak bym chciał, ALE teraz mam WIELGAŚNY problem...

    Teraz zastanawiam się jak tu przenieść dane z komputera na ta kartę nie używając struktury plików.
    Trzeba będzie wysłać jakoś plik (zawartość danego pliku txt który składa się z 0 i 1). Ale nie chce się bawić w obsługę RS'a na kompie w C++...

    Jest jakoś możliwość edycji zawartości karty z poziomu PC tzn wkładam normalnie kartę do czytnika USB na SD i już jakoś grzebię sobie w tej karcie. tylko tu potrzebny est chyba zupełnie nowy sterownik do obsługi karty w ten sposób na kompie :/


    P.S. W sumie używam karty jakiejś "PRAKTIKA" 128MB i śmiga super (póki co :D).
  • #13 4486343
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Poprostu podajesz numer sektora (blok 512B) jaki chcesz odczytać.

    adr= sector+OFFSET_ADR;
       adr<<=9;//mnożenie *512 bajtów
       repeat=0;
       
       res = sd_command(READ_SINGLE_BLOCK,adr);


    Cytat:
    Jest jakoś możliwość edycji zawartości karty z poziomu PC tzn wkładam normalnie kartę do czytnika USB na SD i już jakoś grzebię sobie w tej karcie


    Dokładnie, i do edycji używasz programu WINHEX. WARUNEK!!! Na karcie MUSi byc postawiony system plików np: FAT16 lub FAT32.
    Karta zgłasza się w czytniku jako zewnętrzna pamięć. W programie masz podgląd na poszczególne sektory, musisz sobie ustalić tylko ten offset :wink:. System plików pomoże Ci w obsłudze karty z poziomu PC natomiast z poziomu AVR musisz tylko wiedzeić jaki jest numer sektora z interesującymi Cię danymi. Wystarczy że trochę sie pobawisz i okaże się to bardzo łatwe do zrobienia :wink:
  • #14 4486382
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Niestety dalej mi to nic nie mówi z tym adresem :/

    
    char SPI(char d) {  // send character over SPI
    	char received = 0;
    	SPDR = d;
    	while(!(SPSR & (1<<SPIF)));
    	received = SPDR;
    	return (received);
    }
    
    
    char Command(char befF, uint16_t AdrH, uint16_t AdrL, char befH )
    {	// sends a command to the MMC
    	SPI(0xFF);
    	SPI(befF);
    	SPI((uint8_t)(AdrH >> 8 + adresik));
    	SPI((uint8_t)AdrH);
    	SPI((uint8_t)(AdrL >> 8 + adresik));
    	SPI((uint8_t)AdrL);
    	SPI(befH);
    	SPI(0xFF);
    	return SPI(0xFF);	// return the last received character
    }
    
    int MMC_Init(void) { // init SPI
    	char i;
    	PORTB |= (1 << SPICS); // disable MMC
    	// start MMC in SPI mode
    	for(i=0; i < 10; i++) SPI(0xFF); // send 10*8=80 clock pulses
    	PORTB &= ~(1 << SPICS); // enable MMC
    
    	if (Command(0x40,0,0,0x95) != 1) goto mmcerror; // reset MMC
    
    st: // if there is no MMC, prg. loops here
    	if (Command(0x41,0,0,0xFF) !=0) goto st;
    	return 1;
    mmcerror:
    	return 0;
    }
    
    int writemmc(int address) { // write sector to MMC
    	int i;
    
    		DDRB |= (1<<redled);
    	uint8_t c;
    	// 512 byte-write-mode
    
    	if (Command(0x58,0,512,0xFF) !=0) {
    		//uart_puts("MMC: write error 1 ");
    		
    		PORTB |= (1<<redled);
    		return 1;	
    	}
    
    	else {
    		PORTB &= ~(1<<redled);
    	}
    	SPI(0xFF);
    	SPI(0xFF);
    	SPI(0xFE);
    	// write ram sectors to MMC
    	for (i=0;i<512;i++) {
    		SPI(sector[i]);
    	}
    	// at the end, send 2 dummy bytes
    	SPI(0xFF);
    	SPI(0xFF);
    
    	c = SPI(0xFF);
    	c &= 0x1F; 	// 0x1F = 0b.0001.1111;
    	if (c != 0x05) { // 0x05 = 0b.0000.0101
    		//uart_puts("MMC: write error 1 ");
    		
    		PORTB |= (1<<redled);
    		return 1;	
    	}
    	else {
    		PORTB &= ~(1<<redled);
    	}
    	// wait until MMC is not busy anymore
    	while(SPI(0xFF) != (char)0xFF);
    	return 0;
    }
    
    int sendmmc(int address) { // send 512 bytes from the MMC via the serial port
    	int i;
    		DDRB |= (1<<yellowled);
    	// 512 byte-read-mode 
    	if (Command(0x51,0,512,0xFF) != 0) {
    		//uart_puts("MMC: read error 1 ");
    		
    		PORTB |= (1<<yellowled);
    		return 1;	
    	}
    	else {
    		PORTB &= ~(1<<yellowled);
    	}
    	// wait for 0xFE - start of any transmission
    	// ATT: typecast (char)0xFE is a must!
    	while(SPI(0xFF) != (char)0xFE);
    
    	for(i=0; i < 512; i++) {
    		while(!(UCSRA & (1 << UDRE))); // wait for serial port
    		UDR = SPI(0xFF);  // send character
    	}
    	serialterminate();
    	// at the end, send 2 dummy bytes
    	SPI(0xFF); // actually this returns the CRC/checksum byte
    	SPI(0xFF);
    	return 0;
    }
    
  • REKLAMA
  • #15 4486396
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Tutaj podajesz adres (zmienna addres) int writemmc(int address )

    a u Ciebie jest stały i wynoasi 0x200. (czyli 512).

    int writemmc(int address) { // write sector to MMC 
       int i; 
    
          DDRB |= (1<<redled); 
       uint8_t c; 
       // 512 byte-write-mode 
    
       if (Command(0x58,0,512,0xFF) !=0) {  //tu jest stała wartość a powinno być scęść MSB adresu i częśc LSB adresu
          //uart_puts("MMC: write error 1 "); 
           
          PORTB |= (1<<redled); 
          return 1;    
       }
  • #16 4486406
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Tylko że to "int address" wpisałem sam żeby właśnie wykorzystać w tym celu :]
  • #17 4486411
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Pth napisał:
    Tylko że to "int address" wpisałem sam żeby właśnie wykorzystać w tym celu :]


    Więc zamiast stałej wartości wpisz tą zmienną (narazie te górne 16bitów adresu mozna zrobić 0).

    
    if (Command(0x58,0,address,0xFF) 
  • #18 4486424
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    w sumie jest takie coś i śmiga świetnie. Zapis jest dość wolny no ale niech będzie na razie.


    
    int writemmc(int address) { // write sector to MMC
    	int i;
    	int address1;
    	address1 = address*512;
    		DDRB |= (1<<redled);
    	uint8_t c;
    	// 512 byte-write-mode
    
    	if (Command(0x58,0,address1,0xFF) !=0) {
    		//uart_puts("MMC: write error 1 ");
    		
    		PORTB |= (1<<redled);
    		return 1;	
    	}
    
    	else {
    		PORTB &= ~(1<<redled);
    	}
    	SPI(0xFF);
    	SPI(0xFF);
    	SPI(0xFE);
    	// write ram sectors to MMC
    	for (i=0;i<512;i++) {
    		SPI(sector[i]);
    	}
    	// at the end, send 2 dummy bytes
    	SPI(0xFF);
    	SPI(0xFF);
    
    	c = SPI(0xFF);
    	c &= 0x1F; 	// 0x1F = 0b.0001.1111;
    	if (c != 0x05) { // 0x05 = 0b.0000.0101
    		//uart_puts("MMC: write error 1 ");
    		
    		PORTB |= (1<<redled);
    		return 1;	
    	}
    	else {
    		PORTB &= ~(1<<redled);
    	}
    	// wait until MMC is not busy anymore
    	while(SPI(0xFF) != (char)0xFF);
    	return 0;
    }
    
    int sendmmc(int address) { // send 512 bytes from the MMC via the serial port
    	int i;
    	int address1;
    	address1 = address*512;
    		DDRB |= (1<<yellowled);
    	// 512 byte-read-mode 
    	if (Command(0x51,0,address1,0xFF) != 0) {
    		//uart_puts("MMC: read error 1 ");
    		
    		PORTB |= (1<<yellowled);
    		return 1;	
    	}
    	else {
    		PORTB &= ~(1<<yellowled);
    	}
    	// wait for 0xFE - start of any transmission
    	// ATT: typecast (char)0xFE is a must!
    	while(SPI(0xFF) != (char)0xFE);
    
    	for(i=0; i < 512; i++) {
    		while(!(UCSRA & (1 << UDRE))); // wait for serial port
    		UDR = SPI(0xFF);  // send character
    	}
    	serialterminate();
    	// at the end, send 2 dummy bytes
    	SPI(0xFF); // actually this returns the CRC/checksum byte
    	SPI(0xFF);
    	return 0;
    }
    



    K... jednak nie działa... już nie mm do tego siły...
    ...dzisiaj

    Wrócę do tego jak wrócę z uczelni...
  • #19 4486805
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    address1 = address*512;


    To jest zupełnie niepotrzebne, sektor to 512B, więc adres 0x01 to pierwsze 512B, adres 0x02 to następne 512B itd.
  • #20 4487866
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    No i jestem już w domu... Weekend się zaczął więc kontynuuję zabawę z mmc :)

    Tylko jakoś nei mogę ogarnąć odczytu zawartości karty w winhex. Gdzie tam się zaczynają te sektory?
  • #21 4487907
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Cytat:
    Gdzie tam się zaczynają te sektory?


    No to nie są te same sektory które odczytujesz w AVR. WINHEX ładnie "stronicuje" dane po 512B, natomiast wyświetla adres kolejnych 16bajtów.
    Musisz poprostu wyszukać gdzie fizycznie znajduje się Twój zapisany sektor (nie sugeruj się czasem numerami klastrów z systemu plików :wink: ). Pod adresem 0 w WINHEX znajduje się Twój pierwszy sektor na karcie (i wcale nie jest to sektor o adr = 0x00 widziany z AVR, pisałem o tym wyżej).
  • #22 4488261
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Teraz to już nic nie rozumiem.

    Mamy :

    
    int writemmc(int adr1) { // write RAM sector to MMC
    	int i;
    	uint8_t c;
    	// 512 byte-write-mode
    	if (Command(0x58,0,adr1,0xFF) !=0) {
    		uart_puts("MMC: write error 1 ");
    		return 1;	
    	}
    	SPI(0xFF);
    	SPI(0xFF);
    	SPI(0xFE);
    	// write ram sectors to MMC
    	for (i=0;i<512;i++) {
    		SPI(sector[i]);
    	}
    	// at the end, send 2 dummy bytes
    	SPI(0xFF);
    	SPI(0xFF);
    
    	c = SPI(0xFF);
    	c &= 0x1F; 	// 0x1F = 0b.0001.1111;
    	if (c != 0x05) { // 0x05 = 0b.0000.0101
    		uart_puts("MMC: write error 2 ");
    		return 1;
    	}
    	// wait until MMC is not busy anymore
    	while(SPI(0xFF) != (char)0xFF);
    	return 0;
    }
    


    Podczas zapisu przy adresie (adr1) równym >2 już zwraca mi MMC: write error 1. Czemu tak jest? Co znowu jest źle?!

    No chyba wreszcie doszedłem do tego...

    Adresy sektorów idą tak (i tak też są zapisane na karcie bo znalazłem te sektory w winhex):

    według offsetu dziesiętnego:
    sektor 1 : 0-512
    sektor 1 : 513-1024
    sektor 1 : 1025-1563 itd...

    według offsetu szesnastkowego :
    sektor 1 : 200
    sektor 1 : 400
    sektor 1 : 600 itd...

    // -----------------------------------------------------------------

    Hm... Chyba mamy problem... Wgrałem obraz a właściwie ciąg znaków 01 i znaków nowa linia rozpoczynając od 200 sektora

    wszytko spoko, procesor odczytuje mi sektory i przesyła mi z powrotem te sektory z zapisanym obrazem na kompa.


    Ale teraz nie mogę uzyskać dostępu do karty z kompa :/
    // -----------------------------------------------------------------

    Nie dało się jej w niczym otworzyć w końcu sformatowałem ją w aparacie cyfrowym. Teraz działa tak jak powinna. Ale nadal mnie zastanawia dlaczego się zablokowała.





    Mam takie pytanko. Czy jest jakoś możliwość dostania się do dalekich sektorów powiedzmy np w sektorze 001004544(dec) ?

    Istnieje taka możliwość, żeby zapisywało pliki jakoś w miarę w początkowych sektorach zapisując pliki normalnie w windowsie na dysku wymiennym?

    Dzięki temu, że wrzucam pliki bezpośrednio, nie muszę korzystać, z edytorów hexametryczny tylko od razu mam dane na SD.

    Chciałem zrobić tak, że procek przeszukuje mi całą kartę w poszukiwaniu danego stringa (znajdujacego się w pliku, tak aby automatyznie znaleźć plik).


    Dziwne. Pierwsze sektory karty są na pewno puste bo sprawdzałem w edytorze 16tkowym i wsyztko jest puste a jednak kiedy odczytuje np 10 pierwszych sektorów otrzymuję zawartość pliku.txt). Najciekawsze jest to, że zwraca mi starą zawartość pliku bo teraz jest zmieniona o dodatkową linijkę na początku pliku tak aby było go łatwo znaleźć na karcie. Co jest?!
  • REKLAMA
  • #23 4490579
    Tomek-85
    Poziom 14  
    Posty: 86
    Pomógł: 7
    Ocena: 1
    Cytat:

    Mam takie pytanko. Czy jest jakoś możliwość dostania się do dalekich sektorów powiedzmy np w sektorze 001004544(dec) ?


    A dlaczego nie?
    Adresowanie jest podzielone na
    dwie liczby 16bitowe. Czyli po przekroczeniu liczby 65535 (0xFFFF)
    (największa liczba którą można zapisać na 16 bitach)
    zmiennej AdrL czyli również przekroczenie 127 bloku 512 bajtowego
    [ (65535 / 512) = 127 ] trzeba będzie zacząć używać starszej części
    adresu czyli zmiennej AdrH.

    PS: Nigdy nie obsługiwałem kart MMC/SD na Atmedze
    (ale mam zamiar pobawić się tymi kartami)
    wnioski są jedynie wyciągnięte z analizy kodu źródłowego.
  • #24 4490617
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Cytat:
    Ale nadal mnie zastanawia dlaczego się zablokowała


    Bo omyłkowo zapisałes coś w sekcji BootSektor karty i system nie mógł jej rozpoznać.
    Cytat:

    Pierwsze sektory karty są na pewno puste bo sprawdzałem w edytorze 16tkowym i wsyztko jest puste a jednak kiedy odczytuje np 10 pierwszych sektorów otrzymuję zawartość pliku.txt
    ).

    Ale napisałem wyżej że sektor o adresie 0x00 jaki odczytujesz przez Atmegę to nie ten sam sektor odczytywany w PC, jest przesunięcie które musisz znaleźć. Poprostu odczytuj dane od adresu 0x00 aż napotkasz BootSector karty i wtedy to będzie pierwszy zapisywalny przez Atmegę sektor na karcie.
  • #25 4490649
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Wielkie dzięki już kolejny raz :D
    CO ja bym bez Was zrobił :)

    A teraz takie pytanie trochę odbiegajace od samego SD.

    Jak stworzyć w C tablicę o wielkich rozmiar ale bardzo małych elementach w tablicy?

    Na początek chciałem zrobić bardzo duża tablicę tylko o elementach 0,1,2. Po to, żeby załadować do niej wszystkie sektory w których znajduje się obraz do załadowania. 0-biały, 1 - czarny, 2-nowa linia obrazu.

    Problemem może tu być stworzenie własnego typu tak aby było możliwość dokładnie 3 stanów.
  • #26 4490754
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Jezeli masz trzy stany do zapamietania to potrzebujesz dwóch bitów
    0 i 0 to biały;
    0 i 1 to czarny;
    1 i 1 to nowa linia;

    i definiujesz nowy typ

    typdef struct {
           unsigned char 2: _1;
           unsigned char 2: _2;
           unsigned char 2: _3;
           unsigned char 2: _4;
                        }dana;


    i tworzysz tablicę

    dana tab_dana[10];


    W jednym bajcie masz zapamietane cztery dane.
    Do poszczególnych elementów odwołujesz się np: tak

    if(tab_dana[0]._1 == 0x00){...biale
    if(tab_dana[0]._1 == 0x01){...czarne
    if(tab_dana[0]._1 == 0x03){...nowalinia


    Tylko nie wiem czy o to chodziło :wink:
  • #27 4490763
    Tomek-85
    Poziom 14  
    Posty: 86
    Pomógł: 7
    Ocena: 1
    Nie wiem dlaczego chcesz używać do tej operacji Tablicy?
    Ja bym zrobił to zdecydowanie inaczej !
    1.Odczytuj bloki 512 bajtowe z karty.
    (4096 bitów które decydują czy piksel jest
    zapalony czy nie)
    2.Wymaluj odpowiednią liczbę (bajtów)
    w pętli for (określona liczba kolumn "x")
    3.Po wymalowaniu określonej liczby bitów
    przeskocz do następnego wiersza.
    Też w pętli for (określona liczba wierszy "y")

    gdzie x,y to wymiary twojego obrazka (ekranu).
    Po wykonaniu dwóch pętelek zerujesz
    ich zmienne i odczytujesz kolejny blok
    z karty. I procedurę zaczynasz od nowa.

    Aha do odczytywania kolejnych bitów z bajtu
    możesz użyć takiego kodu:
    
    void Bajty_z_MMC(int weBit)    
    {
    char licz;
     for(licz=0;licz < 8;licz++)
     {
     //Sprawdzenie czy bit najstarszy (MSB) jest jedynką?
      if((weBit & 0x80)==0x80) 
        {
             // tak (zapalenie pixela)
        }
       else 
           { 
              //  nie  (wygaszenie pixela )
            } 
      weBit= weBit << 1;  	//logiczne przesunięcie bitów w lewo
     } 
    }
    

    Pozdrawiam.
  • #28 4490891
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    No tak ale niekoniecznie procesor może zdążyć z odbieraniem danych z karty SD i ustawianiem przetwornika DAC. Dlatego wole od razu załadować cały obraz do pamięci RAM.

    Pliki które wrzucam na kartę zawsze znajdują się w sektorze 1962 (dec 1004544 i hex F5400).


    Nie no teraz to już kompletnie nie rozumiem... odczytuje w procku z karty segment 0 i sektor 512. Wysyłam przez rs'a i zwraca mi zawartość pliku. skopiowałem kawałek tego co mi przesłało przez rs'a i wrzuciłem do wyszukiwarki w w hex edytorze dla napędów. i nie znaduje tego NIGDZIE. Jak to możliwe?!
  • #29 4491136
    Tomek-85
    Poziom 14  
    Posty: 86
    Pomógł: 7
    Ocena: 1
    Pth napisał:

    No tak ale niekoniecznie procesor może zdążyć z odbieraniem danych z karty SD i ustawianiem przetwornika DAC. Dlatego wole od razu załadować cały obraz do pamięci RAM.

    Czytasz uważnie?
    Batmanmen napisał:
    Cytat:

    jeżeli ma to być obraz 640x480 gdzie kolor jest czarny albo biały
    to zajmie ci to 38400 bajtów.

    Dla przypomnienia Atmega32 ma 2K sramu. O załadowaniu
    całego obrazu możesz zapomnieć! Ładowanie obrazu
    będziesz musiał robić fragmentami. I pamiętaj, że nie możesz
    zająć całej przestrzeni 2K, ponieważ stos też musi czymś "oddychać".

    Napisz z jakimi parametrami wywołujesz funkcje writemmc().
  • #30 4491215
    Pth
    Poziom 26  
    Posty: 1080
    Pomógł: 9
    Ocena: 39
    Właściwe to send a nie write bo zapisuje na karcie tylko w kompie a procesor tylko odczytuje.



    powiedzmy, że wywołuję funkcje z parametrami :

    sendmmc(0,0); czyli sektor zaczynajacy się w 512 i segmencie 0.
    
    int sendmmc(int segment, int sect3) { // send 512 bytes from the MMC via the serial port
    	int i;
    	int sect4;
    
    	sect4 = 512 * (sect3+1);
    
    	// 512 byte-read-mode 
    /*	if (Command(0x51,0,512-adr2,0xFF) != 0) {
    		uart_puts("MMC: read error 1 ");
    		return 1;
    	}*/
    	// wait for 0xFE - start of any transmission
    	// ATT: typecast (char)0xFE is a must!
    	Command(0x51,segment,sect4,0xFF);
    	
    	while(SPI(0xFF) != (char)0xFE);
    
    	for(i=0; i < 512; i++) {
    		while(!(UCSRA & (1 << UDRE))); // wait for serial port
    		UDR = SPI(0xFF);  // send character
    	}
    	serialterminate();
    	// at the end, send 2 dummy bytes
    	SPI(0xFF); // actually this returns the CRC/checksum byte
    	SPI(0xFF);
    	return 0;
    }
    

Podsumowanie tematu

✨ Dyskusja dotyczy problemów i rozwiązań związanych z obsługą kart SD/MMC za pomocą mikrokontrolera Atmega8535 oraz środowiska WinAVR. Użytkownicy omawiają sprawdzone biblioteki i projekty do komunikacji z kartami SD/MMC, m.in. z wykorzystaniem SPI, oraz kwestie prędkości transferu danych, która w praktyce wynosi około 2-3 Mbit/s przy przetaktowanej Atmedze. Poruszono temat adresowania sektorów na karcie, gdzie sektor ma rozmiar 512 bajtów, a adresowanie wymaga uwzględnienia starszej i młodszej części 16-bitowej zmiennej, co jest istotne przy przekraczaniu 127 sektora. Wskazano, że pierwszy sektor widziany przez mikrokontroler może być przesunięty względem sektora widzianego przez komputer, co wymaga znalezienia offsetu, np. poprzez analizę BootSector. Omówiono także kwestie zapisu i odczytu danych blokami 512 bajtów oraz konieczność stosowania systemu plików (np. FAT16/FAT32) dla wygodnej edycji danych z poziomu PC. Wskazano, że karty SD należy zasilać napięciem 3.3V. Poruszono problem ograniczonej pamięci RAM mikrokontrolera i sposoby efektywnego przechowywania dużych tablic bitowych, np. poprzez definiowanie struktur bitowych. Wskazano również metody przesyłania danych z karty do mikrokontrolera i ich wyświetlania, a także sposoby wykrywania obecności karty w czytniku, np. za pomocą mikroprzełącznika. Dyskusja zawiera przykładowe fragmenty kodu funkcji SPI, Command, writemmc oraz sendmmc, ilustrujące implementację komunikacji i adresowania sektorów. Poruszono także kwestie bezpieczeństwa wyjmowania karty oraz zarządzania plikami i sektorami na karcie SD.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA