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 |
\