LusoRobótica - Robótica em Português

Sistemas específicos => PIC => Tópico iniciado por: banji em 19 de Outubro de 2012, 18:44

Título: Passar byte para bit em pic18f4550
Enviado por: banji em 19 de Outubro de 2012, 18:44
Boas pessoal,

estou com um problema , estou lendo dois sinais que estao a alto=1 sempre que um vai a 0 um dos sinais quando vai a 0 envia um 1 e o outro sinal quando vai a 0 envia um 0. estou a ler bem o sinal o problema é o seguinte : depois envio por putcusart a varavel que m guarda os dados e ela aparece 000000001 00000000 000000001 0000001 00000001 0000000 00000001 00000000 00000001 00000001 00000001, quando eu queria que aparece-se 10111010111.

ja tentei ao mesmo tempo que uso os dados shiftar mas assim aparece-me 00000010 0000000 00000010 ....

Alguem sabe o que poderei fazer? estou a usar o compilador c18.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: ivitro em 19 de Outubro de 2012, 19:19
Assim por alto tu tas a ler isso para uma variável char [8bits ou 1 byte] mete isso numa variável booleana ( 0 ou 1)

ou então quando fazes um nova leitura fazes um shift para a esquerda
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 19 de Outubro de 2012, 19:50
o que eu leio tem 27 bits logo preciso de uma variavel com 32 bits , estou a usar uma variavel do tipo double .

Sinceramente ja fiz de tudo quando shifto << shifta um bit em cada byte, ou seja não entendo pk é que esta a passar o byte em ves de bit a bit :s
Título: Re: Passar byte para bit em pic18f4550
Enviado por: ivitro em 19 de Outubro de 2012, 19:53
mas tu tas a ler directamente para essa variável não é??
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 19 de Outubro de 2012, 19:58
o meu codigo de leitura é este :

void leitura()
 
{  i=0;
 
    while(i<27) //para ler 26 bits
{
 
    if(PORTBbits.RB2==0 && PORTBbits.RB1==1)
      {
       data=!PORTBbits.RB2;
       while (PORTBbits.RB2==0 && PORTBbits.RB1==1);
       data=data<<1;
      }
   if(PORTBbits.RB2==1 && PORTBbits.RB1==0)
      {
       data=PORTBbits.RB1;
       data=data<<1;
        while(PORTBbits.RB2==1 && PORTBbits.RB1==0);
       
      }
i++;
}   

 
putcUSART(data);
     while(BusyUSART());

   

     INTCON3bits.INT2IF=0;
     INTCON3bits.INT1IF=0;
     INTCONbits.GIE=1;
     
   
}

 a variavel data está como int ... estou a ler numa interrupçao no flanco descendente do INT1 e INT2

Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 19 de Outubro de 2012, 20:05
estou a reparar numa coisa , no ciclo while(i<27)  se eu puser while(i<8) para ler so um byte ele continua a ter 26 bytes e a escrever um bit em cada um desses bytes alias se retirar o ciclo while ele lê na mesma :s estou a ficar maluco .....
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 19 de Outubro de 2012, 20:07
funcionaria melhor com um contador até 26

Variável=0
For Bit=0 to 26
  Aquisição do valor para "Data"
  if Data=1 then Variável = Variável or (2 ^ Bit)
Next

ps: a linguagem é outra mas trata-se de um exemplo, usar while e wend também funciona

Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 19 de Outubro de 2012, 20:10
não estou a entender esta ultima parte ??? porquê o "or(2^BIT)
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 19 de Outubro de 2012, 20:15
2 elevado a um número vai dar o valor do bit inserido no byte como 1
assim coloca-se o operador OR que vai adicionar esse valor à variável final

exe:
2^5 = 10 0000 em binário (bit 5)
se o valor da variável já for 00 0101 o resultado será 10 0101 (ao colocar o operador OR)

10 0000 OR 00 0101 = 10 0101

last edit: OR é um operador lógico e não uma condição (enganei-me)
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 20 de Outubro de 2012, 12:23
com a alteração do (2^bit) é o mesmo que fazer variavel=variavel<<1 esta a deslocar um bit em cada byte.

