Memória SD

Software e Hardware para linha x51

Moderadores: 51, guest2003, Renie, gpenga

Mensagempor fabiorike » 10 Nov 2006 16:00

Enfim comecei a fazer o software aeeeeeeeeeeeeee, mas estou com uma dúvida, como fácil para escolher o bloco para eu ler, no datasheet tem apenas comando para escolher o tamanho de um bloco pelo que eu entendi pode me corrigir se eu estiver errado, estou tentando fazer em assembler, hehe,.
T+
Obrigado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor chipselect » 10 Nov 2006 17:27

o bloco é especificado como uma espécie de "argumento" do comando.

Por exemplo, o comando de leitura de bloco (comando 17) você passa como parâmetro no pacote de dados do comando o número do setor desejado.

Exemplo:
resposta=SD_send_cmd(SD_CMD17,setor << SD_BLOCKSIZE_NBITS, NULL);
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor fabiorike » 13 Nov 2006 08:44

Bom Dia chipselect
Então para eu ler tenho que especificar o bloco ainde eu escrevi a informação?
O comando para escrita é CMD24?
Eu coloquei assim:

Comando (64h,0,05h,01h,02h,0ffh), para enviar o 512h eu separei em tres partes e vou mandar todos na sequencia.

Como eu mudo de setor? e para ler eu coloco o CMD só mudando o valor de CMD, por exemplo para ler uso CMD17(57h,0,05h,01h,02h,0ffh)?
Obrigado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor chipselect » 14 Nov 2006 00:32

Boa noite Fabio

Os comandos de escrita são o 24 e 25. Eu usei o cmd24 com sucesso em cartões SD e MMC.

Supondo que Comando (64h,0,05h,01h,02h,0ffh) seja a sequencia do pacote que vc manda via SPI, vc vai escrever no bloco 327.938 e o checksum com stopbit no final vc setou pra 0xff.

O cartão MMC/SD que eu conheço em modo SPI trabalha com comando-resposta, logo, pra ler um bloco que você acabou de escrever, vai ter que enviar o comando 17 seguido do número do bloco, ou seja, o pacote todo com os dois bits iniciais seguido do comando mais o stopbit e ECC no final. Infelizmente o SD não é igual à SDRAM que você seta páginas.

O que você pode fazer é ler/escrever múltiplos blocos usando o comando 18 ou 25. Nesse caso você vai ter que saber que tipo de cartão é (MMC ou SD) e usar o CMD23 ou ACMD23 conforme o tipo de cartão pra ajustar o número de blocos para a operação seguinte.

Eu costumo ajustar o tamanho do bloco para 512 bytes (comando 16), logo na inicialização do cartão, pra não dar problema.

Ah, já ia esquecendo, é bom ver o código retornado pelo cartão, se o comando foi executado com sucesso ou que tipo de erro deu.
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor fabiorike » 14 Nov 2006 12:21

Boa tarde Chipselect

Desculpa a minha ignorância, mas como vc sabe o numero do bloco que eu estou escrevendo?
Obrigado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor fabiorike » 14 Nov 2006 16:22

Gente alguem ja montou o circuito do site http://www.captain.at/electronics/pic-mmc/ , mas usando o AT89S8253?
Estou aqui tentando, mas a tensão no Sd card não é 3.3V.
Meu Deus me ajudem.
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor fabiorike » 14 Nov 2006 16:39

Boa Tarde Chipselect

Sem querer pedir muito mas vc poderia me passar um exemplo para usar este cartão, pois eu estou brigando com ele faz quase uma semana, hehehe, ou pelo menos me explicar melhor os comandos para mandar, pois o exemplo q eu dei eu deduzir em relação ao exemplo do site do captain.
Obrigado
Bom Feriado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor chipselect » 14 Nov 2006 18:58

Boa noite Fabio

Eu posso tentar te ajudar sim. Escrevi uma lib mas infelizmente não posso te passar o código porque é da empresa onde trabalho... mas posso te passar os passos que você pode seguir.

Eu uso o cartão MMC/SD em modo SPI, somente o básico porque o microcontrolador não tem memória suficiente e SD + FAT-16 fica meio pesado, mas dá pra rodar.

Você já está conseguindo inicializar o cartão corretamente? Em que passo exatamente você está?

Caso já esteja inicializando e configurando corretamente o cartão, e tá precisando ler e escrever nele, então tá mais fácil.

Pra escrever no cartão:

