Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
Josias_Martins

mikroc for pic e mmc_fat_read (ler sdcard)

Recommended Posts

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.

 

Editado por Josias_Martins

Compartilhar este post


Link para o post
Compartilhar em outros sites

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ç

Compartilhar este post


Link para o post
Compartilhar em outros sites
  • Autor do tópico
  • 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.

    Editado por Josias_Martins

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    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.
     

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • 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.

     

     

    Editado por Josias_Martins

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    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

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • 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).

    Editado por Josias_Martins

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
    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?

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • 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)

     

    Editado por Josias_Martins

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    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...

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • 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!

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    Crie uma conta ou entre para comentar

    Você precisar ser um membro para fazer um comentário






    Sobre o Clube do Hardware

    No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

    ×