a saida pela usart esta a ser a seguinte:00000010 00000010 00000010 00000000 00000010 00000010 00000000 00000000
00000000 00000010 00000010 00000000 00000010 00000010 00000000 00000010
00000010 00000010 00000010 00000000 00000010 00000000 00000010 00000000
00000010 00000010        e eu queria: 11101100 01101101 11101010 11    ou sja cada byte deveria ser um bit :s

em anexo envio o meu codigo, não sei o que pode estar a acontecer :s. já ando à quase uma semana com isto....
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 20 de Outubro de 2012, 12:45
Sim, 2^bit vai dar o mesmo que shift left de 1, de qualquer forma tem de ser acrescentado o bit recebido pela uart.
Vou ver do código...
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 20 de Outubro de 2012, 13:00
Código: [Seleccione]
variavel=0;
for (i=0;i<26;i++)
{
    if(PORTBbits.RB2==0 && PORTBbits.RB1==1) //RB2 ?! não seria "if PORTBbits.RB2==1", tem de detectar apenas o bit 0 do byte
      {
       data=!PORTBbits.RB2; //apagar, data não é usada em nenhum lado
       variavel=variavel|(2^i);
       while (PORTBbits.RB2==0 && PORTBbits.RB1==1); //RB2 ?!     
      }
   if(PORTBbits.RB2==1 && PORTBbits.RB1==0) //apagar esta condição completa
      {
       data=PORTBbits.RB1;       
        while(PORTBbits.RB2==1 && PORTBbits.RB1==0);
      } 
}   
      putcUSART(variavel); //OK

infelizmente não entendo de C, alguém poderia confirmar este código sff  :-\
Título: Re: Passar byte para bit em pic18f4550
Enviado por: ivitro em 20 de Outubro de 2012, 13:13
tu tas a ler o bit directamente para o teu data e depois alteras o data isto 27 vezes...

lê para um buffer 0 ou 1

fazes o shit de data e depois um e adicionas o teu buffer.

ou então tens que fazer

data=data<<1 e depois
data= data| PORTBbits.RB2

Código: [Seleccione]

data=0;

for (i=0;i<26;i++)
{
    if(PORTBbits.RB2==0 && PORTBbits.RB1==1)
    {
    data|=0;  //Alteras o primeiro bit de data para 0
    while (PORTBbits.RB2==0 && PORTBbits.RB1==1); //RB2 ?!     
    }
    if(PORTBbits.RB2==1 && PORTBbits.RB1==0) //apagar esta condição completa
    {
    data|=1;      //Alteras o primeiro Bit de data para 1
    while(PORTBbits.RB2==1 && PORTBbits.RB1==0);
    } 
    data<<=1; // shift de data para a proxima ronda alterar o primeiro bit again!
}   
      putcUSART(data); //OK

Se as tuas condições estiverem correctas vais ter na saida o que queres.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 20 de Outubro de 2012, 13:24
Obrigado Ivitro, é isso mesmo embora com algumas modificações:

no inicio da leitura dos 27 bits data tem de ser 0

aqui troquei as instruções (shift só depois da operação lógica)
data= data| PORTBbits.RB2
data=data<<1

no final da leitura dos 27 bits tem de haver um shift right
Título: Re: Passar byte para bit em pic18f4550
Enviado por: ivitro em 20 de Outubro de 2012, 13:32
Editei o meu post anterior e já meti o código...

em termos de eficiência não sei o que é melhor de fazer adição ou um OR ou até mesmo fazer um incremento

tipo:

se....
data++;
se
não faz nada

e depois o data<<=1;

tas a ver? era interessante discutirmos isto XD
Título: Re: Passar byte para bit em pic18f4550
Enviado por: ivitro em 20 de Outubro de 2012, 13:44
nop...

