Página 1 de 4
Alterar apenas um bit de um byte, como?

Enviado:
16 Jan 2010 15:28
por neto_e_khelen
Estou montando um circuito com os cis 74hc595 e 74ls165 para expandir as portas ios do pic. Mas estou com um dúvida aqui:
Inicio uma variável int32 da seguinte maneira:
int32 saidas=0b00000000000000000000000000000000;
A dúvida é? como faço para mudar o estado de um bit sem alterar o restante??
Por exemplo, mudar o estado do 8ª bit da direita para a esquerda sem alterar os outros 32 bits??? estou usando o ccs.

Enviado:
16 Jan 2010 16:16
por Sergio38br

Enviado:
16 Jan 2010 18:38
por ze
oi. não sei se as macros serão otimizadas no seu cod usando 32 bits. sugiro que use como alternativa uma estrutura doida com struct e/ou union, campos de bit e afins para este fim. talvez dê um pouco de dor de cabeça pro uc e pra ti mas azar dele e teu. se quiser colaborar com ele usa char mesmo uai. pra 4 74595 é só chamar a rotina de deslocar char 4 vezes com 4 variáveis difs.
abç

Enviado:
16 Jan 2010 21:08
por neto_e_khelen
Aprendi a usar a função: bit_set(saidas,0);
Só que ele seta o bit da saida que eu quero mais logo já volta a 0...COmo setar e continuar assim??

Enviado:
17 Jan 2010 08:51
por fabim
o tio, isto é o basico dos operandos.
Não entendi exatamente o que esta dizendo com seta, mais logo reseta..
Mas os operandos basicos para o que você quer são AND E OR.
por baixo, mesmo que.
AND = Zera = &
OR = SETA = |
Veja um exemplo.
variavel 8bits saida
saida = 0b11110000;
Veja eu manipulei os dados em binario, "que hoje perdi esse costume", e coloquei o nible superior em 1, e o inferior em 0;
Quero que o Bit 6 de saida, seja colocado como zero, sem alterar os outros bits..
saida &= 0b10111111;
Veja apenas o bit6 como zero, ou seja, o and força este bit a zero, sem fuçar nos outros bits.
Agora.
saida = 0b11110000;
Veja eu manipulei os dados em binario, "que hoje perdi esse costume", e coloquei o nible superior em 1, e o inferior em 0;
Quero que o Bit 2 de saida, seja colocado como 1, sem alterar os outros bits..
saida &= 0b00000100;
Veja apenas o bit2 como 1, ou seja, o or força este bit a 1, sem fuçar nos outros bits.
bom, sabendo-se destes operandos e para q servem pode-se criar makros constantes de compilador etc.
Veja por exemplo o que o lellis BOSTOU,!! turca!!..
Cabrito ? ou não Cabrito ?
Fabim

Enviado:
17 Jan 2010 09:24
por Djalma Toledo Rodrigues
Para não dar bode. rs
Xor alterna o estado de um Bit, ou Byte se preferir no atacado
Equivale ao Togle do 18F
DJ

Enviado:
17 Jan 2010 09:36
por ze
bom isso é peculiaridade da sua função que deve ser + bem estudada. pelo jeito é o horrendo ccs. mas se ela for macro (que não é o mesmo que função) isso não deveria ocorrer. verifique seu programa como um todo. ex. alguma interrupt pode estar causando isso. para setar um bit (pino) numa porta.
Ah e se não for pino do uC e sim de seu periférico 74hcxx tem + coisa envolvida e não quero forçar muito minhas bolas de cristal.
Existe algo + fácil tanto de entender como de escrever do que RB0=1 p.ex.???? porque a mrd do ccs complica tanto???
abç
neto_e_khelen escreveu:Aprendi a usar a função: bit_set(saidas,0);
Só que ele seta o bit da saida que eu quero mais logo já volta a 0...COmo setar e continuar assim??

Enviado:
17 Jan 2010 11:50
por neto_e_khelen
O negócio é o seguinte: Estou montando um circuito com 4 ci´s 74hc595 e 4 74ls165. Liguei o pic no pc e envio dados para o pic via rs232 para ligar e desligar uma certa saida dos ci´s 74hc595. Até ai ta tudo certo, só que quando envio o caracter 'a' por exemplo é pra ele ligar uma certa saida, só que as outras podem ou não estar ligadas e desligadas, entendeu?? por isso achei melhor usar o set_bit e o clear_bit. Sò que no meu programa ele seta o bit que quero e logo apos ele já vai a nivel 0 denovo.
Segue o link do arquivo de simulação no proteus e o códico em ccs para vocês entenderem melhor:
Testes 74hc595.rar

