Interrupção INT0

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Interrupção INT0

Mensagempor vtrx » 06 Fev 2013 23:00

Minha mente não está entendendo o porque de um comportamento em relação a uma interrupção.
Tenho uma rotina de PWM eficaz em ASM que se eu apenas testá-la num looping no programa,ela gera os sinais como o esperado,mas se eu colocá-la dentro de uma interrupção (INT0) na borda de subida de um detector zero cross (120HZ) a rotina fica totalmente fora do esperado.
Estou usando o Proteus para simular.
Seria assim,a cada transição de zero de uma tensão AC(110v)é disparado a rotina que gera as saidas no PORT A.
Se eu fizer apenas um teste,tipo,a interrupção é acionada,elevo RA0 a 1 e depois a 0, a cada interrupção,o sinal no osciloscopio corresponde corretamente,mas se usa a rotina dentro da interrupção,não funciona como o esperado.
Ja tentei usando C18 e ASM,pois achei que a interrupção em C não estava correta mas o resultado é o mesmo.
Segue exemplo no proteus.
A cor amarela é o sinal do detetor zero cross.
Vermelho é a rede AC 60 Hz.
Azul é o primeiro canal PWM.
Verde é o segundo canal PWM.
O exemplo em C é praticamente o mesmo,inclusive a rotina multipla de PWM está em ASM e é totalmente funcional se estiver em LOOPING no programa,eu ja usaei para 8 Leds com controle perfeito do brilho.
Se for descomentado as 4 primeiras linhas da rotina MULTI_PWM,voces poderão ver qual seria o resultado esperado.

Código: Selecionar todos
;
;
#INCLUDE <P18F2550.INC>
         
         CONFIG PLLDIV = 1         
            CONFIG CPUDIV = OSC1_PLL2   
         CONFIG USBDIV = 2         
         CONFIG FOSC =    XTPLL_XT   
         CONFIG FCMEN =    OFF         
         CONFIG IESO =    OFF         
         CONFIG PWRT =    OFF      
;................................................................................................................
   CBLOCK  0X000
         PWM0
      PWM1
      PWM2    
      PWM3
        PWM4
      PWM5
      PWM6
      PWM7
        PWM0_CNTR
      PWM1_CNTR
      PWM2_CNTR
      PWM3_CNTR
        PWM4_CNTR
      PWM5_CNTR
      PWM6_CNTR
      PWM7_CNTR
      ESTADO_PWM2
      SOBE_BORDA
   ENDC

   #DEFINE      POINTER1         .2
;........................................................
    ORG 0             
     GOTO START       
 ;-------------------------------
    ORG 0X08             ;ALTA PRIORIDADE
   BTFSS   INTCON,1
    RETFIE   
   BCF      INTCON,1
     GOTO   MULTI_PWM             ;SALTA PARA A FUNCAO DE INTERRUPCAO
   GOTO   $

    ORG 0X18            ;BAIXA PRIORIDADE          
     GOTO $            
 ;-------------------------------
START:                
      CLRF    PORTB       
      MOVLW    B'11000001'      
     MOVWF    TRISB       
   MOVLW   0X00
   MOVWF   TRISA
   MOVLW   .1
   MOVWF   PWM0
   MOVLW   0X01
   MOVWF   PWM1
   MOVLW   0X01
   MOVWF   PWM2
   MOVLW   0X01
   MOVWF   PWM3
   MOVLW   0X01
   MOVWF   PWM4
   MOVLW   0X01
   MOVWF   PWM5
   MOVLW   0X01
   MOVWF   PWM6
   MOVLW   0X01
   MOVWF   PWM6
   MOVLW   POINTER1
   MOVWF   SOBE_BORDA
   MOVLW   0X0F
   MOVWF    ADCON1
   MOVLW   0X06
   MOVWF   CMCON

   BCF      INTCON,INT0IF
   BSF      INTCON,INT0IE
   BSF      INTCON2,INTEDG0
   BSF      RCON,IPEN
   BSF      INTCON,GIE
;   BCF      INTCON,GIE
XP:
   BTFSC   PORTB,7
   BRA      XP
   INCF   PWM0,F