tas a fazer data= data OR 1, este um é no primeiro bit... os outro bit estejam a 1 ou a 0 vão ficar na mesma por causa da operação OR  com 0.

Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 20 de Outubro de 2012, 13:49
desculpa, apaguei o post antes de responderes, achei estranho o símbolo | antes do =, nabice mesmo  :-[
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 22 de Outubro de 2012, 15:42
Boas, agradeço muito a vossa ajuda mas continua tudo na mesma :s

vou tentar explicar o codigo pois reparei que voces nao estao a entender os meus if e os meus while

Código: [Seleccione]
//Bibliotecas

#include <p18f4550.h>
#include <delays.h> //biblioteca tempos
#include <stdio.h>  //biblioteca in e outs
#include <usart.h>  //biblioteca USART rs232
#include <math.h>  //Biblioteca operaçoes matematicas
#include <xlcd.h> //biblioteca lcd
#include <eep.h>  //biblioteca eeprom interna

//Configuraçao do Pic
#pragma config FOSC =HS



//Definiçoes


//Variaveis
void ISR_alta_prioridade(void);
unsigned char a=0;
int i=0;
long buffer_tx[15];
char read[27];
unsigned int data,variavel;




// Prototipo de funçoes 
#pragma code int_alta=0x08
void int_alta(void)
{
        _asm GOTO ISR_alta_prioridade _endasm
}
#pragma code

void leitura(void);
void gravar (void);
void test (void);
//Programa

void ISR_alta_prioridade()

  leitura();
 
}

 
[b]void leitura()
 

  data=0;
 
for (i=0;i<27;i++)    //PARA LER 26 BITS POIS TENHO DE LER 26 BITS SEGUIDOS
{
 
    if(PORTBbits.RB2==0 && PORTBbits.RB1==1)      // A LEITURA É FEITA EM DUAS PORTAS RB2 E RB1 NO INICIO ESTAO AMBAS A 1 QUANDO UMA DELA VAI A 0 ENTRO NA
      {
       data=data|!PORTBbits.RB2;                             // iNTERRUPÇÃO SE O RB2= 0 ENTÃO ENVIA UM 1 SE O RB1=0 ENTAO ENVIA UM 0 NUNCA FICAM AMBOS A 0, DAI OS IF
       data=data<<1;                                               
       
       while (PORTBbits.RB2==0 && PORTBbits.RB1==1); // ESTE WHILE É PARA GRANATIR QUE SO LÊ O PROXIMO BIT APOS LER O PRIMEIRO OU SEJA ENQUANTO RB2 ESTIVER
                                                                                      // A 0 NÃO FAZ NADA SO QUANDO FICAREM AMBOS A 1 OU O RB1 A 0 É QUE PASSA AO PROXIMO BIT.
      }
   if(PORTBbits.RB2==1 && PORTBbits.RB1==0)
      {
       data=data|PORTBbits.RB1;
       data=data<<1;
       
        while(PORTBbits.RB2==1 && PORTBbits.RB1==0);
      } 

}   
   

      putcUSART(data);
  while(BusyUSART());

   

     INTCON3bits.INT2IF=0;
     INTCON3bits.INT1IF=0;
     INTCONbits.GIE=1;
   
   
}[/b]



void main()
{
if(a==0)
{       
    //OSCCON=0xFE;
    OpenUSART (USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_LOW, 32);   //51
       
//Portas



      //interrupcoes
       ADCON1 =15;        //somente RA0 como analógico
 
      PORTB=0x00;         // limpa portb
     
      TRISB=(0b00000110); //
     
       INTCONbits.GIE=1;

      INTCON2bits.RBPU=0;
      INTCON2bits.INTEDG1=0;
      INTCON2bits.INTEDG2=0;

      INTCON3bits.INT2IP=1;
      INTCON3bits.INT1IP=1;
      INTCON3bits.INT2IE=1;
      INTCON3bits.INT1IE=1;
      INTCON3bits.INT2IF=0;
      INTCON3bits.INT1IF=0;
      a=1;
}   
 
 
 

      sprintf(buffer_tx,"INICIO\n\r");
      putsUSART(buffer_tx);
  while(BusyUSART());


      sprintf(buffer_tx,"Passe O Cartao\n\r");
      putsUSART(buffer_tx);
  while(BusyUSART());

      while(1);

 
}


este é o codigo completo, isto e para ler o sistema wiegand26.
o que esta a sair na usart com a vossa modificaçao é : 00000010 00000010 00000010 00000000 00000010 00000010 00000000 00000000
00000000 00000010 00000010 00000010 00000000 00000010 00000000 00000010
00000000 00000010 00000000 00000000 00000010 00000000 00000000 00000010
00000010 00000010     
               
e eu queria:11101100 01110101 01001001 11     

