Ir ao conteúdo
  • Cadastre-se

mikroc for pic e mmc_fat_read (ler sdcard)


Posts recomendados

Boa tarde a todos

 

Utilizo o MikroC já a algum tempo, mas nunca necessitei realizar a leitura de arquivos no SDCard, então me deparei com um problema bem estranho.

 

Vou colar abaixo um trexo de código:

 

Citação

 


Mmc_Fat_Assign("main.cnf", 0xA0);

       size=Mmc_Fat_Get_File_Size(); //Obtem tamanho do arquivo
       Mmc_Fat_Reset(&size);


       y=1;
       for ( y=1 ; y<=size ; y++)
       {
         Mmc_Fat_Read(&DADO);
         DADOCARREGADO = &DADO;

         LCD_Init();
        LCD_Cmd(_LCD_CURSOR_OFF);
        LCD_Cmd(_LCD_CLEAR);
        Lcd_Out(1, 1, "TESTE:");
        Lcd_Out(1, 7, &DADO);

        Lcd_Out(2, 1, *DADOCARREGADO)
 

 

 

 

O que acontece:

Fiz a inicialização do cartão SD, e abri o arquivo "main.cnf".

Preciso descarregar o conteúdo do arquivo em uma variável interna para avaliar ele, e carregar as configurações de meu dispositivo.

 

O problema, é que aparentemente a função mmc_fat_read apenas relaciona o endereço em memória onde está o dado, e não o dado em si.

O problema é que mesmo trabalhando com ponteiros, não consigo descarregar o dado diretamente em uma variável.

 

No exemplo, tenho uma sequência de comandos para escrever em um display LCD. Se envio para o displau &DADO (o endereço onde está o dado, de acordo com as regras de programação C), tenho na tela os caracteres que estão no arquivo, corretamente.

Porém, DADOCARREGADO recebe &DADO, e este é um ponteiro. Teoricamente, enviar *DADOCARREGADO para o LCD deveria ter o mesmo efeito, só que não tem.

Também não consigo descarregar &DADO diretamente em uma VAR CHAR qualquer. DADO (sem o &) é nulo.

 

Estou a dias tentando achar uma solução para isto, e não saio do lugar. Alguma ideia de como posso fazer para descarregar o caractere recuperado pela função mmc_fat_read diretamente em uma variável do tipo CHAR, para que eu possa manipulá-la posteriormente?

 

 

 

Obrigado por qualquer ajuda.

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

vetores, ponteiros e afins até hoje me causam horror. 

Penso que 1º você deve se autorresponder:

-que tipo de dado pode ser alimentado no argumento de lcdout()? Que tipo ela espera? E que tipo você quer que apareça no display? Como você espera que apareça? No seu fonte você coloca 3 tipos diferentes. Não chute. Consulte o help do seu compilador

-a rotina Mmc_Fat_Read() retorna algum dado? Que tipo ele é? De repente é dado "de verdade" (tipo char) e não apenas algum horripilante indexador ponteiro ou vetor .. iéca..! Consulte o help do seu compilador de novo

Aliás, sabe a diferença entre ponteiro e vetor? nem eu e acho que nem quero saber kk

 

Depois de obter as respostas, vai ser fácil você fazer as compatibilizações.

 

em tempo...

1 hora atrás, Josias_Martins disse:

nunca necessitei realizar a leitura de arquivos no SDCard

tamo junto... Foram só chutes...

abç

Link para o comentário
Compartilhar em outros sites

Pois então.

Consegui ir um pouco adiante. Consegui descarregar o dado de endereço para um ponteiro.

A função MMC_FAT_READ retorna o endereço onde está o dado, pelo que entendi. A documentação da MikroE é muito ruim neste sentido, não explica absolutamente nada...
 




Pag. 376 do PDF: http://download.mikroe.com/documents/compilers/mikroc/dspic/mikroc-dspic-manual-v100.pdf

 


Sabendo que & retorna o endereço, e sabendo que a função incrementa o endereço onde está o caractere cada vez que é chamada, creio que a variável &DADO contém apenas o endereço, e o DADO que quero propriamente dito.

Sabendo isso, posso criar um ponteiro compatível e descarregar o endereço nele, que este irá apontar para o dado:


unsigned short *DATALOAD;

DATALOAD = &DADO;

 

No exemplo acima, descarrego o endereço em memória onde está o dado no ponteiro, e este passa a apontar para o dado que eu quero.

O problema, é que eu não consigo simplesmente descarregar o dado em uma variável unsigned short:


Em todo lugar que vejo sobre C/C++ é afirmado que isto funciona, mas no MikroC parece que não vai.

 

PS: Se enviar DATALOAD para o LCD, tenho os caracteres que necessito. O problema é que não consigo trabalhar em sentenças diretamente com DATALOAD, somente marcando este como ponteiro, que acaba trazendo a localização do ponteiro, e não o valor.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Prestenção pow! Realmente na página 376 não explica nada sobre sua inquietação. pagina 421 por gentileza.

Mmc_Fat_Read
Prototype void Mmc_Fat_Read(unsigned short *bdata);
Description Reads a byte from the currently assigned fle opened for reading. Upon function execution fle pointers 
will be set to the next character in the fle.
Parameters - bdata: buffer to store read byte to. Upon this function execution read byte is returned through this 
parameter. 
Returns Nothing.
Requires MMC/SD card and MMC library must be initialized for fle operations. See Mmc_Fat_Init.
The fle must be previously assigned. See Mmc_Fat_Assign.
The fle must be opened for reading. See Mmc_Fat_Reset.
Example char character;
...
Mmc_Fat_Read(&character);

Penso que 'character' já é o dado propriamente dito que você quer. Neste caso você pode criar um função que retorna o byte

 

char meu_Mmc_Fat_Read()
{
char character;
Mmc_Fat_Read(&character);
return character;
}

Penso que na próxima execução 'character'  vai ser o próximo byte. Crie seu loop e vá montando a palavra

 

Não me importo (muito) caso tenha escrito alguma coisa errada ok? Por gentileza, corrija-me se necessário.

 

Ainda falta você definir como quer que o dado seja apresentado no display. Mas isso não quero te tirar o prazer de descobrir por si.
 

Link para o comentário
Compartilhar em outros sites

Perdão, mandei a versão 100 do manual, e tenho aqui em meu PC a versão 101. A página 376 da Versão 101 possui o mesmo conteúdo da versão da 421 deste manual que coloquei ai no post.

 

Testei a função, mas infelizmente continua sem funcionar. Ele não retorna o byte lido no cartão SD, ele retorna qualquer outra coisa, menos o esperado.

 

Somente consigo obter o valor no caso apresentado no post inicial:

1 - Se "character" for declarado como "unsigned short *character

2 - Se descarregar o endereço do ponteiro character para outro ponteiro "SDDATA = &character"
3 - Neste caso, SDDATA aponta para o valor lido, e consigo mandar-lo para o lcd diretamente com o comando LCD_Out(1, 1, SDDATA);

O problema é que não consigo descarregar o dado para o qual o ponteiro aponta em outra variável. 

Se declarar "character" como variável char comum (não ponteiro para um valor char, como exemplificado em 1), não funciona, simplesmente enlouquece e começa a trazer valores aleatórios armazenados na ROM do Microcontrolador.

 

Não faz sentido. Pois pelo que entendo, é passado para a função MMC_FAT_READ o endereço da variável, para que ele descarregue a informação diretamente nela (provavelmente a variável declarada como input da função seja um ponteiro para o endereço passado por &character). Teoricamente deveria funcionar normalmente, e "character" deveria retornar o byte lido. Mas não está retornando.

 

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

ok mas como você sabe que o dado não é o do arquivo? onde, como você está vendo ele? penso que talvez seja alguma questão de formatação que não estamos conseguindo visualizar. Aguarde algum expert em ponteiros-vetores e cia.

 

Alternativamente, você pode considerar reduzir o nível de otimização do compilador ou , se não obtiver sucesso de forma alguma, considerar que ele pode possuir algum bug. Eu ia te sugerir tentar outro compilador mas este pode não ter as facilidades do mikroc

Link para o comentário
Compartilhar em outros sites

Em 17/01/2017 às 20:45, Isadora Ferraz disse:

ok mas como você sabe que o dado não é o do arquivo? onde, como você está vendo ele? penso que talvez seja alguma questão de formatação que não estamos conseguindo visualizar. Aguarde algum expert em ponteiros-vetores e cia.

 

Alternativamente, você pode considerar reduzir o nível de otimização do compilador ou , se não obtiver sucesso de forma alguma, considerar que ele pode possuir algum bug. Eu ia te sugerir tentar outro compilador mas este pode não ter as facilidades do mikroc

 

 

Obrigado pela ajuda. Acabei conseguindo resolver parte do problema, agora, consigo processar os caracteres e exibí-los no LCD, porém, não estou conseguindo enviar os mesmos através da UART (pelo menos e o que acho, pois o ESP não compreende os dados).

 

A solução foi boba, na realidade. Estava utilizando uma variável para indexar meu vetor, e esta variável estava declarada como CHAR, e não como INT. Isto causou algum bug na indexação, mas o compilador não acusava nada nos logs. Após arrumar isso, tudo passou a funcionar.

 

Código de referência:

Citação

 


unsigned char DADO;

unsigned char DADOCARREGADO[64];

unsigned int index;

 

Mmc_Fat_Assign("main.cnf", 0xA0);

       size=Mmc_Fat_Get_File_Size(); //Obtem tamanho do arquivo
       Mmc_Fat_Reset(&size);


       y=1;

       index = 0;
       for ( y=1 ; y<=size ; y++)
       {
         Mmc_Fat_Read(&DADO);
        index = index +1;

        DADOCARREGADO[index] = DADO;

 
 

 

 

Aqui eu resumi o código. No meu caso utilizo varios vetores pequenos no lugar de DADOCARREGADO, e um switch case para selecionar os dados que vão para cada pequeno vetor (endereço IP, SSID e etc).

 

Em anexo, consta um print do LCD (Proteus) contendo a informação presente nos vetores de dados, sendo o SSID, SENHA, e IP (respectivamente - dados de teste).

LCD.PNG

 

 

Agora o problema já é outro.

 

Tenho o endereço IP no vetor IPADDR

 

Citação

 


unsigned char IPDADDR[16];
 

 

 

E estou enviando ele para o ESP através da UART. Parece que o dado que chega no ESP não é entendido por ele, pois ele fica em loop.

Como sei disso? Pois se eu desativar a função de LOAD de dados do SDCard, e declarar o vetor IPADDR com um valor précarregado, como abaixo, funciona:

 

Citação

 


unsigned char IPDADDR[16] = "192.168.1.100";
 

 


O que me faz acreditar que o problema é formatação dos dados que estão sendo enviados pela UART.

 

Alguma dica do que fazer? Já tentei utilizar o strcpy para formatar o dado, e o memcpy para copiar para outro vetor, mas nada tem efeito.

 

 

PS: Os testes com o ESP (Wifi) estão sendo realizados em protótipo (físico).

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
1 hora atrás, Josias_Martins disse:

CHAR, e não como INT. Isto causou algum bug na indexação

de fato se seu arquivo for maior que 256 bytes, dá pau. Penso que só cabeçalho já é maior que isso.

 

Penso que 1º você deve se autorresponder:

-que tipo de dado o esp (não conheço) espera receber? é em asc-ii mesmo? Já tentou enviar byte a byte e não "a palavra toda"?

-que função de uart está usando? prinf()? putc()? putchar()? etc? Consulte o help dela pra ver que tipo de argumento ela espera. Mas ve se desta vez consulta a página certa! (kk). Enviar dados pela serial é muito fácil. Já pensou em criar sua própria função baseada no hw do mc?

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Isadora Ferraz disse:

de fato se seu arquivo for maior que 256 bytes, dá pau. Penso que só cabeçalho já é maior que isso.

 

Penso que 1º você deve se autorresponder:

-que tipo de dado o esp (não conheço) espera receber? é em asc-ii mesmo? Já tentou enviar byte a byte e não "a palavra toda"?

-que função de uart está usando? prinf()? putc()? putchar()? etc? Consulte o help dela pra ver que tipo de argumento ela espera. Mas ve se desta vez consulta a página certa! (kk). Enviar dados pela serial é muito fácil. Já pensou em criar sua própria função baseada no hw do mc?

 

Pois então, estou utilizando a função UART1_WRITE, do próprio MikroC.

 

Se eu declaro uma variável CHAR e inicializo ela com o valor, funciona:

 

Citação

 


char TESTE = "192.168.0.1" 

UART1_WRITE(TESTE);
 

 

 

Agora, utilizando a variável que contem o endereço IP que foi lido do SDCard, não vai.

Cheguei a cogitar a hipótese de não estar carregando os dados, mas parece que não é isso. Coloquei vários pontos de aviso (leds piscando) no decorrer do código para verificar se as funções são concluídas com êxito.

 

Amanhã vou ver se compro um Display LCD, e de repente ligo ao Hardware para ver o que ele exibe (estou sem display no HW).

 

EDITADO:

 

Realmente, os dados estão sendo carregados. Como sei? Criei um IF para verificar se o conteúdo da posição "0"  do vetor IPADDR é o primeiro número do endereço IP, acionando dois LEDs para caso positivo, e funcionou como esperado. Ou seja, o dado no Vetor é o dado esperado, mas por algum motivo ao enviar pela UART se torna ilegível ao ESP8266 (Wifi).

 

Não parece ser problema com a UART, pois se envio a infornação diretamente, ele reconhece.

 

Por exemplo, isso funciona:

Citação

 


UART1_Write("192.168.1.100")
 

 



 

Agora isso, não:

Citação

 


UART1_Write(IPADDR)
 

 

 

Criando uma variável de teste, também funciona:

 

Citação

 


unsigned char TESTE="192.168.1.100"

UART1_Write(TESTE)

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

UART1_Write("Parece esperar receber uma string em asc-ii como argumento") e IPADDR parece ser uma matriz. Hás de tentar de novo a strcpy() ou algo do gênero. Ou até mesmo enviar byte a byte algo bem lôco como

i=0;
while(i<16) UART1_Write(IPADDR[i++]);//(caso IPADDR esteja em asc-ii)

Mas espere... tem maneira + elegante. Aguarde algum expert em ponteiros...

Mas algo me diz que você está à um passo da felicidade de descobrir por si...

Link para o comentário
Compartilhar em outros sites

19 minutos atrás, Isadora Ferraz disse:

UART1_Write("Parece esperar receber uma string em asc-ii como argumento") e IPADDR parece ser uma matriz. Hás de tentar de novo a strcpy() ou algo do gênero. Ou até mesmo enviar byte a byte algo bem lôco como


i=0;
while(i<16) UART1_Write(IPADDR[i++]);//(caso IPADDR esteja em asc-ii)

Mas espere... tem maneira + elegante. Aguarde algum expert em ponteiros...

Mas algo me diz que você está à um passo da felicidade de descobrir por si...

 

Pois então. Nesse meio tempo consegui resolver isso. Acabei tendo a mesma "luz" que você.. haha

 

O problema é que a função que estava utilizando para envio da matriz, não estava funcionando como esperado. Ela não estava enviando cada um dos bytes, apenas o primeiro byte.

 

OBS: Escrevi errado la em cima no exemplo, a função certa era UART1_Write_text, para envio de mais de um caractere.

 

No fim, acabei escrevendo uma função própria, com um laço for, que faz o envio caractere por caractere, e tudo passou a funcionar como esperado!

 

 

Muito obrigado pela ajuda. Como trabalho sozinho, muitas vezes você chega num ponto que não enxerga mais erros básicos e precisa de alguém para trocar uma ideia!

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...