Página 1 de 1

*Pointer,Variaveis locais...ou ok?

MensagemEnviado: 28 Jun 2018 21:38
por vtrx
Não sou bom na linguagem C,então quase sempre caio em 'armadilhas' que me faz perder tempo.
Comprei um módulo DHT11,e achei que não ia ser difícil sua implementação,mas foi...
Fique horas sem saber se era o Hardware,temporização ou rotina mal interpretada,desmembrei todas as partes da rotina principal e não achava alguma 'lógica errada' em nenhuma delas,mas era a forma de utilizar estas rotinas que eu estava fazendo 'errado'.
A rotina principal de leitura do módulo é:
Código: Selecionar todos
u8 DHT11_Read_Data(void)   
{    
  u8 buf[5];
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
  for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
               HM=buf[0];
               TP=buf[2];
               HM1=buf[1];
               TP1=buf[3];
         }
    }
    else
        return 1;
    return 0;       
}


Acontece que usando HM,TP,HM1 e TP1 como variáveis globais,a rotina retorna os valores corretamente,mas se eu usá-las no corpo da rotina,não consigo retornar os valores.
Exemplo:
Código: Selecionar todos
u8 DHT11_Read_Data(u8 var,u8 var1,u8 var2,u8 var3)   
{    
  u8 buf[5];
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
  for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
               var=buf[0];
               var1=buf[2];
               var2=buf[1];
               var3=buf[3];
         }
    }
    else
        return 1;
    return 0;       
}


Deste modo não consigo carregar as variáveis globais chamando a rotina como if(DHT11_Read_Data(HM,HM1,TP,TP1) ==0 ){...,não carrega os valores nas variáveis.
Como é o procedimento correto?

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 28 Jun 2018 22:12
por tcpipchip
vc deu o #include < >

TCPIPCHIP

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 28 Jun 2018 22:19
por Rodrigo_P_A
Existem várias formas, seguem 2 exemplos:


Código: Selecionar todos
u8 DHT11_Read_Data(u8 *var,u8 *var1,u8 *var2,u8 *var3)   
{   
  u8 buf[5];
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
  for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
               *var=buf[0];
               *var1=buf[2];
               *var2=buf[1];
               *var3=buf[3];
         }
    }
    else
        return 1;
    return 0;       
}


chamando:
void blablabla()
{
  u8 var,var1,var2,var3;
 DHT11_Read_Data(&var,&var1,&var2,&var3) ;
}



--- OU ASSIM:

Código: Selecionar todos
u8 DHT11_Read_Data(u8 *buf)   
{   
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
      for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
         return 0;
         }
       return 1;
    }
    else
   {
        return 2;
   }
    return 3;       
}


chamando:
void blablabla()
{
  u8 buf[5];
  u8 ret;
  ret=DHT11_Read_Data(buf) ;
  if ( ret==0 )
  {
   // ok..... faça algo seus dados estão aqui
  }
}

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 28 Jun 2018 22:27
por andre_luis
Nao ficou claro se voce também está usando essas variaveis dentro de alguma rotina de interrupção ou não, mas na dúvida sempre as declaro como volatile.

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 29 Jun 2018 09:02
por xultz
Uma terceira opção é você declarar uma estrutura com os quatro parâmetros que a função retorna (HM, TP, etc) e pode também colocar na estrutura o valor de retorna da função (0 se leu ok, 1 se deu zica), e fazer a função retornar esta estrutura. Fica bonitinho.
Ou então cria a estrutura somente com os 4 parâmetros e passa a estrutura sob forma de ponteiro, e retorna o valor de status da leitura do sensor. Depois que se acostuma a usar o operador ->, fica bem legalzinho também.

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 29 Jun 2018 10:01
por Rodrigo_P_A
Exemplo 3:

Código: Selecionar todos
typedef struct {
   u8 HM;
   u8 TP
   u8 HM1;
   u8 TP1;
} tpdadosxultz;