pacote inicial de 6 bytes seguido dos dados a serem "escritos no cartão"
-ativa o CS do cartão
-Primeiro byte é: bit 0 e bit 1, e código do comando, o que dá 0x64
-Segundo, terceiro, quarto e quinto byte: número do bloco a ser escrito (32 bits)
-Sexto byte: ECC e stopbit

Após transmitir os 6 bytes, você deve esperar o cartão "processar" o comando. Você deve ficar lendo o canal SPI até identificar a resposta do cartão, se deu erro ou se está ok.
Em seguinda você envia o byte 0xfe, que indica pro SD que é o início dos dados.
Depois do 0xfe você envia todos os bytes para preencher o bloco, seguido de dois bytes de checksum. O número de bytes a serem escritos deve bater com o tamanho do bloco.
Então você fica lendo o spi de novo até o SD te mandar uma resposta ou dar timeout.

Suponho que a função Comando(....) devolva a resposta do cartão, dá pra vc analisar a resposta pra verificar se os dados foram escritos com sucesso.

A leitura é bem parecida com a escrita.

PS. Não esquece de desligar o CS, pq eu esqueci, eehehehehhe
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor fabiorike » 16 Nov 2006 09:58

Bom Dia ChipSelect

Obrigado pela dicas creio que serão de grande ajuda.
Para inicializar o SD, basta apenas mandar + ou - 80 clocks, o CMD0?
Obrigado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor chipselect » 16 Nov 2006 10:37

Bom dia Fabio

Pra inicializar o cartão, eu faço o seguinte:
- limito o clock da SPI pra pouco mais de 100KHz
- ligo a alimentação do cartão
- ativo o CS, envio 80 ciclos de clock e desativo o CS.
- envio o CMD0
- envio o CMD55, ACMD41 e CMD1 até obter uma resposta positiva
- envio o CMD58 e verifico os parâmetros do cartão (OCR)
- envio o CMD16
- mudo o clock da SPI pro máximo que a cpu aguenta
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor fabiorike » 16 Nov 2006 14:53

Boa Tarde ChipSelect

Vc saberia me dizer se eu consigo testar a comunicação SPI, sem estar comunicado a nada?
Obrigado mais uma vez pelas dicas.
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor fabiorike » 16 Nov 2006 15:49

Boa Tarde ChipSelect
Para verificar os parametros vc mada para o lcd o dado que o cartão responde?
Eu teria tbm que soma 40h para o comando ACMD41?
Obrigado
fabiorike
Bit
 
Mensagens: 46
Registrado em: 16 Out 2006 10:32

Mensagempor chipselect » 16 Nov 2006 18:13

boa tarde Fabio

Veja bem, qualquer comando que você vai mandar pro SD via SPI tem que ter um formato específico, que é uma sequencia estruturada de bytes.

O primeiro byte a ser enviado, mais precisamente o primeiro bit tem que ser sempre zero, sendo o segundo bit sempre igual a um. O lance de "somar 0x40" na verdade a maneira mais didática é você fazer um AND com 0x7F (zera o primeiro bit) e um OR com 0x40 (seta o segundo bit).

Como todos os comandos não tem nenhum acima de 127, os dois primeiros bits são sempre zero para uma variável representando o comando. Então basta o OR com 0x40 (o and se torna "desnecessário"), sendo que o OR nessa situação pode ser substituido pela soma. Vc só tem que ver se é mais rápido executar um OR ou uma soma na sua CPU.

Para verificar os parâmetros recebidos do cartão, eu utilizo uma stream redirecionada para uma porta serial, e leio o valor no PC.

Na verdade eu criei uma espécie de prompt de comando via serial, o formato lembra bastante o do MS-DOS, e eu testo comandos de alto nível (DIR, TYPE, FORMAT, DEL...) em FAT-16.
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor Jorge_Francisco » 16 Nov 2006 21:04

Achei esta biblio para MMC:

Código: Selecionar todos
// Written by Ed Waugh 2004, www.edwaugh.co.uk

// for the original source, and hundreds more examples of PIC C code, see:
// http://www.microchipc.com/sourcecode/#mmc

int mmc_init();
int mmc_response(unsigned char response);
int mmc_read_block(unsigned long block_number);
int mmc_write_block(unsigned long block_number);
int mmc_get_status();


/************************** MMC Init **************************************/
/* Initialises the MMC into SPI mode and sets block size, returns 0 on success */

int mmc_init()
{
int i;

SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);

*0x94 |= 0x40;                          // set CKE = 1 - clock idle low
*0x14 &= 0xEF;                          // set CKP = 0 - data valid on rising edge

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)

