18F4520 chama a interrução e é executada duas vezes

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

18F4520 chama a interrução e é executada duas vezes

Mensagempor lpagano » 26 Dez 2008 16:37

Pessoal,

Estou com um programinha de interrupção pela mudança de estado do pino RB0 no 18F4520. Só que quando a interrupção ocorre, ela entra normalmente na rotina de interrupção, executa tudo numa boa e, às vezes (ou seja, não é sempre), quando termina a execução dessa rotina de interrupção o PIC repete essa rotina mais uma vez logo após o término da primeira passagem, isso sem nenhuma mudança de estado no pino RB0.

Vejam o código abaixo:



Código: Selecionar todos


unsigned int i_setup;


void interrupt ( )
{
     if (INTCON.INT0IF == 1)       // se o flag de estouro da interrupção for igual a 1, então
     {
          INTCON.INT0IF = 0;       // zera o flag IF
     }


i_setup = 0;


while (i_setup < 2)         // faz esse loop duas vezes
{
     variável1 = 0;          // atribuição de valores à variáveis
     variável2 = 3;
     variável3 = 10;
     delay_ms(500);

     i_setup++;
}


i_setup = 0;


while (i_setup <= 10000)          // faz esse loop 10001 vezes
{

     variável4 = 20;
     variável5 = 15;
   
     i_setup++;

}


}               // fecha a interrupção





// ---------  CONFIGURAÇÃO DA INTERRUPÇÃO ----------------------------

void main ( )
{

     RCON.IPEN=1;                    // interrupcoes habilitadas para familia 18F
     INTCON.GIEH = 1;                // habilita chave geral de interrupções
     INTCON.INT0IF = 0;              // zera flag da interrupção externa (RBO)
     INTCON.INT0IE = 1;              // habilita a interrupção INT0

     while (1);

}





Esse código está resumido, só para ilustrar como a interrução está estruturada.
Existe alguma coisa errada nesse código?


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

Re: 18F4520 chama a interrução e é executada duas vezes

Mensagempor Renie » 26 Dez 2008 20:54

Olá Ipagano,

Eu nunca usei C ( acho que todo mundo já sabe de tanto eu repetir!hehehhe), mas, vou dar meus pitacos!

- Uma rotina de interrupt de mais de 1 segundo? Para mim isso já
está errado, rotinas de interrupt devem ser o mais breve possível,
se é apenas um gatilho, monte uma variável com o disparo do mesmo
e trabalhe no seu Main.

- Não sei qual é a fonte do seu sinal de disparo da interrupt, pode
estar havendo "ruído" ou repique (sem debounce).

- Se realmente quiser a rotina com tanto tempo, ao entrar nela,
desabilite todas as interrupções até acabar de trata-la.

- Veja também se não está havendo interrupt por outros motivos,
verifique se não tem mais alguma habilitada também ( ex: Brown-out)

- A meu ver, reativar a flag de uma interrupt que está sendo tratada,
só deve ser feito ao final do tratamento.

Essas são minhas considerações, podem não ser a solução!

[]'s
Renie
Renie
Word
 
Mensagens: 732
Registrado em: 11 Out 2006 22:35
Localização: RJ - Niterói - Brasil

Mensagempor ffcprog » 26 Dez 2008 22:12

Tudo o que o Renie disse é valido.
Agora, você fez um while(1);

Como pode uma interrupção ocorrer mais de uma vez, se você está saindo da int, sem ligar o INTCON.GIEH ?

a não ser q sua interrupção fosse por periférico, e mesmo assim não ligou ou desligou o flag de interrupção dos periféricos....

ffcprog
ffcprog
Byte
 
Mensagens: 145
Registrado em: 14 Fev 2007 23:16

Mensagempor lpagano » 26 Dez 2008 22:48

Essa rotina de interrupção chamava uma outra em que era executado o restante do código (logo após o primeiro "i_setup = 0;"), ou seja, a rotina da interrupção um pouco antes desse meu código que mostrei a vocês eram duas rotinas: uma era void interrupt e outra era void setup. Acontecia o mesmo problema.

Eu também pensei que poderia ser o que o Renie disse, um possível ruído no circuito.

