Seriál - PIC16F84 - 22 - Přerušení
11. 12. 07 - 14:32. Napsal Jiří Chytil. Přečteno 6010x. Žádné komentáře
Ano, už je to tak, dostáváme se k očekávané kapitole, která se zabývá přerušeními. PIC16F84A má čtyři zdroje přerušení, a to Přerušení od č/č, přerušení z RB0, přerušení od zápisu do EEPROM a přerušení od RB4 ? RB7.
Ano, už je to tak, dostáváme se k očekávané kapitole, která se zabývá přerušeními. PIC16F84A má čtyři zdroje přerušení, a to Přerušení od č/č, přerušení z RB0, přerušení od zápisu do EEPROM a přerušení od RB4 ? RB7. A o ty se stará registr INTCON, opět osmibitový. A hned se podíváme na jeho složení.
- RBTF ? příznak přerušení od některého z bitů RB4 ? RB7. Pokud je nastaven (tedy je v logické jedničce), znamená to, že došlo ke změně na některém z bitů RB4 ? RB7. Pokud je vynulován nedošlo k žádosti o přerušení od RB4 ? RB7.
- INTF ? příznak přerušení na RB0. Platí to samé jako v předchozím případě. Tedy došlo-li k požadavku na přerušení od RB0, je nastaven, nedošlo-li k tomuto požadavku na přerušení, je vynulován.
- T0IF ? příznak přerušení od č/č, zde je situace stejná jako v předchozích dvou případech.
- RBIE ? v logické jedna povoluje přerušení na pinech RB4 ? RB7. V logické nule jsou tato přerušení zakázána.
- INTE ? v logické jedna povoluje přerušení na pinu RB0. V logické nule je toto přerušení zakázáno.
- T0IE ? v logické jedna povoluje přerušení od č/č. V logické nule je toto přerušení zakázáno.
- EEIE ? v logické jedna povoluje přerušení od dokončení zápisu do EEPROM. V logické nule je toto přerušení zakázáno.
- GIE ? V logické jedna povoluje všechna přerušení, která jsou povolena i maskou (maskami jsou bity RBIE, INTE, T0IE, EEIE). V logické nule zakazuje všechny přerušení.
Příznak, který jen nastaven při přerušení od dokončení zápis do EERPOM, najdete v registru EECON1 jako EEIF. Jako všude tak i zde pro orientaci uvedu výpis pro registr INTCON ze souboru PIC16F84A.INC.
;----- INTCON Bits -------------------------------------------------------- GIE EQU H'0007' EEIE EQU H'0006' T0IE EQU H'0005' INTE EQU H'0004' RBIE EQU H'0003' T0IF EQU H'0002' INTF EQU H'0001' RBIF EQU H'0000'
Zatím jsem se zde zmiňoval jen o jakém si registru a zdrojích přerušení, ale to není zase tak podstatné. Pro nás je teď nejdůležitější to, co ono přerušení umí a to, k čemu ho můžeme využívat. Takže mějme nějaký program, který se nerušeně v pohodě a v poklidu vykonává. Najedou ale vznikne potřeba tento běh programu nějak upravit nebo přerušit. Právě k tomu nám může soužit ono přerušení. Máme tedy nějaký hlavní běh programu a najednou se objeví požadavek na přerušení. Vykoná se poslední rozpracovaná instrukce, opustí se vykonávání hlavního programu a započne zpracování přerušení. Tomuto zpracování říkáme obsluha přerušení. A po obsloužení přerušení se program vrátím tam, kde skončil a ?jakoby nic? pokračuje dále tam, kde před přerušením skončil (tedy pokud není dáno jinak). Po té, co je vyvoláno nějakým způsobem přerušení, dojde k zakázání ostatních přerušení a to tak, že se vynuluje registr GIE. Uloží se adresa místa, na kterém bylo vykonáno přerušení (ta se ukládá proto aby zde program mohl znovu pokračovat). A vykonávaní programu se přesune na adresu 0004h. Ta je pro přerušení pevně vyhrazena. Nyní v případě, že máme povolených několik přerušení testujeme bity RBIF, INTF, EEIF a T0IF a zjišťujeme tak, ze kterého zdroje ono přerušení pochází a podle toho se vykoná programem (programátorem) určená činnost. Na závěr softwarově vymažeme příznaky přerušení, aby po dokončení obsluhy nenastalo přerušení nové, a celou obsluho přerušení ukončíme instrukcí RETFIE. Ta nastaví bit GIE. A vrátí vykonávání programu tam, kde skončilo právě kvůli přerušení. Návrat probíhá vrácením hodnoty z vrcholu zásobníku do PC (program counter). A nyní se podívejme na několik příkladů použití přerušení.
Je nutné zmínit se o jednom z problémů, který musíme při obsluze přerušení řešit je obsah registrů, především se jedná o pracovní registr W a registr STATUS. Ty je nutné před započetím obsluhy přerušení někam uložím a před jejím ukončením opět obnovit. K obnovení se z jistých důvodu nepoužívají jen instrukce MOV, ale je nutné použít také instrukce SWAPF (Instrukce SWAPF prohodí horní a dolní čtyři bity registru zdrojového cílového, pokud je registr zdrojový stejný jako registr cílový, přehodí se bity navzájem pouze v tomto registru. Důležité je, že instrukce SWAPF nemění jakkoliv registr STATUS).
V prvním případě se bude jednat o využití přerušení od změny Pinů RB4 a RB5. Na ně budou připojena tlačítka a stisky tlačítek bude zvyšována nebo snižována rychlost generovaného signálu. A abychom konečně vytvořili něco praktického, budeme tímto signálem řídit krokový motorek. A jeho změnou tedy měnit rychlost jeho otáčení. Signál pro řízení krokového motoru:
Základní:
Úprava signálu pro krokový motor (umožňuje zvýšit rychlost otáčení):
INCLUDE "P16F84A.INC" LIST P=16F84A, R=DEC __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;------------------------------------------------------------- speed EQU H'0C' c1 EQU H'0D' c2 EQU H'0E' ORG 0 ;přesun na vykonávání GOTO program ;programu ORG 4 ;vektor přerušení BCF INTCON,GIE ;zakázání všech přerušení BCF INTCON,RBIF ;smazání příznaku přerušení GOTO interupt ;skok na obsluhu přerušení program BSF STATUS,RP0 ;inicializace uP MOVLW b'11111111' MOVWF TRISB MOVLW b'00000000' MOVWF TRISA BCF STATUS,RP0 MOVLW b'10001000' ;nastavení registru INTCON MOVWF INTCON MOVLW 16 ;zadání základní rychlosti MOVWF speed motor BSF PORTA,0 ;hlavní program otáčející CALL hmoto ;motorem BCF PORTA,0 BSF PORTA,1 CALL wmoto BCF PORTA,1 BSF PORTA,2 CALL wmoto BCF PORTA,2 BSF PORTA,3 CALL wmoto BCF PORTA,3 GOTO motor wmoto MOVF speed,0 ;podprogram zpoždění MOVWF c2 wait2 MOVLW 50 MOVWF c1 wait1 DECFSZ c1,1 GOTO wait1 DECFSZ c2,1 GOTO wait2 RETURN interupt BTFSS PORTB,7 ;obsluha přerušení GOTO next INCF speed,1 ;snížení rychlosti next BTFSS PORTB,6 GOTO endint DECF speed,1 ;zvýšení rychlosti endint RETFIE
Kód není kompletní, je to jen ukázka principu přerušení. Tlačítka jsou zde proti zákmitů chráněna hardwarově. Program je schopen generovat i frekvence, které motor není schopen zvládnout, toto je třeba upravit na míru motoru. Proměnnou speed lze také ?protočit? dokola a to by v kvalitním programu určitě jít nemělo a také by bylo záhodno mít možnost měnit rychlost po větších skocích. Například podržením klávesy. A ne nelineární stupnic, jak je tomu v tomto případě. Důležité je při vzniku přerušení ostatní přerušení zakázat řádkem:
BCF INTCON,GIE
A hned jak je to možné mažeme i příznak přerušení. Zde to můžeme udělat hned, protože mám jen jediný zdroj přerušení, nemusíme tedy zajišťovat, od kterého zdroje pochází. To děláme řádkem následujícím tedy:
BCF INTCON,RBIF
Ve druhém případě se bude jednat o přerušení pocházející od č/č, který bude použit v režimu časovače a bude generovat dobu, po kterou bude znít námi tvořený zvolený tón. Tato metoda je poněkud jednodušší než přepočítávat délku trvání tónu z jeho periody.
INCLUDE "P16F84A.INC" LIST P=16F84A, R=DEC __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;------------------------------------------------------------- speed EQU H'0C' c1 EQU H'0D' c2 EQU H'0E' d1 EQU H'0F' d2 EQU H'11' e1 EQU H'12' e2 EQU H'13' f1 EQU H'14' f2 EQU H'15' g1 EQU H'16' g2 EQU H'17' a1 EQU H'18' a2 EQU H'19' h1 EQU H'1A' h2 EQU H'1B' exit EQU H'1C' ORG 0 GOTO program ORG 4 BCF INTCON,GIE BCF INTCON,T0IF GOTO interupt program BSF STATUS,RP0 ;inicializace uP MOVLW b'00000000' MOVWF TRISB MOVLW b'00010000' MOVWF TRISA MOVLW b'00110000' MOVWF OPTION_REG BCF STATUS,RP0 MOVLW b'10100000' MOVWF INTCON CLRF PORTA melodie call sndc call sndd call snde call sndf call sndg call snda call sndh goto melodie sndc BSF PORTA,3 CALL Cwait BCF PORTA,3 CALL Cwait BTFSS exit,0 GOTO sndc BCF exit,0 RETURN sndd BSF PORTA,3 CALL Dwait BCF PORTA,3 CALL Dwait BTFSS exit,0 GOTO sndd BCF exit,0 RETURN snde BSF PORTA,3 CALL Ewait BCF PORTA,3 CALL Ewait BTFSS exit,0 GOTO snde BCF exit,0 RETURN sndf BSF PORTA,3 CALL Fwait BCF PORTA,3 CALL Fwait BTFSS exit,0 GOTO sndf BCF exit,0 RETURN sndg BSF PORTA,3 CALL Gwait BCF PORTA,3 CALL Gwait BTFSS exit,0 GOTO sndg BCF exit,0 RETURN snda BSF PORTA,3 CALL Await BCF PORTA,3 CALL Await BTFSS exit,0 GOTO snda BCF exit,0 RETURN sndh BSF PORTA,3 CALL Hwait BCF PORTA,3 CALL Hwait BTFSS exit,0 GOTO sndh BCF exit,0 RETURN Cwait MOVLW 27 ;podprogram půl periody pro c1 MOVWF c2 Cwait2 MOVLW 229 MOVWF c1 Cwait1 DECFSZ c1,1 GOTO Cwait1 DECFSZ c2,1 GOTO Cwait2 RETURN Dwait MOVLW 24 ;podprogram půl periody pro d1. MOVWF d2 Dwait2 MOVLW 233 MOVWF d1 Dwait1 DECFSZ d1,1 GOTO Dwait1 DECFSZ d2,1 GOTO Dwait2 RETURN Ewait MOVLW 33 ;podprogram půl periody pro e1. MOVWF e2 Ewait2 MOVLW 153 MOVWF e1 Ewait1 DECFSZ e1,1 GOTO Ewait1 DECFSZ e2,1 GOTO Ewait2 RETURN Fwait MOVLW 34 ;podprogram půl periody pro f1. MOVWF f2 Fwait2 MOVLW 135 MOVWF f1 Fwait1 DECFSZ f1,1 GOTO Fwait1 DECFSZ f2,1 GOTO Fwait2 RETURN Gwait MOVLW 51 ;podprogram půl periody pro g1. MOVWF g2 Gwait2 MOVLW 81 MOVWF g1 Gwait1 DECFSZ g1,1 GOTO Gwait1 DECFSZ g2,1 GOTO Gwait2 RETURN Await MOVLW 49 ;podprogram půl periody pro a1. MOVWF a2 Await2 MOVLW 76 MOVWF a1 Await1 DECFSZ a1,1 GOTO Await1 DECFSZ a2,1 GOTO Await2 RETURN Hwait MOVLW 45 ;podprogram půl periody pro h1. MOVWF h2 Hwait2 MOVLW 75 MOVWF h1 Hwait1 DECFSZ h1,1 GOTO Hwait1 DECFSZ h2,1 GOTO Hwait2 RETURN interupt BSF exit,0 ;obsluha přerušení BSF PORTA,0 RETFIE END ;konec programu
Kód je založen na tom, že se začne generovat nějaký tón a toto generování by probíhalo do nekonečna, kdyby nebylo přerušeno přerušením, který vygeneruje do registru hodnotu, která umožní opustit cyklus generování tónu. Přerušení na RB0 bych přeskočil neboť je podobné přerušením na horních čtyřech bitech registru PORTB.
Na závěr bych upozornil, že někdy je třeba přerušení zakázat i mimo obsluhu přerušení. Jako příklad lze uvést třeba sériové přenosy dat. K tomu nám slouží bit GIE
Novinky Další novinky
Anketa
Jaký obchod preferujete při nákupu součástek?
TME
GES
GME
Farnell
SOS electronic
TIPA
EZK
PS Electronic
Mouser
Buček
Denkl Electronic
FK Technics
Hadex
Conrad
Jiný český
Jiný zahraniční
Poslední komentáře