Como pegar um sinal externo e dividí-lo em 80?

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Como pegar um sinal externo e dividí-lo em 80?

Mensagempor lpagano » 01 Jan 2007 18:13

Galera,

Seguinte, tô com um problema grave aqui. Preciso pegar um sinal externo (onda quadrada de 1kHz), jogar no PIC 16F877A e dividir esse sinal por 80. Quando der 80, sai um sinal em outro pino qualquer e aí o processo vai se repetindo. Já tentei tudo quando é código (no CCS) e não deu certo.
Alguém pode dar uma dica?

Valeu!
lpagano
Byte
 
Mensagens: 393
Registrado em: 06 Nov 2006 14:23

Mensagempor Wagner de Queiroz » 02 Jan 2007 08:00

Voce tentou detectar a mudança de nível como sinal ?

vai lendo a entrada até haver mudanca de nivel (Tipo: Alto para Baixo) e decrementar um contador até passar 80 interacoes ?
Seja Livre, Use Linux
Avatar do usuário
Wagner de Queiroz
Word
 
Mensagens: 872
Registrado em: 11 Out 2006 13:38
Localização: Barueri-SP

Mensagempor andre_luis » 02 Jan 2007 08:34

Interrupção de Timer no modo captura, não rola ?
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor lpagano » 02 Jan 2007 11:23

Wagner,

Eu fiz isso mas surgiu uma dúvida: se eu fizer o seguinte código:

if (input(pin_c6))
{
delay_us(600) //para aguardar descer de HIGH para LOW
output_high(pin_a0);
}

Quando eu ainda estiver dentro do bloco IF (fazendo o delay de 600us por exemplo) e o sinal no pino C6 descer de HIGH para LOW, ele não sai automaticamente desse bloco?

Valeu!
lpagano
Byte
 
Mensagens: 393
Registrado em: 06 Nov 2006 14:23

Mensagempor lpagano » 02 Jan 2007 12:28

Pessoal,

Eu fiz um circuito com um 555 para gerar o sinal de 1kHz. O que descobri agora é que com o código abaixo, sendo verdadeiro ou falso, ele entra dentro do IF e o executa.
Fiz o teste com um push-button manual e ele reconheceu.
As tensões do 555 estão compatíveis com o PIC.

if (input(pin_c6))
{
delay_us(600) //para aguardar descer de HIGH para LOW
output_high(pin_a0);
}
lpagano
Byte
 
Mensagens: 393
Registrado em: 06 Nov 2006 14:23

Metodo Peroba pouco ortodoxo.

Mensagempor Wagner de Queiroz » 02 Jan 2007 12:39

Não sou programador de PIC. Mas eu jogaria fora esta sua rotina.

Vamos repensar um pouco.

Se entendi sua rotina. Ele verifica o sinal alto em C6.
Quando ele chamar a rotina de atraso, se ocorrer mudancas em C6, seu programa só vai voltar a interrogar o pino após sua rotina de delay. Ou seja se voce colocar 6 segundos de atraso, somente após terminar a rotina de atraso que o pic vai voltar a ler c6 !


Crie uma variavel contador:
Código: Selecionar todos
Contador=0;

crie outra variavel:
Código: Selecionar todos
pegatroxa=0;


leia o pino C6. Quando ele cair para zero, ver se a variavel pegatroxa ja foi setada. Caso contrario, sete a variavel pegatroxa
Código: Selecionar todos
pegatroxa=1;

e incremente o contador.

Código: Selecionar todos
contador++;



Pq a variavel pegatroxa ? Pq quando ele detectar a mudanca do pino, vai incrementar contador. Com a pegatroxa nao. Ele só vai incrementar contador quando o sinal de C6 for baixo e a variavel pegatroxa =0.

Quando o sinal em C6 voltar a alto, zere pegatroxa.

Código: Selecionar todos
if (pin_c6)
{pegatroxa=0}
else
{
    if (pegatroxa=0)
    { pegatroxa=1;
       contador++
    }
 if (contador=80)
    { contador=0;
       manda_pulso(pin_a0);
     }
}


A variavel pegatroxa impede que o contador seja incrementado varias vezes enquanto o sinal estiver baixo.

a funcao manda_pulso() é sua funcao que vai enviar o pulso que voce quer.

Tenta isso. Qualquer coisa me procura no MSN.

O problema é só logica.

Voce tem que se preucupar com o sinal de pin_c6 durante a duração da rotina manda_pulso.
Seja Livre, Use Linux
Avatar do usuário
Wagner de Queiroz
Word
 
