Jump to content
ELFORUM - Forumul electronistilor

Intrerupere INT PIC16F1824


Recommended Posts

Hi all!

Ma confrunt cu urmatoarea problema la un PIC16F1824 si anume intreruperea INT (acea care se produce la schimbarea starii pinului RA2) nu se produce.

Codul de initializare a PIC-ului este:

sub procedure initiere()
    SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
    OSCCON =  %11111111
    ANSELA  = %00000000   '  All I/O pins are configured as digital
    ANSELC  = %00000000
    CM1CON0 = %00000000   '  Disbale comparators
    CM2CON0 = %00000000   '  Disbale comparators
    TRISA  = %11111111   '  PORTA All Inputs, Except xxx
    TRISC  = %00000000   '  PORTC All Outputs
    WPUA   = %00111111   '  Pull-ups to be enabled
    APFCON0.SDOSEL = 0
    APFCON0.SSSEL = 1
    
    INTCON.GIE   = 1      '  Enables all unmasked interrupts
    INTCON.PEIE  = 0      '  Disables all peripheral interrupts
    INTCON.T0IE  = 1    '  Enables the TMR0 interrupt
    INTCON.INTE  = 0      '  Enables the RA2/INT external interrupt
    INTCON.IOCIE = 0      '  Disables the PORTA change interrupt
    INTCON.T0IF  = 0      '  TMR0 register did not overflow
    INTCON.INTF  = 0      '  The RA2/INT external interrupt did not occur
    INTCON.IOCIF = 0      '  None of the PORTA <5:0> pins have changed state


    OPTION_REG.WUE    = 0  '  PORTA pull-ups are enabled by individual port latch values
    OPTION_REG.INTEDG = 1  '  Interrupt on rising/falling edge of RA2/INT pin
    OPTION_REG.T0CS   = 0  '  set Timer0 clock source to internal
    OPTION_REG.T0SE   = 1  '  Increment on high-to-low transition on RA2/T0CKI pin
    OPTION_REG.PSA    = 0  '  asign prescaler to Timer 0
    OPTION_REG.PS2    = 1  '  asign prescaler value
    OPTION_REG.PS1    = 1  '  asign prescaler value
    OPTION_REG.PS0    = 1  '  asign prescaler value
    
end sub



sub procedure Interrupt() iv 0x0004 ics ICS_AUTO
    dp.0 = not dp.0
    INTCON.INTE = 0
    INTCON.T0IF = 0
end sub

main:
'   Main program
    initiere()
    while TRUE
           citire()
           prepare_to_show_hour(h1, h0, m1, m0, dp, al )
           afiseaza()
    wend
end.

Pentru INTCON.T0IE = 1   si   INTCON.INTE = 0  adica sa se produca evenimentul pt TMR0 totul e OK, programul functioneaza OK (dp isi schimba starea) deci programul e OK.

Problema este la combinatia INTCON.T0IE = 0   si   INTCON.INTE = 1 (adica la schimbarea starii lui RA2): dp nu-si schimba starea. Unde gresesc, sau ce nu am configutar OK?

Va multumesc!

Link to comment

Salut,

 

Fara a spune ca rezolv problema ta, vreau sa fac cateva mentiuni:

- cand faci initializarea hardware ordinea este asa:

1. oscilator

2. porturi

3. configurare alte periferice

4. configurare timere, intreruperi

5. la final faci enable la intreruperi si ma refer la bitul GIE

 

In cazul tau, faci enable la intreruperea externa chiar in intrerupere. Ai un motiv pentru aceasta? Pentru ca ar fi fezabil doar daca vrei sa faci un fel de chain de intreruperi, gen in cazul in care apare intreruperea timer, doar atunci faci enable la inreruperea externa si cand se intampla intreruperea externa executi ceva si apoi o dezactivezi. Oricum acest cod nu apare in ce ai postat asa ca presupun ca ai facut o greseala. Intreruperea externa o activezi in afara rutinei de intrrupere (ma refer la bitul INTE)

 

- rutina de intrerupere este una singura pentru toate intreruperile. Trebuie sa testezi in functia chemata de intreruperi care intrerupere a facut "call" la functia de intrerupere.

Nu stiu sintaxa Basic dar ceva de genul:

 

sub procedure Interrupt() iv 0x0004 ics ICS_AUTO
    // atentie C Code
    // daca modulul intrerupere externa este activat si daca tocmai a avut loc o intrerupere externa executa
    if (INTCON.INTE && INTCON.INTF){
   	// flagul pentru intr. ext trebuie facut zero manual
    	INTCON.INTF = 0
        // codul tau in caz ca ai intrerupere externa
    }
    // daca timer0 este activat si daca tocmai a avut loc o intrerupere generata de overflow al Timer0
    if (INTCON.T0IE && INTCON.T0IF){
    	// flagul pentru intreruperea data de TMR0 trebuie facut zero in mod manual
      	INTCON.T0IF = 0
        // codul tau cand ai intrerupere data de TMR0
    }
    // end C code

end sub

 

Nu am verificat secventa ta de initializare.

 

Edited by mars01
Link to comment
10 hours ago, mars01 said:

De fapt o dezactivai.

 

Ceea ce, de altfel, n-are nici un efect, pentru ca la intrarea in rutina de servire a intreruperii GIE e facut 0 automat:

 

Quote

The following events happen when an interrupt event

occurs while the GIE bit is set:

• Current prefetched instruction is flushed

• GIE bit is cleared

...

 

 

Link to comment
10 hours ago, Liviu M said:

 

Ceea ce, de altfel, n-are nici un efect, pentru ca la intrarea in rutina de servire a intreruperii GIE e facut 0 automat:

 

Salut Liviu,

ma bucur sa vad ca mai postezi pe aici :)

In ceea ce ai postat tu de fapt m-am corectat pentru afirmatia precedenta aceleia, in care am spus ca " faci enable la intreruperea externa chiar in intrerupere" ceea ce era incorect datorita faptului ca bitul INTE era sters si nu setat.

Bun addagio, totusi!

Edited by mars01
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines