czwartek, 19 stycznia 2017

Przerwania na przykładzie PIC24H (16 bitowce)



Podstawowe informacje o przerwaniach .....


Podstawowe rejestry do obsługi przerwań w mikrokontrolerach PIC o których powinniśmy mieć pojęcie bawiąc się nimi  to :
 
INTCON1: Interrupt Control Register 1 (Rejestr kontrolny)

W tym rejestrze interesuje nas tylko jeden bit oznaczony jako NSTDIS . Bit ten włącza lub wyłącza zagnieżdżenie przerwań. Jeśli korzystamy z priorytetów w przerwaniach to włączmy zagnieżdżenie.

Przykład :

INTCON1bits.NSTDIS = 0 ; /* włącz zagnieżdzenia przerwań */


INTCON2: Interrupt Control Register 2 (Rejestr kontrolny)

Ten rejestr dedykowany jest dla przerwań zewnętrznych INT0 – INT4. Ustawiamy w nim jakim zboczem jest przerwanie zewnętrzne wyzwalane. I w zasadzie tyle co powinniśmy o nim wiedzieć.

Przykład :

INTCON2bits.INT0EP = 0 ; /*zbocze narastające wyzwala przerwanie zewnętrzne INT0 */

IFSx (gdzie x od 0 do 4): Interrupt Flag Status Registers (Rejestr flagowy)

Każde przerwanie (zewnętrzne/wewnętrzne/od peryferiów) zgłasza swoje wystąpienie za pomocą ustawienia odpowiedniego bitu w rejestrze flkagowym IFSx. Jeśli na przykład Timer1 zgłosi przerwanie to w rejestrze IFS0 na bicie T1IF pojawi się stan logiczny „1”. Należy jednak pamiętać i jest to specyfika mikrokontrolerów PIC aby w funkcji obsługi wektora przerwania wyzerować bit flagi przyporządkowany do źródła przerwania. Czyli na przykład w przypadku Timer1 musimy ustawić w funkcji wektora obsługi przerwania T1IF = 0 ;. Przy inicjalizacji przerwania bit ten również należy wyzerować.

Przykład :

void __attribute__((interrupt, no_auto_psv))_T1Interrupt() /* tak wygląda funkcja przerwania dla Timer1. Uwaga na ilość dolnych _*/
{

/*kod użytkownika do obsługi przerwania*/

/* Clear Timer1 interrupt */
IFS0bits.T1IF = 0 ; /* (NazwaRejestru.nazwaBitu) zerowanie flagi dla Timer1.To zerowanie musi być koniecznie !!! */
/*lub inny prostszy zapis : _T1IF = 0 ;   (_nazwaBitu)*/

}


IECx (gdzie x od 0 do 4) : Interrupt Enable Control Registers (Rejestr typu Włacz/Wyłącz przerwania dla poszczególnych źródeł )

W AVR włączaliśmy globalnie przerwania a tutaj włączamy indywidualnie dla wybranego źródła.
W myśl zasady to czego nie używamy to niech śpi i nie marnuje prądu.
Posłużymy się znowu Timer1 czyli to będzie nasze źródło przerwania.
W tym przypadku musimy odszukać w odpowiednim rejestrze IECx bitu dla Timer1.
Znajdujemy w IEC0 bit T1IE:(Timer1 Interrupt Enable bit). Aby właczyć przerwanie od Timer1 musimy ustawić ten bit na „1”. Odpowiednio ustawienie bitu T1IE na „0” wyłączy nam przerwanie od Timer1.
Widzimy , że jest to proste jak budowa cepa, musimy tylko zapamiętać , że jak chcemy skorzystać z źródła , które zgłasza przerwanie musimy te źródło włączyć w rejestrze IECx.

Przyład :

IEC0bits.T1IE = 1 ; /* włącz przerwanie od Timer1.*/
/* lub inny prostszy zapis : _T1IE = 1 ; */


IPCx (gdzie x od 0 do 17): Interrupt Priority Control Registers (Rejestr do ustawiania priorytetów dla zgłaszanych przerwań)

Mamy do wyboru 7 poziomów priorytetów. Im wyższa cyferka tym wyższy priorytet.
Czyli 7 to najwyższy priorytet dla przerwania a 1 najniższy. Wartość 0 wyłącza priorytetowość. Dla przykładu posłużmy się znowu Timer1. Chcemy ustawić priorytet dla zgłaszanego przerwania od Timer1 na poziomie 4. Szukamy w rejestrach IPCx bitów przyporządkowanych Timer1, znajdujemy je w IPC0, trzy bity oznaczone jako T1IP.

Przykład  :

IPC0bits.T1IP = 0b100 ; /* ustaw priorytet na poziomie 4 dla przerwania od Timer1.*/

O co chodzi z tą całą priorytetowością :) Ano wyobraźmy sobie , że mamy dwa przerwania X i Y. X ma priorytet 4 a Y ma priorytet 5. Przerwanie X zostaje zgłoszone i wykonuje się akurat funkcja wektora przerwania, i wtedy pach przychodzi zgłoszenie przerwania Y o wyższym priorytecia. CPU zamraża na stosie funkcję wektora przerwania X i zajmuje się wektorem przerwania Y. Po obsłużeniu Y  wraca do obsługi wektora X.
Jeśli oba przerwania nie miałyby ustawionego priorytetu to pierw zostaje wykonane w sposób kompletny przerwanie , które pierwsze zgłosiło się a następnie kolejne.