XP2:
   BTFSS   PORTB,7
   BRA      XP2
   GOTO   XP
;.................................................
MULTI_PWM:   
;      BSF      PORTA,0
;      NOP
;      BCF      PORTA,0
;      RETFIE
;.................................................
        DECFSZ  SOBE_BORDA,1,BANKED 
        BRA      PWM_ATUALIZA2   
      MOVLW   POINTER1
      MOVWF   SOBE_BORDA,BANKED                 
      MOVFF   PWM0,PWM0_CNTR
      MOVFF   PWM1,PWM1_CNTR
      MOVFF   PWM2,PWM2_CNTR
      MOVFF   PWM3,PWM3_CNTR   
      MOVFF   PWM4,PWM4_CNTR
      MOVFF   PWM5,PWM5_CNTR
      MOVFF   PWM6,PWM6_CNTR
      MOVFF   PWM7,PWM7_CNTR 
        MOVLW   0XFF       
        GOTO    PWM_FIM2       
PWM_ATUALIZA2:
        MOVLW   0x00             
        DECFSZ  PWM0_CNTR,1,BANKED   
         IORLW  B'00000001'   
        DECFSZ  PWM1_CNTR,1,BANKED     
         IORLW  B'00000010'     
        DECFSZ  PWM2_CNTR,1,BANKED   
         IORLW  B'00000100'     
        DECFSZ  PWM3_CNTR,1,BANKED     
         IORLW  B'00001000'     
        DECFSZ  PWM4_CNTR,1,BANKED     
         IORLW  B'00010000'     
        DECFSZ  PWM5_CNTR,1,BANKED     
         IORLW  B'00100000'     
        DECFSZ  PWM6_CNTR,1,BANKED     
         IORLW  B'01000000'     
        DECFSZ  PWM7_CNTR,1,BANKED     
         IORLW  B'10000000' 
        ANDWF   ESTADO_PWM2,0,BANKED                                   
PWM_FIM2:                       
        MOVWF   PORTA, ACCESS            
        MOVWF   ESTADO_PWM2,BANKED       
       RETFIE  FAST
;...........................................
 END


http://www.4shared.com/rar/pwWssG_s/PWM_8.html
Gostaria muito de entender onde estou errando...
PS:Quero ressaltar que o problema não é na rotina que gera o PWM,a mesno que exista uma rotina de multiplo PWM mais eficaz,oque eu acho pouco provável.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor ze » 07 Fev 2013 06:51

oi
-poste o fonte noutra linguagem + universal
-poste o circuito num hospedeiro de imagem. (preguiça de clicar)
-explique o que extamanente tem que acontecer. é um dimmer?
-compartilhe o .dsn, .hex, .scambal
...xute
-a interupt: desabilite no começo e reabilite no fim dentro da rotina de interrupt
abç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor vtrx » 07 Fev 2013 08:34

Agora estou no trampo mas se voce tiver o MPLAB,apenas rode o exemplo que esta no 4shared,depois 'descomente' as 3 primeiras linhas da rotina (;),compile denovo e rode,assom voce verá como deveria ser a saida,e ela é se estiver num loopin no programa,tipo;
while(1){MULTI_PWM:;}
Seria tipo um DIMMER sim mas de 8 canais sincronizado com a rede.
Para um canal funciona perfeito(disperdício usar um microcontrolador para um canal...).
J tentei habilitar a interripção depois da rotina executada mas se fizer isso o sinal PWM fica 'desincronizado' com a rede.
A unica observação é que estou usando o proteis antes de qeuimas tudo...
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 07 Fev 2013 11:29

Segue código em C18 e link com projetos no Proteus em ASM e C18(assim qualquer um pode ajudar).
Código: Selecionar todos
#include<P18F2550.H>
#include <delays.h>