uma coisa que reparo é que se eu alteraro ciclo if(i=0;i<27;i++) e alterar para if(i=0;i<3;i++) a saida é exactamente igual:  00000010 00000010 00000010 00000000 00000010 00000010 00000000 00000000
00000000 00000010 00000010 00000010 00000000 00000010 00000000 00000010
00000000 00000010 00000000 00000000 00000010 00000000 00000000 00000010
00000010 00000010     

ou seja o ciclo if parece que não esta a fazer nada.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: totilx em 22 de Outubro de 2012, 16:28
if ou for?

a questão é que o teu ciclo for está mal implementado, visto a variável i não ter qualquer ligação com o código no seu interior...e que deveria ter para funcionar correctamente.

aparece-te o mesmo à saida pois tens sempre a mesma dimensão do array de chars... se o alterares para valores diferentes vais ver que tenho razão.

tens duas soluções assim de repente: ou englobas a variável i no teu código do for ou substituis o for por outro ciclo, de forma a que consigas ler os bit's que pretendes e termine assim que for lido o último.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 22 de Outubro de 2012, 16:49
For loll já me baralho todo :P ....

Não entendi englobo como??? eu ao fazer o ciclo For estou a dizer testa os If se for verdade poe o data a 1 se for o outro IF poe a 0 isto para um bit no bit seguinte , ja incrementa o i e faz isso i vezes neste caso 26.

quando falas em englobar o que queres dizer?

se eu ler um outro cartao mesmo pondo o ciclo for(i=0;i<3;i++) ele continua a preencher correctamente os 26 bytes ao inves dos 26 bits.

não consigo perceber porque é que ele escreve bytes e nao bits, nunca me tinha acontecido tal coisa :s....

Uma coisa tão simples esta a ser muito complicada, ou eu estou cada vez a desapreender mais heheheheh. ainda vou ter um esgotamento a ler os bits hihihihihhi
Título: Re: Passar byte para bit em pic18f4550
Enviado por: totilx em 22 de Outubro de 2012, 18:21
bom, esquecendo o que disse  pois nao faz diferença no teu caso....já reparaste que tens um array de chars e um char é um byte?

é mesmo por isso que estás a escrever bytes e não bits! :P
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 22 de Outubro de 2012, 18:39
mas se eu tenho d ler 26 bits preciso de algo no minimo com 4 bytes certo ??? alias em vez do data ser um INT deveria ate ser um Double mas ai nao iria conseguir shiftar.
eu mesmo pondo o data como um short continua a nao funcionar e a ler o data correctamente mas em bytes.

eu penso mesmo que o problema tambem passa pelo ciclo FOR , ja tentei usar um ciclo while do genero While(i<26)  { .... i++; }   mesmo variando o valor de i ele lê correctamente mas em bytes, ja ignorei o segundo IF:
while(i<27) 
{
 
    if(PORTBbits.RB2==0 && PORTBbits.RB1==1)      // A LEITURA É FEITA EM DUAS PORTAS RB2 E RB1 NO INICIO ESTAO AMBAS A 1 QUANDO UMA DELA VAI A 0 ENTRO NA
      {
       data=data|!PORTBbits.RB2;                             // iNTERRUPÇÃO SE O RB2= 0 ENTÃO ENVIA UM 1 SE O RB1=0 ENTAO ENVIA UM 0 NUNCA FICAM AMBOS A 0, DAI OS IF
       data=data<<1;                                               
       
       while (PORTBbits.RB2==0 && PORTBbits.RB1==1); // ESTE WHILE É PARA GRANATIR QUE SO LÊ O PROXIMO BIT APOS LER O PRIMEIRO OU SEJA ENQUANTO RB2 ESTIVER
                                                                                      // A 0 NÃO FAZ NADA SO QUANDO FICAREM AMBOS A 1 OU O RB1 A 0 É QUE PASSA AO PROXIMO BIT.
      }
   if(PORTBbits.RB2==1 && PORTBbits.RB1==0)
      {
       data=data|PORTBbits.RB1;
       data=data<<1;
                                                                                               ignorando esta parte continua a ler correctamente e esta parte deveria dar os 0 :s estou muito confuso
        while(PORTBbits.RB2==1 && PORTBbits.RB1==0);
      } 


}   
   

      putcUSART(data);
     while(BusyUSART());

   

     INTCON3bits.INT2IF=0;
     INTCON3bits.INT1IF=0;
     INTCONbits.GIE=1;
   
   
}