I to w zasadzie wszystko co zgrubsza powinniśmy wiedzieć o ustawianiu przerwań w PIC.

Są jeszcze dwa rejestry o istnieniu których można wiedzieć i zajrzeć sobie w ich noty :

SR: CPU Status Register –  ustawiamy priorytety przerwań od CPU
CORCON: Core Control Register – współpracuje z rejestrem SR w zakresie zmiany zakresów poziomów priorytetów dla przerwań od CPU .W rejestrze tym wybieramy zakres 0-7 albo 8-15.


Link :
http://ww1.microchip.com/downloads/en/DeviceDoc/70304A.pdf

PIC24HJ128GP502 Interrupt Vectors

The table below specifies the interrupt vectors for these 16-bit devices.
IRQ# Primary Name Alternate Name Vector Function
N/A _OscillatorFail _AltOscillatorFail Oscillator Fail Trap Vector
N/A _AddressError _AltAddressError Address Error Trap Vector
N/A _StackError _AltStackError Stack Error Trap Vector
N/A _MathError _AltMathError Math Error Trap Vector
N/A _DMACError _AltDMACError DMAC Error Trap Vector
0 _INT0Interrupt _AltINT0Interrupt INT0 - External Interrupt 0
1 _IC1Interrupt _AltIC1Interrupt IC1 - Input Compare 1
2 _OC1Interrupt _AltOC1Interrupt OC1 - Output Compare 1
3 _T1Interrupt _AltT1Interrupt T1 - Timer1
4 _DMA0Interrupt _AltDMA0Interrupt DMA0 - DMA Channel 0
5 _IC2Interrupt _AltIC2Interrupt IC2 - Input Capture 2
6 _OC2Interrupt _AltOC2Interrupt OC2 - Output Compare 2
7 _T2Interrupt _AltT2Interrupt T2 - Timer2
8 _T3Interrupt _AltT3Interrupt T3 - Timer3
9 _SPI1ErrInterrupt _AltSPI1ErrInterrupt SPI1E - SPI1 Error
10 _SPI1Interrupt _AltSPI1Interrupt SPI1 - SPI1 Transfer Done
11 _U1RXInterrupt _AltU1RXInterrupt U1RX - UART1 Receiver
12 _U1TXInterrupt _AltU1TXInterrupt U1TX - UART1 Transmitter
13 _ADC1Interrupt _AltADC1Interrupt ADC1 - A/D Converter 1
14 _DMA1Interrupt _AltDMA1Interrupt DMA1 - DMA Channel 1
16 _SI2C1Interrupt _AltSI2C1Interrupt SI2C1 - I2C1 Slave Events
17 _MI2C1Interrupt _AltMI2C1Interrupt MI2C1 - I2C1 Master Events
18 _CMPInterrupt _AltCMPInterrupt CMP - Comparator Interrupt
19 _CNInterrupt _AltCNInterrupt Change Notification Interrupt
20 _INT1Interrupt _AltINT1Interrupt INT1 - External Interrupt 1
22 _IC7Interrupt _AltIC7Interrupt IC7 - Input Capture 7
23 _IC8Interrupt _AltIC8Interrupt IC8 - Input Capture 8
24 _DMA2Interrupt _AltDMA2Interrupt DMA2 - DMA Channel 2
25 _OC3Interrupt _AltOC3Interrupt OC3 - Output Compare 3
26 _OC4Interrupt _AltOC4Interrupt OC4 - Output Compare 4
27 _T4Interrupt _AltT4Interrupt T4 - Timer4
28 _T5Interrupt _AltT5Interrupt T5 - Timer5
29 _INT2Interrupt _AltINT2Interrupt INT2 - External Interrupt 2
30 _U2RXInterrupt _AltU2RXInterrupt U2RX - UART2 Receiver
31 _U2TXInterrupt _AltU2TXInterrupt U2TX - UART2 Transmitter
32 _SPI2ErrInterrupt _AltSPI2ErrInterrupt SPI2E - SPI2 Error
33 _SPI2Interrupt _AltSPI2Interrupt SPI2 - SPI2 Transfer Done
34 _C1RxRdyInterrupt _AltC1RxRdyInterrupt C1RX - ECAN1 Receive Data Ready
35 _C1Interrupt _AltC1Interrupt C1 - ECAN1 Event
36 _DMA3Interrupt _AltDMA3Interrupt DMA3 - DMA Channel 3
45 _PMPInterrupt _AltPMPInterrupt PMP - Parallel Master Port
46 _DMA4Interrupt _AltDMA4Interrupt DMA4 - DMA Channel 4
61 _DMA5Interrupt _AltDMA5Interrupt DMA5 - DMA Channel 5
62 _RTCCInterrupt _AltRTCCInterrupt RTCC - Real-Time Clock and Calendar
65 _U1ErrInterrupt _AltU1ErrInterrupt U1E - UART1 Error
66 _U2ErrInterrupt _AltU2ErrInterrupt U2E - UART2 Error
67 _CRCInterrupt _AltCRCInterrupt CRC - Cyclic Redunancy Check
68 _DMA6Interrupt _AltDMA6Interrupt DMA6 - DMA Channel 6
69 _DMA7Interrupt _AltDMA7Interrupt DMA7 - DMA Channel 7
70 _C1TxReqInterrupt _AltC1TxReqInterrupt C1TX - ECAN1 Transmit Data Request

Brak komentarzy:

Prześlij komentarz