Yes, but only if you're using ON INTERRUPT, which is really not the way to go for somethingAs I understand it, interrupts only work at the end of a command so if I pause 1sec the interrupt would only execute at the end of the pause ? Same as if I paused 1sec then just read an input pin.
like this application. Assembler interrupts would work, but I think this can be done with a lot
less hassle.
Let's get creative on this one, and not use interrupts. We'll just monitor the Timer1 overflow
flag. With Timer1 running in the background you have a multi-tasking environment that can
remove a ton of firmware overhead.
This is pretty heavily commented, but if you have questions, let me know. I didn't have aCode:DEFINE LOADER_USED 1 DEFINE OSC 4 ' Define LAB-X1 LCD registers and bits DEFINE LCD_DREG PORTD DEFINE LCD_DBIT 4 DEFINE LCD_RSREG PORTE DEFINE LCD_RSBIT 0 DEFINE LCD_EREG PORTE DEFINE LCD_EBIT 1 DEFINE LCD_COMMANDUS 2000 DEFINE LCD_DATAUS 50 SYMBOL PROBE = PORTA.0 ' O-scope probe for timing tests SEC_COUNT VAR BYTE ' seconds counter OLD_COUNT VAR BYTE ' copy of count PORT_VAL VAR BYTE ' holds value read from input port O_FLOWS VAR BYTE ' holds the number of timer1 overflows T1LO CON $B0 ' timer1 reload values T1HI CON $3C PORTB = 0 ' RB3 to RB0 = 0 TRISB = %11110000 ' RB7 to RB4 = inputs, RB3 to RB0 = outputs INTCON = 0 ' interrupts disabled (we're just watching tmr1 int flag) OPTION_REG = 0 ' portb pull-ups on for RB7 to RB4 T1CON = %00100000 ' 1:4 prescale (4uS per tick), timer1 off TMR1H = T1HI ' $3CB0=15,536. 65,536-15,536 = 50,000 TMR1L = T1LO ' 50,000 ticks * 4uS = 0.2 seconds. 1 second / 0.2 = 5 ' every 5 timer1 overflows = 1 second ADCON1 = 7 ' Set PORTA and PORTE to digital LOW PORTE.2 ' LCD R/W line low (W) PAUSE 1000 ' Wait for LCD to start up LCDOUT $FE,1 ' Clear LCD Main: SEC_COUNT=30 ' load for 30 to 0 countdown OLD_COUNT=1 ' mismatch for display (see below) O_FLOWS=0 ' clear overflow count PIR1.0=0 ' clear timer1 overflow flag T1CON.0=1 ' start timer1 Test: TOGGLE PROBE ' 77uS from start to return ' Note: Timer1 overflows every 0.2 seconds, so we have time to execute ' a whopping 200,000 single-cycle instructions before this section is ' executed IF PIR1.0 THEN ' if timer1 overflow then O_FLOWS=O_FLOWS+1 ' inc oveflow counter IF O_FLOWS=5 THEN ' if 1 second elapsed then SEC_COUNT=SEC_COUNT-1 ' decrement seconds count O_FLOWS=0 ' reset overflow counter ENDIF PIR1.0=0 ' clear timer1 overflow flag T1CON.0 = 0 ' stop timer1 TMR1L = TMR1L + T1LO ' add in low byte IF TMR1L < T1LO THEN TMR1H = TMR1H + 1 ' if low byte overflow, increment high byte TMR1H = TMR1H + T1HI ' add in high byte T1CON.0=1 ' re-start timer1 IF SEC_COUNT=255 THEN SEC_COUNT=30 ' reset to 30 after 0-1 underflow OLD_COUNT=1 ' make sure new value is displayed ENDIF ENDIF ' display is updated only when count has changed, so LCDOUT gets executed ' only once each second IF SEC_COUNT != OLD_COUNT THEN LCDOUT $FE,1,"Count = ",DEC SEC_COUNT OLD_COUNT=SEC_COUNT ' match last displayed count for next pass ENDIF ' portb gets read ~every 77uS PORT_VAL = (PORTB >> 4) ' read portb IF PORT_VAL !=15 THEN ProcessInput ' do something if switch pressed GOTO Test ProcessInput: ' print switch inputs on 2nd line of LCD when RB7, 6, 5 or 4 are at ground LCDOUT $FE,$C0,IBIN4 PORT_VAL ' display input values GOTO Test END
serial LCD handy, but this should be pretty easy to modify for your own hardware.
Making entry into the time-consuming routines conditional, leaves a ton of time to monitor
your switch inputs, and it's easy to keep everything up to date without using interrupts.
So you have a boat-load of time to goof-off doing other stuff between the count,
display updates, and timer reloads.
Instead of wasting valuable time with a PAUSE 1000, you're running around the entire loop
from start to return in around 77uS, and have plenty of time to burn for other stuff.
If you have an O-scope, try placing the TOGGLE PROBE at different locations to see how fast
everything happens.




Bookmarks