u8 DHT11_Read_Data(tpdados *tpdadosxultz)   
{   
  u8 i;
  u8 *buf=(u8*)tpdadosxultz;
  DHT11_Rst();
 if(DHT11_Check()==0)
    {
      for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
         return 0;
         }
       return 1;
    }
    else
   {
        return 2;
   }
    return 3;       
}


chamando:
void blablabla()
{
  tpdadosxultz xultz;
  u8 ret;
  ret=DHT11_Read_Data(&xultz) ;
  if ( ret==0 )
  {
   // ok..... faça algo seus dados estão aqui
   // aggora vc tem os dados em: xultz.HM  xultz.TP xultz.HM1 xultz.TP1
  }
}

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 29 Jun 2018 13:17
por eletroinf
O Xultz gosta de estruturas

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 30 Jun 2018 16:13
por xultz
Eu não gostei dessa parte:
Código: Selecionar todos
u8 *buf=(u8*)tpdadosxultz;


Não é mais humanamente compreensível fazer
Código: Selecionar todos
tpdadosxultz->HM = DHT11_Read_Byte();
tpdadosxultz->TP = DHT11_Read_Byte();
tpdadosxultz->HM1 = DHT11_Read_Byte();
tpdadosxultz->TP1 = DHT11_Read_Byte();


do que
Código: Selecionar todos
for(i=0;i<5;i++)
 {
 buf[i]=DHT11_Read_Byte();
 }

?

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 30 Jun 2018 16:36
por Rodrigo_P_A
xultz escreveu:Eu não gostei dessa parte:
Código: Selecionar todos
u8 *buf=(u8*)tpdadosxultz;


Não é mais humanamente compreensível fazer
Código: Selecionar todos
tpdadosxultz->HM = DHT11_Read_Byte();
tpdadosxultz->TP = DHT11_Read_Byte();
tpdadosxultz->HM1 = DHT11_Read_Byte();
tpdadosxultz->TP1 = DHT11_Read_Byte();


do que
Código: Selecionar todos
for(i=0;i<5;i++)
 {
 buf[i]=DHT11_Read_Byte();
 }

?



pode ser, mas eu pensei que fosse mais fácil para ele entender... existem várias formas de fazer.

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 01 Jul 2018 19:35
por vtrx
Usei como o Rodrigo_P_A sugeriu,pois é oque se encontra na Net,usando Keil:

Código: Selecionar todos
void TIM2_IRQHandler(void)  //
{
   u8   TP,TP1,HM,HM1;
     if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
     {
   //   GPIOA->ODR ^=  ( 1 << 2 );
   //   GPIOA->ODR ^=  ( 1 << 3 );
   //   GPIOB->ODR ^=  ( 1 << 2 );
       GPIOA->ODR ^= GPIO_Pin_2;
       GPIOA->ODR ^= GPIO_Pin_3;
       GPIOB->ODR ^= GPIO_Pin_2;
      if(DHT11_Read_Data(&HM,&TP,&HM1,&TP1)==0)
         {
            sprintf((char *)Texto,"HUMIDADE:%d%%, TEMPERATURA:%d C",HM,TP);
          GLCD_Print(4,16,Texto,White,Black);               
         }
         else
         {
            GLCD_Print(4,16,(u8 *)"DH11 erro",White,Black);
         }
      TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 );   
     }

}


Código: Selecionar todos
u8 DHT11_Read_Data(u8 *var,u8 *var1,u8 *var2,u8 *var3)   
{    
  u8 buf[5];
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
  for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
           *var=buf[0];
           *var1=buf[2];
           *var2=buf[1];
           *var3=buf[3];
         }
    }
    else
        return 1;
    return 0;       
}


Pergunta que preciso fazer:
1-Porque só tenho o resultado usando 'pointers',se usar direto retorna zero?
2-Porque usar
Código: Selecionar todos
&
,não seria '*' ?

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 01 Jul 2018 21:27
por Rodrigo_P_A
vtrx escreveu:Usei como o Rodrigo_P_A sugeriu,pois é oque se encontra na Net,usando Keil:

