Página 1 de 1

Interrupção externa PIC16F877A

MensagemEnviado: 14 Set 2009 02:49
por Viana
Olá, pessoal.
Estou fazendo um programa para controlar o disparo de 1 triac com o pic 16f877a, mplab e compilador ccs. Durante os testes descobrimos que ele não está fazendo as contas da chamada de interrupção e, quando colocamos o delay em ms, ele não o faz corretamente.
Eis parte do código fonte:

#int_ccp1 //Interrupção gerada pela entrada CCP1
void detecta_zero()
{
if (liga == 1)
{ // Lembrando que o período desejado para controle é de 8,333ms (1 semi-ciclo de 60Hz)
fase = 8 - (0.08*saida_perc); // converte a saída percentual desejada para tempo
delay_ms(fase); // delay para disparo do triac na fase correta
output_high(pin_c0); // seta a saída de disparo do triac
delay_us(100); // largura do pulso de disparo do triac
output_low(pin_c0); // reseta a saída de disparo do triac
}

}

Com esse código ele fica dando pulsos aleatórios (para mim) e não no tempo que eu especifiquei. Também gera avisos de desligamento da interrupção para não causar reentrâncias. Li que teria de desabilitar o flag da interrupção depois de tratada, então acrescentei a seguinte linha:

#asm
BCF PIR1, CCP1IF ;
#endasm

mas o compilador não aceita e dá erro. Não reconhece o PIR1 e nem o CCP1IF.

O que fazer???
Ah, configurei as portas dessa forma:

/* No modo captura, a entrada CCP1 gerará uma interrupção toda vez que houver a borda de subida. Dessa forma será
possível efetuar o disparo do TRIAC no tempo desejado. */

setup_ccp1(CCP_CAPTURE_RE); // coloca a entrada CCP1 em modo de captura com sensibilidade na borda de subida
setup_timer_1(T1_INTERNAL); // habilita o timer 1 com clock interno
enable_interrupts(INT_CCP1); // habilita a interrupção de CCP1
enable_interrupts(GLOBAL); // habilita as interrupções selecionadas, no nosso caso a interrupção de CCP1

Desde já agradeço a ajuda.
Abraço,

MensagemEnviado: 14 Set 2009 08:04
por Sergio38br
bom dia, ja tentou ler o arquivo .h do micro no CCS, deve ter uma declaração ou union do tipo "CCP1IF.PIR1" ou algo parecido, vc pega o nome correto e faz igual a 0, ai vc limpa o flag.

[ ]'s
Sergio

MensagemEnviado: 14 Set 2009 08:22
por fabim
Sergim, por se tratar do CCiéca.
Um amigo aqui do forum me pediu um help, e o nome dos endereços "nome os quais conhecemos pelo datashit", não estavam coerentes com o header.
Pra não mecher com o header, basta ir no datasheet descobrir o endereço do nome conhecido, e no cabeçalho do source.

#define PIR1 0Xo_endereço_dele_para_o_ucontrolador

O restante o CCIÉCA se vira.

IÉCA TRAVEIZ.

Fabim

MensagemEnviado: 15 Set 2009 02:28
por Viana
Fabim, implementei, testei e funcionou beleza!!! Agora ele está resetando o bit, porém os avisos de desabilitar a interrupção continua e sempre que coloco o delay em ms ele não fixa os disparos.
Estou testando no proteus, coloco um gerador de sinal na entrada com osciloscópio e monitoro a saída. Quando faço o delay com o comando delay_ms, a saída fica pulsando doida. Quando eu faço o delay usando o delay_us, a saída fica paradinha onde eu quero. Usei o laço for com o comando delay_us e funcionou, mas ainda não entendi o porquê dessa intolerância, visto que uso o delay_ms em outra parte do programa e aparentemente não tenho problemas.

Mais uma vez, Obrigado.

Sds,

MensagemEnviado: 15 Set 2009 21:44
por andre_luis
Viana,

Não é uma boa prática colocar Delay em interrupções.
O main deve receber a prioridade do processamento, enquanto que as interrupções devem apenas acionar flags para serem tratados no main.

O mais aconselhável é que o tratamento da interrupção esteja fora do vetor de interrupção.

+++

MensagemEnviado: 15 Set 2009 23:44
por Viana
Valeu, André. Não sabia sobre essas boas práticas. A minha preocupação estava sendo em enviar o pulso de disparo no tempo correto, por isso coloquei toda a rotina de tratamento dentro da interrupção. Vou rever meus conceitos e tentar adequar a rotina...