#pragma config PLLDIV=1, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=XTPLL_XT//, FCMEM=OFF //CPUDIV=OSC1_PLL2=48MHz
#pragma config IESO=OFF, PWRT=OFF, BOR=ON_ACTIVE, BORV=3, VREGEN=ON, WDT=OFF
#pragma config MCLRE=ON, PBADEN=OFF, CCP2MX=OFF, STVREN=ON, LVP=ON, XINST=OFF, DEBUG=OFF
#define   PW_Ini  0x06
//......................................................
void Multi_PWM(void);
//......................................................
#pragma udata
volatile unsigned char         
         PWM0,PWM1,PWM2,PWM3,
        PWM4,PWM5,PWM6,PWM7,
        PWM0_CNTR,PWM1_CNTR,PWM2_CNTR,PWM3_CNTR,
        PWM4_CNTR,PWM5_CNTR,PWM6_CNTR,PWM7_CNTR,
        AUXILIAR,ESTADO_PWM;
//#pragma udata
volatile  unsigned char  LARGURA_PULSO;

void PWM_isr (void);
#pragma code high_vector=0x08   //ALTA PRIORIDADE
void high_interrupt (void)
{
_asm GOTO PWM_isr _endasm
}

#pragma code
#pragma interrupt PWM_isr
void PWM_isr (void)
{
unsigned int i;
  if(INTCONbits.INT0IF)
   {
   INTCONbits.INT0IF = 0;   
   Multi_PWM();
   }
}
//------------------------------------------------------------
void Multi_PWM(void)
 {
   LARGURA_PULSO--;
if (LARGURA_PULSO == 0)
 {
   PWM0_CNTR = PWM0;   
   PWM1_CNTR = PWM1;
   PWM2_CNTR = PWM2;   
   PWM3_CNTR = PWM3;
   PWM4_CNTR = PWM4;   
   PWM5_CNTR = PWM5;
   PWM6_CNTR = PWM6;   
   PWM7_CNTR = PWM7;
   LARGURA_PULSO = PW_Ini;
   ESTADO_PWM = 0xFF;
   PORTA = ESTADO_PWM ;
 }
else
   {
   AUXILIAR = 0;
   PWM0_CNTR--;
if (PWM0_CNTR == 0){PWM1_CNTR--;}
 else
    {
    AUXILIAR |= 0b00000001 ;
    PWM1_CNTR--;
    }
if (PWM1_CNTR == 0){PWM2_CNTR--;}
 else
   {
    AUXILIAR |= 0b00000010 ;
    PWM2_CNTR--;
    }   
if (PWM2_CNTR == 0)   {PWM3_CNTR--;}
 else
   {
    AUXILIAR |= 0b00000100 ;
    PWM3_CNTR--;
    }
if (PWM3_CNTR == 0)   {PWM4_CNTR--;}
 else
   {
    AUXILIAR |= 0b00001000 ;
    PWM4_CNTR--;
   }
if (PWM4_CNTR == 0)   {PWM5_CNTR--;}
 else
   {
    AUXILIAR |= 0b00010000 ;
    PWM5_CNTR--;
   }
if (PWM5_CNTR == 0){PWM6_CNTR--;}
 else
   {
    AUXILIAR |= 0b00100000 ;
    PWM6_CNTR--;
   }
if (PWM6_CNTR == 0){PWM7_CNTR--;}
 else
   {
    AUXILIAR |= 0b01000000 ;
    PWM7_CNTR--;
   }
if (PWM7_CNTR == 0)
   {
    AUXILIAR &=  ESTADO_PWM;
    PORTA = AUXILIAR;
    ESTADO_PWM = AUXILIAR;
   }
 else
   {
   AUXILIAR |= 0b10000000;
   AUXILIAR &= ESTADO_PWM;
   PORTA = AUXILIAR;
   ESTADO_PWM = AUXILIAR;
   }
 }
}
//----------------------------------------------------

void main(){
   ADCON1 = 0x0F;     
   CMCON =  0X07;
   TRISA =  0x00;         
   TRISB = 0b11000001;
   PORTA = 0X00;
//      PORTB = 0b01111101;
   PWM0 = 0x05;
   PWM1 = 1;
   PWM2 = 1;
   PWM3 = 1;
   PWM4 = 1;
   PWM5 = 1;
   PWM6 = 1;
   PWM7 = 1;
   LARGURA_PULSO = PW_Ini;
//---- PARA DESABILITAR A INT,COMENTAR ATÉ '   INTCONbits.GIE = 1'///
    RCONbits.IPEN = 1;               
   INTCONbits.INT0IF = 0;
   INTCONbits.INT0IE = 1;
   INTCON2bits.INTEDG0 = 1;
   RCONbits.IPEN = 1;
    INTCONbits.GIE = 1;         //HABILITA AS INTERRUPÇÕES
             
//    INTCONbits.GIE = 0;      //DESABILITA AS INTERRUPÇÕES   
             
//.....................................................................
   while(1){
//   Multi_PWM();
//   Delay100TCYx(20);

         }
}