Enviado:
17 Jan 2010 14:20
por Sergio38br
vc desligou o wdt??
[ ]`s
Sergio

Enviado:
17 Jan 2010 15:30
por neto_e_khelen
Não tinha desligado, mas desliguei agora com o código:
#fuses NOWDT
E continua ligando e desligando.

Enviado:
17 Jan 2010 17:36
por Djalma Toledo Rodrigues
Se você esta usando Shift Register para ampliar os I / O do µC ao altera um Bit terá
que enviar toda a sequência.
DJ

Enviado:
17 Jan 2010 18:56
por Red Neck Guy
Um forma elegante de fazer é a seguinte:
Criar uma variavel global que contém o estado dos bits que serão armazenados no 74hc595 ou similar e sempre que for realizar todas as operações de escrita e leitura nessa variavel. Daí o refresh do conteúdo do 74hc595's pode ser de duas formas, ou a cada alteração dos valores dos bits ou por pooling. Isso vai depender da frequência que tu faz a alteração nos valores e do que está ligado nas saídas. Se fosse para, digamos, controlar relés ligados aos 74hc595's a técnica do pooling seria legal pois poderia deixar um pooling aa cada 3ms rodando numa thread da aplicação e em outra thread tratar os dados referentes aos comandos recebidos da serial e executar as operações sobre a memória espelho
- Código: Selecionar todos
//variavel global
int32 espelhoReles; //Tens que ver o tipo conforme o teu compilador
//Função para escrever na variavel espelho
// (Esse código não tem pretende ser bonito)
//
unsigned char setRele(unsigned char rele,unsigned char value){
espelhoReles&= ~rele;
espelhoReles|= value<<rele;
}
// Função de refresh dos 74hc595 que
// pode ser chamada a cada vez que o valor for alterado
// ou por pooling
void atualizaRegs(void){
for(unsigned int i=0;i<4;i++)
write_74hc595( (unsigned char*)((unsigned char*)& espelhoReles)[i]);
}

Enviado:
18 Jan 2010 21:32
por neto_e_khelen
Vou explicar melhor: O que eu preciso é que, quando o pic receber um caracter via serial ele acenda ou apaga uma lampada de minha casa. Por exemplo: recebeu letra 'a' = acender lampada do comodo 1. Recebeu letra 'b' = apagar lampara do comodo 1. Até ai tudo bem, o problema é que no meu código, quando ligo a lampada do comodo 1 e vou ligar a lampada do como 2 ele liga, porem desliga a do comodo 1. Entendeu?? Ta ai o código que estou usando, acho que eu preciso é sempre estar atualizando o valor da minha variavel, tentei assim: saidas=saidas; mas mesmo assim não da certo. Por favor me ajudem!! sei que tem gente aqui que entende muito!!!
- Código: Selecionar todos
#include <16F877.h>
#include <74595.c>
#include <74165.c>
//#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES RC //Resistor/Capacitor Osc with CLKOUT
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
int32 saidas=0b11111111111111111111111111111111;
int32 saida_atual=0b00000000000000000000000000000000;
comodo1_lig();comodo2_lig();comodo3_lig();comodo4_lig();comodo5_lig();comodo6_lig();comodo7_lig();comodo8_lig();comodo9_lig();comodo10_lig();
comodo1_des();comodo2_des();comodo3_des();comodo4_des();comodo5_des();comodo6_des();comodo7_des();comodo8_des();comodo9_des();comodo10_des();
char x;
short vlr_b0_ant = 1, vlr_b1_ant = 1, vlr_b2_ant = 1, vlr_b3_ant = 1, vlr_b4_ant = 1, vlr_b5_ant = 1, vlr_b6_ant = 1, vlr_b7_ant = 1, vlr_c0_ant = 1, vlr_c1_ant = 1;
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
while(1)
{
if (kbhit()) // se houver caractere no buffer de entrada da serial ...
{
x = getchar(); // busca caractere da serial
switch(x) // escolhe x
{
case 'a' :
{
comodo1_lig();
break;
}
case 'b' :
{
comodo1_des();
break;
}
case 'c' :
{
comodo2_lig();
break;
}
case 'd' :
{
comodo2_des();
break;
}
}
}
}
comodo1_lig()
{
putc('a');
bit_set(saidas,0);
write_expanded_outputs(&saidas);
delay_ms(50);
output_high(PIN_B6);
delay_ms(50);
output_low(PIN_B6);
saidas=saidas;
}
comodo1_des()
{
putc('b');
bit_clear(saidas,0);
write_expanded_outputs(&saidas);
delay_ms(50);
output_high(PIN_B6);
delay_ms(50);
output_low(PIN_B6);
saidas=saidas;
}
comodo2_lig()
{
putc('c');
bit_set(saidas,1);
write_expanded_outputs(&saidas);
delay_ms(50);
output_high(PIN_B6);
delay_ms(50);
output_low(PIN_B6);
saidas=saidas;
}
comodo2_des()
{
putc('d');
bit_clear(saidas,1);
write_expanded_outputs(&saidas);
delay_ms(50);
output_high(PIN_B6);
delay_ms(50);
output_low(PIN_B6);
saidas=saidas;
}

Enviado:
19 Jan 2010 06:58
por fabim
hum tá,,,
não olhei o source., mais a unica forma de isto acontecer, é você ao invés de usar uma variavel, que ja tem o nivel dos pinos de saida, alterar esta variavel, enviar novamente para os shifts, igual eu te expliquei lá encima na logica dos operandos..!
Tu esta mandando o BIT a 1 ou a 0 para aquele determinato pino, só que esta mexendo nos outros tambem.!!!
Sobre enviar um Byte, sendo um char. isso bagunça um pouco a cabeça, faz de outra forma.
BIT7 = 1 = liga
BIT7 = 0 = desliga
BITS0....6 = qual lampada vai ser atualizada
Isso fica mais facil pra você!!!
Abraços
Fabim

Enviado:
19 Jan 2010 09:31
por ze
-entende como funciona o 74hc595? se e quando endender vai ver com é fácil acioná-lo sem usar as funcs mastigáveis e fazer o uC se curvar as suas regras.
-quebrei o teu galho e li o fonte em ccs...write_expanded_outputs(&saidas): o tipo de parâmetro está correto? sabe como funciona esta func? foi feita pro teu hw mesmo? debulhe-a.
-junte as 2 dicas acima e faça outra função 100% sua
abç