16F873А има една неприятна особеност, мястото на записа на W, STATUS и PCLATH регистрите при входа в обработването на прекъсването зависи от състоянието на бита RP0 в самия STATUS регистър. Тоест, ако W_Temp, STATUS_Temp и PCLATH_Temp са декларирани на адреси примерно 70h, 71h и 72h при RP0 = 0 ще се запишат точно там, обаче ако RP0 = 1 ще се запишат на F0h, F1h и F2h. Ако в прекъсването се променя стойността на RP0 резултатите са непредсказуеми, инструкцията banksel INTCON прави точно това. Тя нулира PR0 и W, STATUS и PCLATH ще се възстановят от адреси 70h, 71h и 72h, незаисимо, че са били записани в F0h, F1h и F2h ако RP0 е бил в 1. Между другото INTCON е достъпен във всички банки, така че banksel INTCON е излишна.
Заради тази особеност никога не съм ползвал PIC16F873A/874A, слагам 876A/877A, декларирам W_Temp, STATUS_Temp и PCLATH_Temp някъде между 70h и 7Fh и ми е мирна главата.
Бих предложил следния код:
; Възстановява STATUS както е бил при влизането в прекъсването
swapf STATUS_Temp,W
movwf STATUS ; Restore STATUS register - restores bank
;Регистрите се четат от банката, в която са били записани
movfw PCLATH_Temp
movwf PCLATH ; Restore PCLATH
swapf STATUS_Temp,W
movwf STATUS ; Restore STATUS register - restores bank
swapf W_Temp,F
swapf W_Temp,W ; Restore W register
retfie
Разбира се, ако W_Temp, STATUS_Temp и PCLATH_Temp са на адреси примерно 70h - 72h , адресите F0h - F2h в банка 1 не трябва да се ползват нито в главната програмат, нито в прекъсването.
Гаранции не давам, все пак никога не съм го проверявал