Também já tinha feito o teste desabilitando todas as interrupções no registrador INTCON.GIE logo após a entrada na rotina de interrupção, mas não funcionou.

Vou continuar tentando.

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

Mensagempor RobL » 27 Dez 2008 09:48

Teste (ferramenta):
1-Crie um contador (para teste) dentro dessa interrupção e outro na porta (em quem gera a int).
Compare os valores. Os dois devem ter o mesmo valor.

2-Com os contadores acima, mude o serviço dessa int, só para teste, set um flag ao entrar nela e retorne imediatamente, liberando todas interrupcoes.
Teste esse flag no main e execute o serviço.
Analise o comportamento e tire suas conclusões.

O objetivo é saber se são de fato duas chamadas.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor Djalma Toledo Rodrigues » 27 Dez 2008 10:16

Considerando pinos de entrada nível alto:
Borda de descida interrompe (Nivel baixo)
Borda de subida interrompe (Retorno ao nível alto)

De modo que para evitar essa dupla interrupção teste na ISR, se pino esta alto descarta, sai da interrupção.

A Interrupção por mudança de estado só é adquada para teclado. Prefira a Interrupção Externa, onde pode selecionar borda descida ou subida, se houver mais de um evento, mais de um pino, a interromper uma simples "Porta OR" com diodos 1N4148 já esta de bom tamanho.
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Re: 18F4520 chama a interrução e é executada duas vezes

Mensagempor Djalma Toledo Rodrigues » 27 Dez 2008 10:42

lpagano escreveu:
// --------- CONFIGURAÇÃO DA INTERRUPÇÃO ----------------------------

void main ( )
{

RCON.IPEN=1; // interrupcoes habilitadas para familia 18F
INTCON.GIEH = 1; // habilita chave geral de interrupções
INTCON.INT0IF = 0; // zera flag da interrupção externa (RBO)
INTCON.INT0IE = 1; // habilita a interrupção INT0

while (1);

}

A INTCON.GIEH = 1 Deverá ser a última - verifique
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor lpagano » 27 Dez 2008 14:07

Pessoal,

New news.
Fiz um teste aqui no circuito montado na EasyPIC5 e parece que a falta de um debouncer está causando esse problema. Fiz alguns testes com acionamento da interrupção por pelo botão RB0 dessa placa, fazendo com que ele seja acionado duas vezes bem rápido (coisa de 100ms entre acionamentos). Não deu outra: quando saiu da interrupção entrou nela de novo.

Eu coloquei também o registrador INTCON2.INTEDG0 = 0 para acionar na borda de subida.

Estou fazendo essa interrupção pelo botão RB0 pois no circuito pronto quem gerará a interrupção será outro PIC, ou seja, com baixíssima probabilidade de gerar ruídos.

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

Mensagempor guest2003 » 27 Dez 2008 15:59

O problema é o seguinte,

Voce esta desligando o Flag de interrupção no inicio da mesma... e como seu sinal pode ter ruido, logo apos voce desligar e antes mesmo de sair da INT o flag é ligado novamente... causando uma nova chamada logo apos o atendimento da primeira...

Como sua INT é demorada, pode usar isso como bounce, simplesmente desligando o Flag no fim da INT antes de sair dela, ai tudo vai funcionar como voce deseja...

e IF e esta instrucao... INTCON.INT0IF = 0;

Faca isso no final da rotina...

[]'s
http://www.sethi.com.br (Institucional)
http://www.sethi3d.com.br (Impressoras 3d)
http://www.sethi.com.br/blog (Blog Impressoras 3d)
Avatar do usuário
guest2003
Word
 
Mensagens: 746
Registrado em: 13 Out 2006 11:48
Localização: Campinas - SP

Mensagempor lpagano » 28 Dez 2008 09:19

guest2003,

Realmente parece que sua dica de zerar o flag da interrupção no final da rotina funcionou legal.

Os primeiros a responder o post também falaram sobre a falta de um debouncer e pude comprovar isso por aqui.

Já fiz vários testes e não deu mais o problema.

Obrigado a todos pelas dicas!!!!

:P :P :P
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