Interrupt On Change op een 12F675

PIC uit slaap laten ontwaken door vooraf opgegeven poort(en)

Alle PIC types hebben de mogelijkheid om in slaap te worden gebracht, waardoor ze nog maar enkele micro ampères (of nog minder, afhankelijk van diverse instellingen) aan stroom opnemen (= low power), ideaal voor batterij gevoede projecten.
De instructie hiervoor is SLEEP welke de PIC in een low power mode brengt.
SLEEP laat de PIC slapen maar behoud hierbij zijn geheugen, dus instellingen en niveaus van poorten, variabelen en registers blijven behouden.


Met onderstaand programmavoorbeeld kan de PIC
gewekt worden met GPIO.4 of GPIO.0.

 


PIC Basic Interrupt On Change testprogramma
Met onderstaand programmavoorbeeld zal de LED 2× knipperen (door de FOR ... NEXT lus) ten teken dat de PIC van voren af aan is opgestart (door inschakelen van de voeding).
Daarna wordt GPIO.1 vlak voor de SLEEP instructie laag gemaakt waardoor de LED uit zal gaan ten teken dat de PIC slaapt.

Om de PIC weer te ontwaken moet (in dit voorbeeld) ingang GPIO.0 of ingang GPIO.4 van niveau worden veranderd (van hoog naar laag of van laag naar hoog).
Als een GPIO poort op niets is aangesloten dan heeft de pin een hoog niveau vanwege de ingeschakelde interne pull-up weerstanden, dus moet de PIC (in dit geval) gewekt worden met een laag signaal.

Hierna zal de LED twee seconden oplichten en daarna weer doven ten teken dat de PIC weer in slaap is gebracht (vanwege de oneindige WHILE ... WEND lus).

;                PIC12F675:           +--v--+                                         
;                                +5V >[     ]< GND                                    
;                               vrij<>[     ]< PIC is wakker te maken met deze pin
;PIC is wakker te maken met deze pin >[     ]> Controle of PIC wakker is (door b.v. een LED)
;                           Vpp/vrij >[     ]<>vrij
;                                     +-----+                                         

DEVICE 12F675                 ;Gebruik een 12F675 (of 12F629) type
CONFIG INTRC_OSC_NOCLKOUT,_   ;INTerne RC OSCillator van de PIC gebruiken
       WDT_OFF,_              ;Watch Dog Timer uitgeschakeld
       PWRTE_ON,_             ;PoWeR up Timer Enable ingeschakeld
       BODEN_OFF,_            ;Brown Out Detection ENable uitgeschakeld (minder stroomopname)
       MCLRE_OFF              ;Master CLeaR Enable uitgeschakeld (resetpin GPIO.3 op OFF)
ALL_DIGITAL TRUE              ;Alle ingangen digitaal (voor de toetsen)
'SET_OSCCAL                   ;Plaats calibratie (fabrieks)waarde in het OSCCAL register

;Logische constanten
SYMBOL OFF          = 0       ;UIT 
SYMBOL ON           = 1       ;AAN 

;Registernamen (zie voor info hierover de datasheet van de 12F629 / 675, kijk bij INTCON)
SYMBOL GPIF         = INTCON.0;Bit 0 van INTerrupt CONtrol register heet: GP Interrupt Flag
SYMBOL GPIE         = INTCON.3;Bit 3 van INTCON register heet: GPIO Port Interrupt Enable
SYMBOL GIE          = INTCON.7;Bit 7 van INTCON register heet: Global Interrupt Enable

;Poortnamen
SYMBOL WordtWakker1 = GPIO.0  ;Ingang die de PIC wekt door Interrupt On Change 
SYMBOL LED          = GPIO.1  ;Controlesignaal, continu HOOG zolang PIC actief is 
SYMBOL WordtWakker2 = GPIO.4  ;Ingang die de PIC wekt door Interrupt On Change 

;Variabele declareren
DIM BD1             AS BYTE   ;Byte Dummy 1

;         76543210
GPIO   = %00000000            ;Alle uitgangen bij opstart een laag niveau
TRISIO = %11111101            ;GPIO.1 is uitgang voor LED
IOC    = %00010001            ;Interrupt On Change voor GPIO.4 en GPIO.0 inschakelen
GIE    = 0                    ;Global Interrupt Enable uitschakelen(!)
GPIE   = 1                    ;GPIO Port change Interrupt Enable inschakelen
 
PORTB_PULLUPS ON              ;Pullup weerstanden actief (voor schakelaars en open pinnen)
CLEAR                         ;Wis alle RAM geheugen 


;Hoofdprogramma
FOR BD1 = 1 TO 3              ;LED aan-uit-aan (controle LED dat PIC vanaf begin start)
  LED = ~LED                  ;Toggle de LED
  DELAYMS 300                 ;Knippersnelheid van de LED
NEXT

WHILE 1 = 1                   ;Oneindige lus 
  LED  = OFF                  ;LED uitzetten (controle dat PIC slaapt)
  BD1  = GPIO                 ;Lees "This wil end the mismatch condition" in de datasheet
  GPIF = 0                    ;Dit bit moet steeds door het programma zelf op 0 worden gezet
  SLEEP                       ;Breng de PIC in low power mode (PIC laten slapen)
  LED  = ON                   ;LED aanzetten (controle dat PIC wakker is)

  DELAYMS 2000                ;PIC zal 2 seconden wakker zijn, daarna via WEND weer slapen