Código: Selecionar todos
void TIM2_IRQHandler(void)  //
{
   u8   TP,TP1,HM,HM1;
     if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
     {
   //   GPIOA->ODR ^=  ( 1 << 2 );
   //   GPIOA->ODR ^=  ( 1 << 3 );
   //   GPIOB->ODR ^=  ( 1 << 2 );
       GPIOA->ODR ^= GPIO_Pin_2;
       GPIOA->ODR ^= GPIO_Pin_3;
       GPIOB->ODR ^= GPIO_Pin_2;
      if(DHT11_Read_Data(&HM,&TP,&HM1,&TP1)==0)
         {
            sprintf((char *)Texto,"HUMIDADE:%d%%, TEMPERATURA:%d C",HM,TP);
          GLCD_Print(4,16,Texto,White,Black);               
         }
         else
         {
            GLCD_Print(4,16,(u8 *)"DH11 erro",White,Black);
         }
      TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 );   
     }

}


Código: Selecionar todos
u8 DHT11_Read_Data(u8 *var,u8 *var1,u8 *var2,u8 *var3)   
{    
  u8 buf[5];
  u8 i;

  DHT11_Rst();
 if(DHT11_Check()==0)
    {
  for(i=0;i<5;i++)
       {
        buf[i]=DHT11_Read_Byte();
       }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
           *var=buf[0];
           *var1=buf[2];
           *var2=buf[1];
           *var3=buf[3];
         }
    }
    else
        return 1;
    return 0;       
}


Pergunta que preciso fazer:
1-Porque só tenho o resultado usando 'pointers',se usar direto retorna zero?
2-Porque usar
Código: Selecionar todos
&
,não seria '*' ?


Essas suas dúvidas são conceituais, sugiro ler um pouco mais sobre ponteiros, veja um artigo:
https://www.ime.usp.br/~pf/algoritmos/aulas/pont.html

Se tiver mais dúvidas após ler, poste aí pra gente.

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 02 Jul 2018 09:15
por vtrx
Muito interessante...depois dizem que ASM é difícil...

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 02 Jul 2018 09:54
por Rodrigo_P_A
vtrx escreveu:Muito interessante...depois dizem que ASM é difícil...


depois que entender vai bem... vale a pena!

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 02 Jul 2018 19:09
por xultz
Pergunta que preciso fazer:
1-Porque só tenho o resultado usando 'pointers',se usar direto retorna zero?
2-Porque usar &,não seria '*' ?


Quando você passa uma variável para uma função (não seu ponteiro), o programa cria um clone dessa variável. Esse clone vai existir enquanto a função estiver em execução. Assim que a função encerrar, esse clone será sumariamente destruído de uma forma violenta e dolorida.
Quando você passa o ponteiro da variável, é como se você dissesse prá função "use a variável que mora na rua tal, número tal, cidade tal". A função vai lá naquele endereço e mexe na variável como quiser. Quando a função termina, a variável continua naquele endereço. Como quem criou a variável foi a função principal (e ela sabe o endereço, porque foi ela que criou a variável), quando ela for visitar o endereço vai encontrar o resultado do que a função que foi chamada fez na variável. Ficou confuso o que eu escrevi, mas não é (muito).

A segunda pergunta é um detalhe irritante do C. Você usa o * quando quer declarar um ponteiro. Você usa o & para pegar o endereço da variável. E usa * para pegar o valor apontado por um ponteiro. Mas como assim, usa o * para duas coisas? É, isso gera uma confusão dos diabos, e eu não sei da onde os inventores do C tiveram essa ideia de jerico. Depois de fazer um milhão de vezes, acaba se acostumando. Mas no começo, isso gera confusão mesmo, não se preocupe, você não é o único não.

Re: *Pointer,Variaveis locais...ou ok?

MensagemEnviado: 03 Jul 2018 07:55
por andre_luis
Porque usar &,não seria '*' ?


De um modo resumido, o & é usado como argumento da função, indicando o endereço da variavel á ser manipulada, enquanto que o * funciona mais como uma declaração de tipo, que no caso da declaracao da função, é o tipo ponteiro para armazenar o endereço da variavel 'endereço' instanciada posteriormente no argumento da função.