http://www.4shared.com/rar/pwWssG_s/PWM_8.html

Desabilitem a interrupção e descomentem o Loop no final do código para ver a diferença.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor ze » 07 Fev 2013 11:56

baixei o projeto do teu 1º post. meio zoneadinho. tendi paul newman. mas isso é normal. só o pai entende bem o filho.

tipo.. sei lá... veja como vislumbro um multipwm minimalista:
se fizer questão de usar a interrupção do pino. Também pode estar no loop principal sincronizado com a rede
Código: Selecionar todos
void interrupt(void) //só pra zerar o timer
{
TIMER1=0;
}

e no main
Código: Selecionar todos
void main(void)
{
for(;;)
{
if (dc0>TIMER1) {RB0=1;asm("nop");RB0=0;}; else RB0=0;
...
if (dc7>TIMER1) {RB7=1;asm("nop");RB7=0;}; else RB7=0;
}
}
claro, antes acertar os valores da contagem/freq do TIMER1 de acordo com os herts da rede, achar uma maneira de acertar as variáveis dcx por um teclado p.ex., etc.
nem sei se dá certo. quiçá provavelmente talvez não ou ao contrário. talvez possa simplifcar ainda +. a qualquer momento faço um teste no proteus pra ver. ou não.

Coincidentemente to fazendo algo semelhantíssimo mas não é pra disparar no zero mas qdo atingir 8V e parar no 0. Pra isso uso 5 canais ad e 5 pinos pros gates de 5 mosfets 100A. Nada + é do que um comparador com histerese. Ok no proteus, Ok no protoboard mas na placa padrão...

abç. voar muçá.
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor vtrx » 08 Fev 2013 20:54

Conseguí oque queria pelo menos com 2 canais.
Segue link com projeto Proteus e C18.
Rotina de saida PWM em ASM pelo PORT A.
RA0 é o canal 1 e RA1 o canal 2.
4 botões para testar cada canal que esta(segundo o Proteus)sincronizado com a fase da rede AC/110v tanto na fase positiva como na fase negativa da tensão AC.
Falta aumentar a resolução para diminuir os passos.
O código ficou meio grande mas isso não importa para mim,o PIC que se vire...
Vou montar um Layout com os Triacs para ver se fica como eu quero que é controlar cada canal acendendo uma lampada incandecente desde seu filamento mínimo até brilho máximo linearmente,depois passo para ser controlado pelo USB no PC.
http://www.4shared.com/rar/wHwbbYLU/Pwm_C18.html

Se alguem souber um meio melhor de setar/zerar um BIT numa variável no C18 sem que o compilador encha a tela de 'Warnings' me avise,só achei o método que está no código.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor ze » 09 Fev 2013 18:24

main unexceptional warning: missing magic words. potential helper-- good luck
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor vtrx » 09 Fev 2013 20:41

Ja estou na fase 'que bosta,pensei que ia mais lonje...'.
Reescreví o código em ASM,ASM/C18 e C18 puro ,para conseguir o código de menor tamanho possível.
Analisando o ASM gerado pelo C18,fiz alterações na rotina que gera os sinais pela PORta e a que analisa qual canal modificar,e cheguei ao tamanho total do programa,em C18 puro,a 24219 byte de programa,sobrando 8549 bytes usando 8 canais.
Falta a parte do USB que não sei se vai caber,mas deve caber pois é em média 5k de programação para usar USB plenamente.
Agora é realmente montar um protótipo para ver como vai reagir o brilho nas lampadas.
Para o código não ficar maior,por enquanto o controle dos canais vai de 0 a 31 (31 máximo brilho).
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 10 Fev 2013 11:44