Título: Re: Passar byte para bit em pic18f4550
Enviado por: totilx em 22 de Outubro de 2012, 19:02
como estavas a trabalhar com bytes usavas o putcUSART(xxx) que envia tb um byte....
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 22 de Outubro de 2012, 19:15
bem entao quer dizer que o data esta por exemplo neste formato 10010110 11111001 11010110 mas quando uso o PUTCUSART fica 00000001 0000000 0000000 00000001 00000000 00000001 00000001 00000000 00000001 00000001 ..... é isso?

se eu guardar logo o data na eeprom estou a guardar 10010110 11111001 11010110???

como poderei enviar correctamente pela USART então???

se eu antes de enviar pela usart converter o data em decimal achas que funcionara?

estou a achar isto muito confuso , pois uns dizem que é o shfit mal feito outros dizm que tenho d por o or logico, tu dizes que é simplesmente de usar o PUTCUSART.

fiquei ainda mais confuso....
Título: Re: Passar byte para bit em pic18f4550
Enviado por: senso em 22 de Outubro de 2012, 20:27
O problema aqui é mesmo manipulação de bits, como usar shifts, and's, or's e afins.
Um double é um formato de representação de numeros em virgula flutuante, usar um double para representar um conjunto de bits é o pior que podes fazer.
Se queres 32 bits, usa um uint32_t, se o compilador tiver o inttypes.h ou nome parecido que define estas convenções para tamanhos de variaveis, não se queixa, se não usas um long que deve ser o mesmo, um short int deve ser uma variavel de 16 bits, ou 8, depende do compilador.

Anda por aqui um tutorial sobre o assunto,vê se te ajuda:
http://lusorobotica.com/index.php?topic=2838.msg29942#msg29942 (http://lusorobotica.com/index.php?topic=2838.msg29942#msg29942)

E vê o que o manual do teu compilador diz sobre a diferença entre | e || um é bitwise que é o que queres, e o outro é lógico, que não queres, vê quem é quem.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 23 de Outubro de 2012, 17:23
bem após este tempo todo ja entendi o que se está a passar,  não sei se repararam mas eu estou a ler a RB1 e RB2 por interrupção , estou a usar a interrupçao externa no flanco descendente, pois os meus sinais normalmente estao a 1 so quando envia dados e que vai a 0.

posso apagar todos os ciclos da funçao leitura, que ele lê na mesma 26 bytes pois entra 26 vezes na interrupçaoe em cada vez que entra escreve um byte um 1 ou um 0 dependendo do estado das portas.

Ou seja o meu problema está em entrar 26 vezes na interrupçao ao invés de ler os 26 bits so numa entrada da interrupção é niso que estou a lutar agora, pois se eu ler os 26 bits numa so interrupçao consigo preencher bit a bit o problema é que ele entra na interrupçao escreve um bit depois volta a entrar na interrupçao e escreve outro mas em cada saida fecha um byte.

Alguem m conseguiu entender :)

bem sabendo a falha vamos la procurar a solução, ajudas sao bem vindas hehehehe
Título: Re: Passar byte para bit em pic18f4550
Enviado por: totilx em 23 de Outubro de 2012, 20:17
boa! ...já conseguiste avançar! :p

tás a trabalhar com uma variável local, tenta uma global e vê se funciona.
Título: Re: Passar byte para bit em pic18f4550
Enviado por: banji em 07 de Novembro de 2012, 15:58
Boas pessoal já consegui solucionar o meu problema , acrescentei um while para esperar enquanto nao houvesse mudança de estado, problema de ler 26 bytes resolvido :) .
o outro problema foi facilmente (lol depois de muita luta) apenas criando uma nova variavel e fazer :

data=0b00000000;
byte=byte+(data<<i);

desta forma a palavra byte é bem preenchida :)

Mais uma vez obrigado a todos que participaram nesta "discussão"
Título: Re: Passar byte para bit em pic18f4550
Enviado por: dropes em 08 de Novembro de 2012, 00:28
estava complicado, ainda bem que conseguiste resolver  :)