Interrupt On Change op een 16F628A

PIC uit slaap laten ontwaken na SLEEP instructie

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 PORTB.7 ... PORTB.4.

 


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 PORTA.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 een PORTB.7 ... PORTB.4 ingang van niveau worden veranderd (van hoog naar laag of van laag naar hoog).
Als een PORTB 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).

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

DEVICE 16F628A                ;Gebruik een 16F628A (of 16F648A) 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)
       LVP_OFF,_              ;Low Voltage Programming uitgeschakeld
       MCLRE_OFF              ;Master CLeaR Enable uitgeschakeld (resetpin PORTA.5 op OFF)
ALL_DIGITAL TRUE              ;Alle ingangen digitaal (voor de toetsen)

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

;Registernamen (zie voor info hierover de datasheet van de 16F628A, kijk bij INTCON)
SYMBOL RBIF         = INTCON.0;Bit 0 van INTerrupt CONtrol register heet: RB Interrupt Flag
SYMBOL RBIE         = INTCON.3;Bit 3 van INTCON register heet: RB change Interrupt Enable
SYMBOL GIE          = INTCON.7;Bit 7 van INTCON register heet: Global Interrupt Enable

;Poortnamen
SYMBOL LED          = PORTA.1 ;Controlesignaal, continu HOOG zolang PIC actief is 
SYMBOL WordtWakker1 = PORTB.4 ;Ingang die de PIC wekt door Interrupt On Change 
SYMBOL WordtWakker2 = PORTB.5 ;Ingang die de PIC wekt door Interrupt On Change 
SYMBOL WordtWakker3 = PORTB.6 ;Ingang die de PIC wekt door Interrupt On Change 
SYMBOL WordtWakker4 = PORTB.7 ;Ingang die de PIC wekt door Interrupt On Change 

;Variabele declareren
DIM BD1             AS BYTE   ;Byte Dummy 1

;         76543210
PORTA  = %00000000            ;Alle uitgangen PORTA bij opstart een laag niveau
TRISA  = %11111101            ;PORTA.1 is uitgang voor LED
GIE    = 0                    ;Global Interrupt Enable uitschakelen(!)
RBIE   = 1                    ;Register portB 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  = PORTB                ;Lees "This wil end the mismatch condition" in de datasheet
  RBIF = 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 PORTB.7 ... PORTB.4 ingang van de 16F628A, 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) 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 RBPU bit (= OPTION_REG.7) op '0' in te stellen.
De pull-up weerstanden inschakelen kan in PIC Basic ook door eenvoudig PORTB_PULLUPS ON ergens bovenin het programma te plaatsen.
Het individueel (onafhankelijk van elkaar) instellen van PORTB pull-ups is niet mogelijk op een 16F628A.
Is een PORTB poort als uitgang ingesteld, dan wordt de pull-up weerstand van de betreffende poort hardwarematig uitgeschakeld.

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 PORTB.7 ... PORTB.4 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 16F628A.
 

Het interrupt waar het in dit artikel om draait is het RB port change type.
Deze kunnen we enablen (inschakelen) door van het INTCON register het RBIE 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 RBIF 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 gaat alleen over het ontwaken van de PIC, dus interesseert ons de stand van dit bit helemaal niet.
Wél belangrijk te weten is dat het RBIF 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 PORTB poort te lezen (de ingelezen waarde is niet interessant, dus schrijf maar naar een dummy variabele), en vervolgens het RBIF bit op '0' te zetten door CLEAR RBIF of door RBIF = 0 (zie programma voorbeeld).


Bij de 16F628A is het niet mogelijk om poorten afzonderlijk te kiezen welke de IOC interrupt hebben en welke niet.
Het is alleen mogelijk op PORTB.7 t/m PORTB.4 en dan óf alle vier mét IOC, óf alle vier zónder IOC.
De IOC op de vier bovenste PORTB poorten kan bijvoorbeeld worden gebruikt voor een matrix toetsenbord om de PIC te laten ontwaken bij een willekeurige toetsindruk.
Ook mogelijk is om met ingeschakeld IOC een deel er van als uitgang te gebruiken.
Sommige PIC types hebben een speciaal IOC register om zelf te bepalen welke poorten deze functie krijgt toegewezen (zoals 12F675).

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 (onnauwkeurige) interne oscillator loopt.
2. Bovenstaande beschrijving geldt ook voor een 16F627A en 16F648A.
 

Interrupt On Change voorbeeld met een 12F675
Het watersensor project maakt gebruik van interrupt on change en een 12F629

 

\