Mensagens: 872
Registrado em: 11 Out 2006 13:38
Localização: Barueri-SP

Mensagempor Red Neck Guy » 02 Jan 2007 13:02

Na verdade é relativamente fácil implementar:

//variavel global
unsigned char contadorCiclos=0;

#int_ext
void int_External(void){

contadorCiclos++;
if(contadorCiclos>=80){
contadorCiclos=0;
PINO_SAIDA = ~PINO_SAIDA;
}
}
ASM51 descanse em paz!
Avatar do usuário
Red Neck Guy
Dword
 
Mensagens: 1968
Registrado em: 12 Out 2006 22:24

Mensagempor Red Neck Guy » 02 Jan 2007 13:07

só pra complementar
e se a idéia for ativar o divisor apenas quando o botão estiver pressionado.


//variavel global
unsigned char contadorCiclos=0;
shor int flagBotao=0;

#int_ext
void int_External(void){

contadorCiclos++;
if(contadorCiclos>=80){
contadorCiclos=0;
if(flagBotao)
PINO_SAIDA = ~PINO_SAIDA;
else
PINO_SAIDA = 0;
}
}

///
void main(void){

for(;;){
if(!TECLA_BOTAO){//testa se o botao está pressionado
flagBotao = 1;
}
else
flagBotao = 0;
}
}
ASM51 descanse em paz!
Avatar do usuário
Red Neck Guy
Dword
 
Mensagens: 1968
Registrado em: 12 Out 2006 22:24

Mensagempor lpagano » 02 Jan 2007 18:34

Pessoal,

Valeu a força de todos. Já consegui matar o problema da seguinte forma. Veja o código abaixo:

loop:
if (!input(pin_c6)) //aguarda o HIGH do sinal quadrado
{
delay_ms(10); //aguarda 10ms para o sinal ir para LOW
cont++; //incrementa 1 na variável ‘cont’
if (cont==3600) //SE ‘cont’ for igual a 3600
{
x1++; //incrementa 1 na variável ‘x1’
output_B(x1); //joga o valor de ‘x1’ no portB
cont=0; //zera a variável ‘cont’
}
}

goto loop;


O sinal quadrado que consegui jogar foi de uns 55 Hz. Bem, aí o delay_ms(10) era para aguardar o sinal ir para LOW, ou seja, o código acima captura o sinal em HIGH. Fiz o teste e deu certo com a ajuda de um cronômetro. Como o sinal só iria para HIGH após uns 18ms, testei o delay com 11, 12, 13, 14 e 15 ms. Não teve alteração alguma no tempo. A variável 'x1' sempre era incrementada a cada mais ou menos 55,5 segundos, contanto com a precisão do disparo manual do meu cronômetro, que deu um desvio de no máximo 100ms. Depois fiz o mesmo teste para captura do sinal em nível LOW e também não teve nenhuma alteração.

Por favor, como consegui fazer o meu próprio código, não quero desmerecer os códigos que os amigos sugeriram acima, muito pelo contrário, me ajudaram muito a construir o meu código.

Para finalizar, obrigado mais uma vez a todos que ajudaram a responder esse tópico.

ATÉ QUE ENFIM ESSA NOVELA ACABOU!!!

fui!!!
lpagano
Byte
 
Mensagens: 393
Registrado em: 06 Nov 2006 14:23

Mensagempor andre_luis » 03 Jan 2007 07:55

lpagano,

Apenas uma sugestão: Se voce tiver tempo e paciencia, tenta implementar isso via interrupção e usando a função 'capture' do timer, pois o uso de delay() não é uma boa prática porque trava o processo; a menos que seu microcontrolador tenha apenas que fazer esse contador.

+++
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor microeletronica » 03 Jan 2007 08:34

Mesmo que o micro soh faca isso, sugiro tambem uma interrupcao de capture.
A tarefa a ser executada eh simples e pode ser feita sem muito codigo. :)
Aproveite o hw ao maximo :)
microeletronica
Byte
 
Mensagens: 158
Registrado em: 05 Dez 2006 18:22

Mensagempor lpagano » 04 Jan 2007 17:58

microeletronica e andre_teprom,

Valeu a força. Vou tentar fazer isso com a interrupção e aí eu aviso vocês se deu certo.

Valeu!!!
lpagano
Byte
 
Mensagens: 393
Registrado em: 06 Nov 2006 14:23


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x