Agora voltei a fase 'yes,we can'.
Analisando com calma os algorítimos mantive,por enquanto,os passos de 0 a 31 ,mas reescrví novamente a rotina de atualização(que era a que gerava o maior código) e cheguei ao total do programa de 24219 bytes para atualmente a 4509 bytes...
Depois de testar um Hardware 'real',se alguem tiver curiosidade,postarei o projeto teste.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor andre_luis » 10 Fev 2013 16:48

Código: Selecionar todos
void high_interrupt (void)
{
_asm GOTO PWM_isr _endasm
}


Posso estar enganado, mas a utilização de diretivas de chamadas em Assembly no C não me parece ser uma prática adequada, uma vez que o C dispoe de todos os recursos necessários.
O ideal é focalizar a programação em uma única linguagem de programação.


Outra coisa, é que em C, a utilização do GOTO é considerado como uma quebra na estrutuda do programa, sendo recomendado tentar utilizar o CALL em seu lugar.


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor vtrx » 10 Fev 2013 17:48

André,esqueça a linguagem C pura para micros.

Outro detalhe,essa implementação é padrão C18 da Microchip ,assim eu não preciso escrever a rotina começando no endereço 0x08 e subscrevendo os outros endereços,usando GOTO eu salto para a rotina e gasto menos instruções pois CALL exige mais pilha e me faz retornar de onde chamei forçando uma parada.
Linguagem C para micros não segue regras a não ser que esteja usando biblioteca padrão ,tipo, STDLIB.
A instrução GOTO tem que saber usar,se não souber não use.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 14 Fev 2013 22:29

ja estou quase no limite doque um PIC a 48 MHZ pode fazer entre duas passagens de zero de uma senoide a 60HZ.
Agora ficou 32 canais PWM independente,usando 4 CIs 74HC595,com passos de 0 a 62 (62 = Máximo) e código total incluindo framework USB HID com 13742 bytes.
Os 74HC595 deixaram a rotina de atualização 8 x mais lenta para cada byte,fazendo o tempo que tenho dentro da interrupção por passagem por zero limitada.
Ainda falta a parte prática($)...
O soft está praticamente terminado,envia uma amostra em tempo real de 255 frequencias retiradas em tempo real de uma sequencia de músicas e delas escolho as 32 mais 'interessantes' para serem representadas por lampadas spot.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 27 Fev 2013 18:42

Ja está montado a placa teste com o primeiro e ultimo canal(1 a 32)para teste prático.
Tudo OK como esperado.
Estou preparando um vídeo com o circuito ja funcionando recebendo bytes de áudio pela USB e controlando duas lampadas PAR 30.
Próxima fase será montar os 32 canais e suas lampadas.
OBS:Todo o circuito menos a parte dos TRIACS,que o proteus não simula como deveria,foram testados e calibrados 'virtualmente' no Proteus e depois montado na prática.
O Proteus realmente é confiável,desde que a simulação não chegue a 100% de uso da CPU,em termos de leitura de seu frequencímetro e osciloscópio.
Tudo oque ocorria na tela do osciloscópio no Proteus,era oque realmente estava acontecendo.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 06 Mar 2013 20:37

Fiz um videozinho só para ter noção do resultado.
http://www.youtube.com/watch?v=i-urCR63vtE&feature=youtu.be
Na próxima vez deve estar com todas as lampadas.
Algumas observações;
O circuito final ficou com um PIC 18F2550 e dois 74HS595.
O programa suporta 16 canais com 150 passos por canal,não foi possível com apenas um PIC(48 MHZ/32K) e meu algorítimo controlarem 32 canais de uma vez sem sacrificar o USB.
O tamanho do programa ficou em 4818 bytes.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor vtrx » 08 Mar 2013 20:36

Estou postando um detetor zerocross super simples e totalmente funcional com 110 ou 220 v,que foi usado no circuito:
Imagem

Foi usado como Drvier dos FETs o MOC 3011 que é sem zero-cross.
Um detalhe foi que para efeito com lampadas de filamento,o efeito é melhor disparando o TRIAc por pulsos na fase,equanto que para cargas tipo motores o melhor foi por largura de pulso.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01


Voltar para PIC

Quem está online

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

x