LusoRobótica - Robótica em Português
Sistemas específicos => PIC => Tópico iniciado 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.
-
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
-
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
-
mas tu tas a ler directamente para essa variável não é??
-
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
-
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 .....
-
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
-
não estou a entender esta ultima parte ??? porquê o "or(2^BIT)
-
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)
-
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....
-
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...
-
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 :-\
-
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
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.
-
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
-
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
-
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.
-
desculpa, apaguei o post antes de responderes, achei estranho o símbolo | antes do =, nabice mesmo :-[
-
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
//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.
-
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.
-
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
-
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
-
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;
}
-
como estavas a trabalhar com bytes usavas o putcUSART(xxx) que envia tb um byte....
-
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....
-
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.
-
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
-
boa! ...já conseguiste avançar! :p
tás a trabalhar com uma variável local, tenta uma global e vê se funciona.
-
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"
-
estava complicado, ainda bem que conseguiste resolver :)