Itt kezdődik az érdemi része
EXT_INT0:
- Ez a megszakítás akkor következik be, ha az INT0 bemeneten (D port 2 bit), változás történik. Úgy állítottuk be, hogy mind a felfutó, mind a lefutó élre érzékeny legyen.
- Ez a rutin használja az "IT_valtozo", a "felbit" és a "bitek" nevű regisztereket, és értékkel látja el a "vettbyteL" és "vettbyteH" nevű regisztereket.
in IT_valtozo, SREG
push IT_valtozo
- Minden megszakítást illik úgy kezdeni, hogy az állapotregisztert elmentjük a verembe (stack).
in IT_valtozo, TCNT0
- Kiolvassuk az időzítő pillanatnyi értékét. Ez mutatja a legutóbbi élváltozás óta eltelt időt, kb. 15.6us-os felbontásban. Mivel a számláló 8 bites, így a maximális érték 255 lehet, ami kb. 4 ms-nak felel meg.
cpi IT_valtozo, 0
breq EXT_INT0_ELSO
- Ha a számláló értéke 0, akkor még nincs elindítva az időzítő. Új adatsor kezdődik, ez most az első bit kezdete, tehát el kell indítani az időzítőt (EXT_INT0_ELSO)
- Ha nem 0, akkor el kell dönteni, hogy "0" vagy "1" bit érkezett.
cpi IT_valtozo, 83
brlo FELEGY
- Az eltelt idő 1.3 ms-nál rövidebb? (15.625us X 83) Ha igen, akkor "1" bit egyik fele (FELEGY)
- Ha hosszabb, akkor "0" bit érkezett
sbrc felbit, 0
rjmp EXT_INT0_VEGE
- Ellenőrzés, érkezett-e előzőleg "1" bitnek az első fele? Ha az előző egy "1" bitnek az első fele volt, akkor a másik felének kellett volna jönnie, tehát hiba történt. Ilyenkor nem csinálok semmit, a végén kevesebb lesz a bitek száma a szükségesnél, és a program el fogja dobni az adatsort (EXT_INT0_VEGE).
- Ha rendben van az ellenőrzés...
inc bitek
- Növelem a bitek számát egyel. Tudom, hogy végül 14 darabnak kell lennie.
cpi bitek, 8
brlo NULLA_ELSO
- Eldöntöm, hogy az első 7 bitnél vagy a második 7 bitnél tartunk. Ha az első 7 bit valamelyikénél, akkor ott folytatom (NULLA_ELSO)
lsl vettbyteH
- Tárolom a "0" bitet. A vettbyteH regisztert eltolom egy bittel balra. Minden bit magasabb helyi-értékre kerül, és a jobb szélső helyre, a legalacsonyabb értékre 0 érkezik. Mivel valóban ez érkezett, nincs is más dolgom, befejezhetem a megszakítást.
rjmp EXT_INT0_VEGE
NULLA_ELSO:
- Ha az első 7 bit valamelyikéről van szó.
lsl vettbyteL
- Tárolom a "0" bitet. A vettbyteL regisztert eltolom egy bittel balra. Minden bit magasabb helyi-értékre kerül, és a jobb szélső helyre, a legalacsonyabb értékre 0 érkezik. Mivel valóban ez érkezett, nincs is más dolgom, befejezhetem a megszakítást.
rjmp EXT_INT0_VEGE
FELEGY:
- Ide ugrik, ha "1" bitnek a fele érkezett
sbrc felbit, 0
- El kell dönteni, hogy az első vagy a második fele jött az "1" bitnek.
rjmp EGY
- Ha a második fele volt, akkor megérkezett a teljes "1" bit. (EGY)
inc felbit ; Megjegyzem, hogy megjött az "1" első fele
- Ha még csak az első volt, akkor megjegyzem és befejezem a megszakítást.
rjmp EXT_INT0_VEGE
EGY: ; Ez már az "1" bit második fele volt
- Ide ugrik, ha már a második fele is megérkezett az "1" bitnek.
clr felbit
- Törlöm az "1" bit felének jelzését.
inc bitek
- Növelem a bitek számát egyel. Tudom, hogy végül 14 darabnak kell lennie.
cpi bitek, 8
brlo EGY_ELSO
- Eldöntöm, hogy az első 7 bitnél vagy a második 7 bitnél tartunk. Ha az első 7 bit valamelyikénél, akkor ott folytatom (EGY_ELSO)
lsl vettbyteH
- Tárolom a "0" bitet. A vettbyteH regisztert eltolom egy bittel balra. Minden bit magasabb helyi-értékre kerül, és a jobb szélső helyre, a legalacsonyabb értékre 0 érkezik.
inc vettbyteH
- Mivel valójában nem ez érkezett, ezért be kell írnom egy "1" bitet a jobb szélső helyre. Ezután befejezhetem a megszakítást.
rjmp EXT_INT0_VEGE
EGY_ELSO:
- Ha az első 7 bit valamelyikéről van szó.
lsl vettbyteL
- Tárolom a "0" bitet. A vettbyteL regisztert eltolom egy bittel balra. Minden bit magasabb helyi-értékre kerül, és a jobb szélső helyre, a legalacsonyabb értékre 0 érkezik.
inc vettbyteL
- Mivel valójában nem ez érkezett, ezért be kell írnom egy "1" bitet a jobb szélső helyre. Ezután befejezhetem a megszakítást.
rjmp EXT_INT0_VEGE
EXT_INT0_VEGE:
- Az EXT_INT0 rutin lezárása
clr IT_valtozo
out TCNT0, IT_valtozo
pop IT_valtozo
out SREG, IT_valtozo
reti
- Minden megszakításnak így kell véget érnie. A veremből visszatölti az állapotregisztert és kilép.
EXT_INT0_ELSO:
- Ide ugrik, amikor a legelső él érkezett.
clr bitek ; Eddig jött 0 darab bit
clr felbit ; Eddig nem jött "1" bit fele sem
clr vettbyteL ; A vett byte-ok tartalmának törlése
clr vettbyteH
- Törli a változókat: bitek, felbit, vettbyteL, vettbyteH
ldi IT_valtozo, 3
out TCCR0B, IT_valtozo
- A számláló elindítása. Az előosztó: a belső órajelet 1/64-ed részére osztja.
pop IT_valtozo
out SREG, IT_valtozo
reti
- Minden megszakításnak így kell véget érnie. A veremből visszatölti az állapotregisztert és kilép.
T0_OVF:
- Ez a megszakítás akkor következik be, ha a 0. időzítő számlálójában túlcsordulás keletkezik. Ez azért történhet, mert a legutóbbi élváltozás óta eltelt 4 ms. Mivel rendes körülmények között 0.6 - 2 ms közötti idő telik el két él között, ezért ennek két oka lehet. Vagy ez volt az utolsó bit, vagy megszakadt a bitsorozat valamilyen okból. Első esetben megérkezett a teljes jelsorozat, fel kell dolgozni. Második esetben hiba történt, ezért ez eddigieket el kell dobni és várni a következőre.
- Ez a rutin használja az IT_valtozo, kuldeni és valtozo nevű regisztereket és végső értéket ad a vettbyteL és vettbyteH regisztereknek. Használja az EGYBYTEKULD szubrutint.
cli
- Tiltom a további megszakításokat, biztos, ami biztos alapon
in IT_valtozo, SREG
push IT_valtozo
- Minden megszakítást illik úgy kezdeni, hogy az állapotregisztert elmentjük a verembe (stack).
clr IT_valtozo
out TCCR0B, IT_valtozo
- Leállítom az időzítőt, hiszen nem várok több bitet.
out TCNT0, IT_valtozo
- Nullázom a számlálót. Így ismeri majd fel, hogy egy új adatsor kezdődik.
cpi bitek, 13
brlo T_OVF_HIBA
- El kell dönteni, hogy miért történt a túlcsordulás.Ha eddig 13 bit érkezett, akkor ez a 14. bit, vagyis minden rendben van. Ha nem pont annyi, akkor hiba történt (T_OVF_HIBA).
lsl vettbyteH
- Igen, akkor megvan az utolsó bit is, balra tolom egy helyi-értékkel a magasabb byte-ot.
sbrc felbit, 0
inc vettbyteH
- Ha előzőleg egy "1" bit egyik fele érkezett már, akkor ez a második fele. Ebben az esetben beírom a jobb szélső helyre az "1"-et.
mov kuldeni, vettbyteL
rcall EGYBYTEKULD
mov kuldeni, vettbyteH
rcall EGYBYTEKULD
rcall SORVEGE
- Átküldöm a PC-nek előbb az alacsonyabb értékű, majd a magasabb értékű byte-ot, végül a "kocsivissza" + "soremelés" karaktereket.
T_OVF_HIBA:
- Ide ugrik, ha hiba volt, és nem küld semmit el. Ha nem volt hiba, akkor a vett byte-ok elküldése után folytatja itt.
pop IT_valtozo
out SREG, IT_valtozo
sei
reti
- Minden megszakításnak így kell véget érnie. A veremből visszatölti az állapotregisztert, ismét engedélyezi a megszakításokat és kilép.
- Itt van felsorolva az összes lehetséges megszakításrutin. Bármelyik történik, ugyanazt teszi, visszatér e program korábbi futásához.
- Azokat a rutinokat, amiket valóban használok (EXT_INT0, T0_OVF, UART_RX) megjegyzésként jelölöm meg. Ha tovább rutinokat szeretnék használni, akkor azokkal is ezt kell tennem.
;EXT_INT0:
EXT_INT1:
T1_CAPT1:
T1_COMPA:
T1_OVF:
;T0_OVF:
;UART_RX:
UART_UDRE:
UART_TX:
ANA_COMP:
PCINT:
T1_COMPB:
T0_COMPA:
T0_COMPB:
USI_START:
USI_OVF:
EE_READY:
WDT_OVF:
reti
A cikk még nem ért véget, lapozz!
Értékeléshez bejelentkezés szükséges!