Here is something from Bruce that will time-out and active serial port. Works very well for radios.
Code:
'****************************************************************
'*  Name    : DEC.BAS                                           *
'*  Author  : B. Reynolds                                       *
'*  Notice  : Copyright (c) 2009 Reynolds Electronics           *
'*          : All Rights Reserved                               *
'*  Date    : 11/15/2009                                        *
'*  Version : 1.0 (Momentary decoder version)                   *
'*  Notes   : 4-BIT DECODER IC FOR RF REMOTE CONTROL            *
'*          : USING THE PIC12F635                               *
'****************************************************************
@ DEVICE PIC12F635,MCLR_OFF,INTRC_OSC_NOCLKOUT,WDT_OFF,BOD_OFF
@ DEVICE PWRT_ON,FCMEN_OFF,IESO_OFF,WUREN_OFF,PROTECT_OFF
    
    DEFINE OSC 4
    DEFINE NO_CLRWDT 1      ' Watchdog timer is disabled, so we don't need to reset it
    DEFINE INTHAND RESET_VT ' Interrrupt on Timer1 overflow to reset outputs in 65.5mS
                            ' if no serial data received in this time period
    SYMBOL  MODE = GPIO.3   ' baud select. 1=4800, 0=2400
    SYMBOL  D_IN = GPIO.5   ' Encoder data input pin
    SYMBOL  TMR1IF = PIR1.0 ' Timer1 overflow interrupt flag (reset in int handler)
    SYMBOL  TMR1IE = PIE1.0 ' Timer1 interrupt enable bit
    
    'Variables for saving state in interrupt handler
    wsave    VAR    BYTE $70 system        ' Saves W
    ssave    VAR    BYTE bank0 system    ' Saves STATUS
    psave    VAR    BYTE bank0 system    ' Saves PCLATH
    fsave    VAR    BYTE bank0 system    ' Saves FSR
    
    ' Working variables
    MATCH     VAR BYTE bank0 system ' Match variable
    DAT_IN1   VAR BYTE  ' 1st Data byte
    DAT_IN2   VAR BYTE  ' 2nd Data byte for verify
    CHK_SUM   VAR BYTE  ' Holds checksum received
    CheckSum  VAR BYTE  ' Checksum of data bytes received
    LOOPS     VAR BYTE  ' Loop var
    BAUD      VAR WORD  ' Holds baud rate
    
    ' Constants
    Synch    CON "~"    ' 01111110 synch byte
    N2400    CON 16780  ' 2400 bps inverted
    N4800    CON 16572  ' 4800 bps inverted
    
     ' hardware init
    GPIO = 0            ' Clear outputs on power-up
    TRISIO = 101000  ' GPIO.5=data input, GPIO.3=baud select input
    WPUDA = 0           ' Disable weak pull-ups
    IOC = 0             ' Interrupt on change disabled
    VRCON = 0           ' Comparator Vref disabled
    CMCON0 = 7          ' Disable comparators
    OSCCON = 100000  ' Internal 4MHz select
    OPTION_REG = 128    ' Pull-ups off
    
    ' Setup Timer1 for resets after ~65.5mS
    T1CON = 000000   ' Internal clock, 1:1 prescale, Timer1 off for now
    TMR1L = 0 
    TMR1H = 0           ' Timer1 low & high bytes cleared
    TMR1IF = 0          ' Clear Timer1 overflow flag before enabling interrupt
    TMR1IE = 1          ' Enable Timer1 overflow interrupt
    INTCON = 000000  ' Global & peripheral ints enabled
    MATCH = 0           ' Clear match count
    GOTO    MAIN        ' Jump over int handler
    
ASM
RESET_VT
    movwf    wsave            ; Save W
    swapf    STATUS, W        ; Swap STATUS to W (swap avoids changing STATUS)
    clrf    STATUS            ; Clear STATUS
    movwf    ssave            ; Save swapped STATUS
    movf    PCLATH, W        ; Move PCLATH to W
    movwf    psave            ; Save PCLATH
    movf    FSR, W            ; Move FSR to W
    movwf    fsave            ; Save FSR
    
    ; Do interrupt stuff here
    bcf     T1CON,TMR1ON    ; Stop Timer1
    clrf    TMR1L           ; Clear low byte
    clrf    TMR1H           ; Clear high byte
    bcf     PIR1,TMR1IF     ; Clear Timer1 interrupt flag bit
    clrf    GPIO            ; Clear outputs on button release (or timeout)
    clrf    MATCH           ; Clear match variable
    
    ; Restore FSR, PCLATH, STATUS and W registers
    movf    fsave, W        ; retrieve FSR value
    movwf    FSR                ; Restore it to FSR
    movf    psave, W        ; Retrieve PCLATH value
    movwf    PCLATH            ; Restore it to PCLATH
    swapf    ssave, W        ; Get swapped STATUS value (swap to avoid changing STATUS)
    movwf    STATUS            ; Restore it to STATUS
    swapf    wsave, F        ; Swap the stored W value
    swapf    wsave, W        ; Restore it to W (swap to avoid changing STATUS)
    bsf     T1CON,TMR1ON    ; Re-enable Timer1 before exiting interrupt handler
    retfie                    ; Return from the interrupt
ENDASM
 
MAIN:    
    ' Set data rate
    IF MODE = 1 THEN
       BAUD = N4800
    ELSE
       BAUD = N2400
    ENDIF
      
    ' Fire up Timer1 before entry to serial input routine
    T1CON.0 = 1
    
    ' at 4MHz Timer1 overflows in 65536 * 1uS (~65.5mS) if no Synch byte
    ' and serial data arrive on time. SERIN2 timeout & label options
    ' are useless with a noisy RF receiver output - as noise continually
    ' resets the timeout period causing it to hang forever.
    
    ' Wait for Synch byte, then get new inbound data & checksum
    SERIN2 D_IN,BAUD,[WAIT(Synch),DAT_IN1,DAT_IN2,CHK_SUM]
    
    T1CON.0 = 0    ' Stop Timer1 once we've received data
    TMR1L = 0      ' Clear low byte
    TMR1H = 0      ' Clear high byte
    
    ' / **** Begin data validation **** /
    
    ' Calculate checksum
    CheckSum = DAT_IN1 + DAT_IN2
    
    ' Test new checksum against one received in CHK_SUM
    IF CheckSum != CHK_SUM THEN MAIN ' Failed checksum, return
    
    ' Test data bytes for match
    IF DAT_IN1 != DAT_IN2 THEN MAIN ' Failed data comparison, return
    
    MATCH = MATCH + 1        ' We have a match so increment match count
    IF MATCH = 2 THEN DECODE ' Everything matched twice, we're good
    GOTO Main                ' Else do it all over
    
    ' Everything looking good - so place new data on outputs
    
DECODE:
    ' Place decoded values on port pins..
    GPIO = (DAT_IN1 & 010111)
    DAT_IN1 = !DAT_IN2  ' Destroy the match
    MATCH = 0 
    GOTO MAIN
        
    END
.
The forum is stripping off "%". But you should get the idea.