Zdravím, mám problém s přerušením u PIC16F876A. Mám vytvořený program pro ovládání zimní zahrady. Na první stránce programového kódu (ORG 0) je samotný program pro zobrazování informací na displeji, testování vstupů atd. Pak je zde přerušení kde se čte klávesnice. K přerušení dojde při přetečení TMR0. Ostatní přerušení jsou zakázána. Na další straně programového kódu (ORG 0x900) je ovládání menu celého zařízení. Fungovat to má tak že program běží pouze na první straně kódu a pouze při stisknutí tlačítka menu na klávesnici skočí na stranu 2. Všechno funguje až do doby než pogram přeskočí na stranu 2. V tu chvíli přestane fungovat přerušení a nefunguje ani když se program vrátí na stranu 1. Musí se při skoku na jinou stranu kódu nějak ošetřovat přerušení nebo TMR0?
Děkuji předem za pomoc
Zkus si ošetřit i PCLATH, případně FSR. Taky jsem s tím měl problémy.
[code] org 0x0004 ; vektor přerušení
;*********************************
PRERUS
MOVWF TMP_W
MOVF STATUS,W
MOVWF TMP_S
movf PCLATH,w
movwf TMP_PCLATH
; movf FSR,w
; movwf TMP_FSR
; movf INDF,w
; movwf TMP_INDF
pagesel 0 ;TOTO DELA DOBREJ BORDEL
banksel 0 ;TOTO DELA DOBREJ BORDEL
bcf STATUS,IRP
;********************************
; vykon
;********************************
;dokončit přerušení
;--------------------------------
INT_END
KP
; movf TMP_INDF,w
; movwf INDF
; movf TMP_FSR,w
; movwf FSR
MOVF TMP_PCLATH,W
MOVWF PCLATH
MOVF TMP_S,W
MOVWF STATUS
SWAPF TMP_W,F
SWAPF TMP_W,W
RETFIE
[/code]
Díky moc, vypadá to že to chodí. Zatím jen v MPLABU. Doma to nahraju do PIC a uvidím. Ještě jsem akorát musel do toho přerušení doplnit CLRF PCLATH aby to přerušení proběhlo správně jinak mě to stejně odkazovalo jinam. Ještě v tom mám trochu zmatek
pagesel 0 je místo clrf PCLATH, ale je fakt, že já ho tam mám taky. pagesel 0 nevynuluje celej PCLATH. Mám ho, ale těsně před obsluhou přerusení (v tom výkonu).
Aha to jsou věci. banksel ani pagesel neznám. Ještě budu muset nasbírat nějaký informace. Asi jsem si s tím programem vzal velký sousto
A PAGE 1 jako org 0x900 je dle mě špatně. PAGE 1 je od 0x0800 do 0x0FFF. PAGE 2 je od 0x1000 do 0x17FF, PAGE 3 je od 0x1800 do 0x1FFF, viz datasheet str. 11
Aha takže se vlastně okrádam o kousek prostoru protože mám prostor mezi 0x800 a 0x900 nevyužitej. Tu adresu jsem našel v knížce o PIC16876. Díky za upozornění
Myslím, že jsi v tomto případě o nic nepřišel. Jsou to pseudoinstrukce, které assemler nahradí kódem BCF a jak výše uvedeno “TOTO DELA DOBREJ BORDEL”
Nevidím jediný důvod tuto konstrukci používat.
pagesel X, u 876x 0-3, nastavuje STATUS,RP0 a RP1. Používám ho, když skáču do jiné stránky, ale používám ho jako pagesel MAIN. tak mam jistotu, že se RPx nastaví tak jak má a já to nemusím hlídat. Nechápu, co ti na použití této pseudoinstrukce vadí? Něco podobného platí i pro banksel
Nějak jsem totiž nepochopil funkci direktivy banksel a nebo dělám někde hrubou chybu.
Když napíšu krátký prográmek:
list P=PIC16F877
#include <P16F877.INC>
errorlevel -302
lab0 EQU 0x00
lab1 EQU 0x01
lab2 EQU 0x02
lab3 EQU 0x03
;--------- ZACATEK PROGRAMU -------------------------------------------
org 0x0000 ; zacatek programu
loop
movlw B'01100000'
movwf STATUS
banksel lab0
banksel lab1
banksel lab2
banksel lab3
banksel lab0
goto loop
end ; konec programu
Tak překlad tohoto prográmku vypadá takto:
0000 3060 MOVLW 0x60
0001 0083 MOVWF 0x3
0002 1283 BCF 0x3, 0x5
0004 1283 BCF 0x3, 0x5
0006 1283 BCF 0x3, 0x5
0008 1283 BCF 0x3, 0x5
000A 1283 BCF 0x3, 0x5
000C 2800 GOTO 0
No a s tím výsledkem si nějak nevím rady.
Já to zblbl
pagesel x je, že nastavení PCLATH bude dle stránek
a
banksel x je, že dojde k nastavení STATUS, RP0 a RP1
a u tebe jsou všechny v bank0, tak proto je ten překlad stejnej. Neboli BCF STATUS, RP0. Akorát nevím, jak by to vypadalo, kdyby jsi byl v bank 2 nebo 3
Až ted jsem to pochopil. Ty jsi nastavil RP0 a RP1 do 1
To pak nemůže fungovat.
EDIT: Ale je zajímavé, že když to kroukuješ v MPLABu, tak to u prvního banksel hodí RP1 i RP0 do nuly. Nikdy jsem o tom takhle nepřemýšlel, ale musí to fungovat, protože to používám a nikdy jsem s tímhle problém neměl.
list P=PIC16F877A
#include <P16F877A.INC>
errorlevel -302
lab0 EQU 0x20
lab1 EQU 0xA0
lab2 EQU 0x120
lab3 EQU 0x1A0
;--------- ZACATEK PROGRAMU -------------------------------------------
org 0x0000 ; zacatek programu
loop
movlw b'01100000'
movwf STATUS
banksel lab0
banksel lab1
banksel lab2
banksel lab3
banksel lab0
goto loop
end ; konec programu[/code]
Tohle krásně přepíná STATUS, ale překlad je hroznej
[code] MOVLW 0x60
MOVWF 0x3
BCF 0x3, 0x5
BSF 0x3, 0x5
BCF 0x3, 0x5
BSF 0x3, 0x5
BCF 0x3, 0x5
GOTO 0
Je legrační, že jsem svůj program upravil prakticky do stejné podoby. Všiml jsem si také stejného efektu při simulaci jako ty. Ale především se podívej na svůj výsledek:
MOVLW 0x60
MOVWF 0x3
BCF 0x3, 0x5
BSF 0x3, 0x5
BCF 0x3, 0x5
BSF 0x3, 0x5
BCF 0x3, 0x5
GOTO
Tohle přece nepřepíná správně ! Přepíná to pouze mezi bankou 0 a 1.
Jsem to napsal blbě. Jako že při simulaci to přepíná správně. Ale proč to teda funguje správně v reálu?
To teda nevím. V simulaci se to chová naprosto správně a ten rozpor mě vadí. Nedovedu to vysvětlit.
Když to zhrnu, tak v simulaci a reálně to funguje, ale podle překladu by to fungovat nemělo. Divné.
Asi jsem na to přišel
bcf STATUS,RP0 - 1283
bsf STATUS,RP0 - 1683
bcf STATUS,RP1 - 1303
bsf STATUS,RP1 - 1703
A když dáš banksel 0, tak je v HEXU kod 1283 1303, banksel lab3 dá 1683 1703, takže je to dobře, akorát ten disassemler je nějak zmatenej, ale v HEXu je to dobře.
Ale co teda nefunguje, je příkaz banksel 1,2,3 atd. To udělá to samé, jako banksel, 0. Takže příkaz banksel funguje jen se jménem registru!!
EDIT: A jak tak koukám, tak i v tom disassembleru je to dobře. Jeden příkaz, jeden řádek. Ale u banksel jeden chybí. Takže to není jen zobrazené. 00,01,02,04,06,08,0A,0C,0D,0E,0F
0000 3060 MOVLW 0x60 12: movlw b'01100000'
0001 0083 MOVWF 0x3 13: movwf STATUS
0002 1283 BCF 0x3, 0x5 14: banksel lab0
0004 1683 BSF 0x3, 0x5 15: banksel lab1
0006 1283 BCF 0x3, 0x5 16: banksel lab2
0008 1683 BSF 0x3, 0x5 17: banksel lab3
000A 1283 BCF 0x3, 0x5 18: banksel lab0
000C 2800 GOTO 0 19: goto loop
000D 0000 NOP 20: nop
000E 0000 NOP 21: nop
000F 0000 NOP 22: nop
Jsem dobrej
Nejsi jen dobrej, jsi nejlepší
Je to opravdu skryté, ale v hex kódu to je obsaženo. Hned budu klidněji spát
Nasadil jsi mi s tím brouka do hlavy. Bych to asi přestal používat, i když jsem s tím zatím problémy neměl. Ale můžu v klidu usnout a čekat, kdo, co jak a proč se stane zítra.
K těm dohadům okolo BANKSEL - správně se ta konstrukce používá takto: BANKSEL jmeno_registru, např. BANKSEL TRISB, překladač už sám určí, která je to banka. Význam je, že člověk nemusí tolik čumět do datasheetu.
Spíš vidím výhodu v tom, že když už mám napsanej třeba skoro celej program a najednou potřebuju registr přemístit někam jinam, tak když to mám ošetřene banksel, tak o tom registru nemusím vůbec přemýšlet.