Alterar apenas um bit de um byte, como?

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Alterar apenas um bit de um byte, como?

Mensagempor neto_e_khelen » 16 Jan 2010 15:28

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.
neto_e_khelen
Bit
 
Mensagens: 33
Registrado em: 22 Jul 2009 19:01

Mensagempor Sergio38br » 16 Jan 2010 16:16

Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor ze » 16 Jan 2010 18:38

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ç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor neto_e_khelen » 16 Jan 2010 21:08

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??
neto_e_khelen
Bit
 
Mensagens: 33
Registrado em: 22 Jul 2009 19:01

Mensagempor fabim » 17 Jan 2010 08:51

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
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Djalma Toledo Rodrigues » 17 Jan 2010 09:24

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
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor ze » 17 Jan 2010 09:36

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??
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor neto_e_khelen » 17 Jan 2010 11:50

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
neto_e_khelen
Bit
 
Mensagens: 33
Registrado em: 22 Jul 2009 19:01

Mensagempor Sergio38br » 17 Jan 2010 14:20

vc desligou o wdt??

[ ]`s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor neto_e_khelen » 17 Jan 2010 15:30

Não tinha desligado, mas desliguei agora com o código:
#fuses NOWDT
E continua ligando e desligando.
neto_e_khelen
Bit
 
Mensagens: 33
Registrado em: 22 Jul 2009 19:01

Mensagempor Djalma Toledo Rodrigues » 17 Jan 2010 17:36

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
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor Red Neck Guy » 17 Jan 2010 18:56

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]);
}

Avatar do usuário
Red Neck Guy
Dword
 
Mensagens: 1968
Registrado em: 12 Out 2006 22:24

Mensagempor neto_e_khelen » 18 Jan 2010 21:32

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;
}
neto_e_khelen
Bit
 
Mensagens: 33
Registrado em: 22 Jul 2009 19:01

Mensagempor fabim » 19 Jan 2010 06:58

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
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor ze » 19 Jan 2010 09:31

-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ç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Próximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Google [Bot] e 1 visitante

x