WEND                          ;Terug naar WHILE waar de PIC weer in slaap wordt gebracht

 


Ontwaken van de PIC vanuit SLEEP met de Interrupt On Change methode
Het laten ontwaken van de PIC door een gebeurtenis van buitenaf kan op een paar verschillende manieren.
De Interrupt On Change (= Interrupt bij veranderde toestand) is een manier die de PIC laat ontwaken door een verandering van niveau op een poortingang van de 12F675, of dit nu van een laag naar hoog of van een hoog naar laag verandering is maakt hierbij niet uit.
Hiervoor moeten er een paar bits van het INTCON register (= Interrupt Control) en het IOC register (= Interrupt OChange) worden ingesteld.

Eén van de eerste dingen die niet moet worden vergeten is om de interne pull-up weerstanden in te schakelen.
Als dit namelijk niet wordt gedaan dan zullen pinnen die geen verbinding hebben steeds een interrupt veroorzaken omdat deze een zwevend niveau hebben waardoor dit de ene keer als hoog en dan weer als laag zal worden gezien.
De PIC zou hierdoor continu gewekt worden.
Het instellen van de pull-up weerstanden kan door rechtstreeks van het OPTION_REG register het GPPU bit (= OPTION_REG.7) op '0' in te stellen en met het WPU register een keus te maken van welke poorten de pull-up moet worden ingeschakeld.
Alle pull-up weerstanden tegelijk inschakelen kan in PIC Basic eenvoudig met PORTB_PULLUPS ON (in PICBasic mag i.p.v. GPIO ook de naam PORTB worden gebruikt).
Let op: GPIO.3 heeft geen interne pull-up weerstand, dus die moet zelf geplaatst worden als deze poort gebruikt wordt (bijv. 33k).

Hoewel we hier een interrupt instellen, zijn we niet geïnteresseerd in het starten van een interrupt handler.
Daarom moeten de global interrupts uitgeschakeld worden, anders springt de PIC steeds naar een interrupt handler bij een verandering van niveau op een GPIO poort.
Uitschakelen van de global interrupts kan door van het INTCON register het GIE bit (= INTCON.7) op '0' te zetten.


Fragment uit de datasheet van de 12F675.
 

Het interrupt waar het in dit artikel om draait is het GPIO port change type.
Deze kunnen we enablen (inschakelen) door van het INTCON register het GPIE bit (= INTCON.3) op '1' te zetten.
Het enige wat dit type interrupt doet is de PIC wakker maken en tevens van het INTCON register het GPIF bit (= INTCON.0) op '1' zetten.
Als je met global interrupts werkt, kun je aan dit bit zien of het de oorzaak was van het IOC interrupt, maar dit artikel dat alleen gaat over het ontwaken van de PIC, interesseert ons de stand van dit bit helemaal niet.
Wél belangrijk te weten is dat het GPIF bit nooit door de PIC hardware zelf terug op '0' wordt gezet, dus dat moet softwarematig (door je PIC Basic programma) gebeuren.
Dit doe je door steeds vlak voor een SLEEP instructie eerst even de GPIO poort te lezen (de ingelezen waarde is niet interessant, dus schrijf maar naar een dummy variabele), en vervolgens het GPIF bit op '0' te zetten door CLEAR GPIF of door GPIF = 0 (zie programma voorbeeld).


Tot slot moet nog bepaald worden welke poorten een interrupt mogen geven.
In tegenstelling tot bijvoorbeeld de 16F628A is het bij de 12F675 mogelijk om zelf te bepalen wélke poorten een interrupt mogen geven en welke niet.
Dit kun je bij de 12F675 met het IOC register instellen (de 16F628A heeft dan ook geen IOC register).
Zie het bovenstaand PIC Basic programma, waar als voorbeeld GPIO.0 en GPIO.4 zijn ingesteld.
Experimenteer door zelf andere poorten in te stellen in het IOC register en dit uit te proberen (denk aan de externe pull-up 33k weerstand voor GPIO.3).


Bit 7 en bit 6 zijn natuurlijk niet in te stellen.
De 8 pins PIC heeft immers maar 6 I/O poorten (GPIO.5 t/m GPIO.0).

 

Volgens de datasheet van de 12F629/12F675 moet GIE aan staan, maar als je verder geen interrupts gebruikt moet GIE uitgeschakeld zijn.
Of bedoelen ze misschien GPIE aan?
Hoe dan ook, als je IOC alleen gebruikt om de PIC te laten ontwaken (na een SLEEP instructie) en verder geen interrupts gebruikt, moet je GIE uitgeschakeld hebben (GIE = 0).
 

1. De voorbeeld tijd van 2 seconden kan afwijken omdat de PIC op zijn interne oscillator loopt (dit is te calibreren met het OSCCAL register).
2. Bovenstaande beschrijving geldt ook voor een 12F629.
 

Het watersensor project maakt gebruik van IOC en een 12F629
Interrupt On Change voorbeeld met een 16F628A