for(i=0;i<10;i++)                       // initialise the MMC card into SPI mode by sending clks on
{
        SPI_WRITE(0xFF);
}

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on) tells card to go to spi mode when it receives reset

SPI_WRITE(0x40);                        // send reset command
SPI_WRITE(0x00);                        // all the arguments are 0x00 for the reset command
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95);                        // precalculated checksum as we are still in MMC mode

puts("Sent go to SPI\n\r");

if(mmc_response(0x01)==1) return 1;     // if = 1 then there was a timeout waiting for 0x01 from the mmc

puts("Got response from MMC\n\r");

i = 0;

while((i < 255) && (mmc_response(0x00)==1))     // must keep sending command if response
{
        SPI_WRITE(0x41);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);                // all the arguments are 0x00 for command one
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
        i++;
}
if(i >= 254) return 1;                   // if >= 254 then there was a timeout waiting for 0x00 from the mmc

puts("Got out of idle response from MMC\n\r");

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)

SPI_WRITE(0xFF);                        // extra clocks to allow mmc to finish off what it is doing

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x50);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x02);                // high block length bits - 512 bytes
        SPI_WRITE(0x00);                // low block length bits
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;
OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
puts("Got set block length response from MMC\n\r");
return 0;
}

/************************** MMC Get Status **************************************/
/* Get the status register of the MMC, for debugging purposes */

int mmc_get_status()
{

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x58);                // send mmc command one to bring out of idle state
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);
        SPI_WRITE(0x00);                //
        SPI_WRITE(0x00);                // always zero as mulitples of 512
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
return 0;
}

/************************** MMC Write Block **************************************/

int mmc_write_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;

varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);

puts("Write block\n\r");                // block size has been set in mmc_init()

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x58);                // send mmc write block
        SPI_WRITE(HIGH(varh));
        SPI_WRITE(LOW(varh));
        SPI_WRITE(HIGH(varl));
        SPI_WRITE(0x00);                // always zero as mulitples of 512
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;
puts("Got response to write block\n\r");

SPI_WRITE(0xFE);                        // send data token

for(i=0;i<512;i++)
{

SPI_WRITE(i2c_eeprom_read(HIGH(i),LOW(i)));     // send data

}

SPI_WRITE(0xFF);                        // dummy CRC
SPI_WRITE(0xFF);

if((SPI_READ(0xFF)&0x0F)!=0x05) return 1;

puts("Got data response to write block\n\r");

OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
return 0;
}



/************************** MMC Read Block **************************************/
/**** Reads a 512 Byte block from the MMC and outputs each byte to RS232 ****/

int mmc_read_block(unsigned long block_number)
{
unsigned long i;
unsigned long varh,varl;

varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);

OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)

        SPI_WRITE(0x51);                // send mmc read single block command
        SPI_WRITE(HIGH(varh));      // arguments are address
        SPI_WRITE(LOW(varh));
        SPI_WRITE(HIGH(varl));
        SPI_WRITE(0x00);
        SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF

if((mmc_response(0x00))==1) return 1;   // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)

puts("Got response to read block command\n\r");

if((mmc_response(0xFE))==1) return 1;   // wait for data token

puts("Got data token\n\r");

        for(i=0;i<512;i++)
        {
                putc(SPI_READ(0xFF));               // we should now receive 512 bytes
        }

SPI_READ(0xFF);                 // CRC bytes that are not needed
SPI_READ(0xFF);

OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
SPI_WRITE(0xFF);                // give mmc the clocks it needs to finish off

puts("\n\rEnd of read block\n\r");

return 0;
}

/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout ****/

int mmc_response(unsigned char response)
{
        unsigned long count = 0xFFFF;           // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point

        while(SPI_READ(0xFF) != response && --count > 0);

        if(count==0) return 1;                  // loop was exited due to timeout
        else return 0;                          // loop was exited before timeout
}


[img]
http://www.microchipc.com/sourcecode/images/mmc.gif
[/img]

Para SD card eu não sei.Na verdade estou me interessando pelo assunto agora,não sei nada!!!!
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor jeanfernandes » 17 Nov 2006 13:01

Se queres uma coisa mais mastigada

http://www.roland-riegel.de/sd-reader/
Jean P. Fernandes - Eng. Eletrônico - (83) 2102-2116 - APEL - www.apel.com.br - Campina Grande - PB
jeanfernandes
Word
 
Mensagens: 539
Registrado em: 11 Out 2006 15:36
Localização: Campina Grande - PB

AnteriorPróximo

Voltar para 8051

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x