list P = PIC16F690 #include "p16F690.inc" __config (_CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _FCMEN_OFF) org 0 goto Main org 4 GOTO ISR org 5 ;Port definitions #define QUERY_LINE 5 #define QUERY_PORT PORTC ;LED definitions for testing #define LED_Y 1 #define LED_G 2 #define LED_R 0 #define LED_PORT PORTC ;Register definitions Q_TEMP equ 0x7A ;for query timer, whether the query line should be hi or low BYTE_COUNT equ 0x70 ;byte counter W_TEMP equ 0x71 ;interrupt shadow copy of W STATUS_TEMP equ 0x72 ;interrupt shadow copy of STATUS LAST_RX equ 0x73 ;last received byte AA equ 0x74 ;AA in Balloon Monitor standard BB equ 0x75 ;BB in Balloon Monitor standard CC equ 0x76 ;CC in Balloon Monitor standard DD equ 0x77 ;DD in Balloon Monitor standard EE equ 0x78 ;EE in Balloon Monitor standard CK equ 0x79 ;CK in Balloon Monitor standard ;=======MAIN PROGRAM========== Main: ;Port Setup banksel ANSEL ;clear analog inputs CLRF ANSEL CLRF ANSELH ;Set ports as input and output banksel TRISC BCF TRISC,QUERY_LINE; BCF TRISC,LED_R BCF TRISC,LED_G BCF TRISC,LED_Y BSF TRISB,5 ;port B RX is input banksel LED_PORT clrf LED_PORT ;Set up UART banksel SPBRG BCF TXSTA, SYNC ;disable sync BSF TXSTA, BRGH BCF BAUDCTL,BRG16; MOVLW 0x81;32 ;for baud rate of 9600, need divisor of 32 MOVWF SPBRG banksel RCSTA BSF RCSTA, SPEN ;enable serial module BSF RCSTA, CREN ;enable receiver banksel PIE1 BSF PIE1, RCIE ;enable receive complete interrupt ;Set up timer 1 for polling every 50ms banksel T1CON clrf T1CON BSF T1CON,T1CKPS1 ;set prescale to 8 BSF T1CON,T1CKPS0 clrf CCP1CON BSF CCP1CON,CCP1M1 ;compare mode, generate software interrupt, toggle CCP1 pin upon match banksel PIE1 BSF PIE1,CCP1IE ;enable CCP1 interrupt banksel CCPR1H MOVLW 0x7A ;put 31,250 (50ms) into CCPR1 register for OC MOVWF CCPR1H MOVLW 0x12 MOVWF CCPR1L BSF T1CON,TMR1ON ;timer 1 on, use Fosc/4 (5Mhz) MOVLW 1 MOVWF Q_TEMP ;set Q_temp to 1, indicate counting the high time ;Interrupts banksel INTCON BSF INTCON, PEIE ;enable peripheral interrupts BSF INTCON, GIE ;enable global interrupts LOOP: ;main loop GOTO LOOP ;empty loop as everything is in interrupts ;=======Interrupt Service Routines/Helpers======= ISR: ;Save registers BANKSEL W_TEMP MOVWF W_TEMP SWAPF STATUS,W MOVWF STATUS_TEMP ;Check for RX interrupt banksel PIR1 BTFSC PIR1, RCIF goto RxInterrupt ;Check for Timer 1 interrupt BTFSC PIR1, CCP1IF goto Tmr1Interrupt ISRcomplete: ;Restore registers BANKSEL STATUS_TEMP SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W RETFIE Tmr1Interrupt: BCF PIR1, CCP1IF s;Clear interrupt flag banksel Q_TEMP ;if Q_TEMP is 1, then put 31,250 into the register for OC to keep line high for 50 ms BTFSS Q_TEMP,0 GOTO lower ;else if Q_TEMP is 0 go to lower banksel CCPR1H MOVLW 0x7A ADDWF CCPR1H MOVLW 0x12 ADDWF CCPR1L CLRF Q_TEMP ;clear Q_TEMP GOTO ISRcomplete lower: banksel CCPR1H MOVLW 0x09 ;add 2500 into register for OC to lower the query line for 4 ms ADDWF CCPR1H MOVLW 0xC4 ADDWF CCPR1L banksel Q_TEMP ;set Q_TEMP to 1 MOVLW 0x01 MOVWF Q_TEMP GOTO ISRcomplete ;Receive interrupt RxInterrupt: banksel RCREG ;Load newest receive byte, also clearing RCIF flag MOVF RCREG,W BTFSC RCSTA,FERR ;test for framing error goto RxError BTFSC RCSTA,OERR ;test for receiver overrun goto RxError ;If no errors, accept and store this byte banksel LAST_RX MOVWF LAST_RX ;save received byte for later use MOVF LAST_RX,W XORLW 0x02 ;check if received byte is 0x22 BTFSS STATUS,Z ;if it is not 0x22 then go to NotFirstByte GOTO NotFirstByte MOVLW 1 ;if it is 0x22, set ByteCount to 1 MOVWF BYTE_COUNT GOTO ISRcomplete ;go to end of ISR NotFirstByte: MOVF BYTE_COUNT,W XORLW 1 ;check if ByteCount is 1 BTFSS STATUS,Z GOTO NotSecondByte ;if ByteCount isn't 1, go to NotSecondByte MOVF LAST_RX,W ;if ByteCount is 1, store received byte as AA MOVWF AA MOVLW 2 ;set ByteCount to 2 MOVWF BYTE_COUNT GOTO ISRcomplete ;go to end of ISR NotSecondByte: MOVF BYTE_COUNT,W XORLW 2 ;check if ByteCount is 2 BTFSS STATUS,Z GOTO NotThirdByte ;if ByteCount isn't 2, go to NotThirdByte MOVF LAST_RX,W ;if ByteCount is 2, store received byte as BB MOVWF BB MOVLW 3 ;set ByteCount to 3 MOVWF BYTE_COUNT GOTO ISRcomplete ;go to end of ISR NotThirdByte: MOVF BYTE_COUNT,W ;follow same pattern as above XORLW 3 BTFSS STATUS,Z GOTO NotFourthByte MOVF LAST_RX,W MOVWF CC MOVLW 4 MOVWF BYTE_COUNT GOTO ISRcomplete NotFourthByte: MOVF BYTE_COUNT,W XORLW 4 BTFSS STATUS,Z GOTO NotFifthByte MOVF LAST_RX,W MOVWF DD MOVLW 5 MOVWF BYTE_COUNT GOTO ISRcomplete NotFifthByte: MOVF BYTE_COUNT,W XORLW 5 BTFSS STATUS,Z GOTO NotSixthByte MOVF LAST_RX,W MOVWF EE MOVLW 6 MOVWF BYTE_COUNT GOTO ISRcomplete NotSixthByte: MOVF BYTE_COUNT,W XORLW 6 BTFSS STATUS,Z GOTO NotSeventhByte MOVF LAST_RX,W MOVWF CK MOVLW 7 MOVWF BYTE_COUNT GOTO ISRcomplete NotSeventhByte: ;last byte frame MOVF BYTE_COUNT,W XORLW 7 ;check if ByteCount is 7 BTFSS STATUS,Z GOTO ByteFailed ;if ByteCount isn't 7 but it got to this part of the code, something is wrong MOVF LAST_RX,W ;if ByteCount is 7, check that it is 0x03 XORLW 0x03 BTFSS STATUS,Z GOTO ByteFailed ;byte failed if it isn't 0x03 MOVLW 0 ;if it is 0x03, set ByteCount back to 0 MOVWF BYTE_COUNT ;check checksum banksel AA MOVF AA,W XORWF BB,W XORWF CC,W XORWF DD,W XORWF EE,W XORWF CK,W BTFSS STATUS,Z ;checksum should result in 0 GOTO ByteFailed ;if not, byte failed ;correct checksum banksel LED_PORT ;clear the LEDs BCF LED_PORT,LED_G BCF LED_PORT,LED_R BCF LED_PORT,LED_Y banksel CK MOVF CK,W ;check if the CK value matches that of a popped or intact balloon XORLW 0x5f BTFSS STATUS,Z ;if CK is 0x5f, then balloon in intact GOTO Popped ;else it is popped Intact: banksel LED_PORT BSF LED_PORT,LED_G ;intact indication goto ISRcomplete Popped: banksel LED_PORT BSF LED_PORT,LED_R ;popped indication goto ISRcomplete RxError: BSF LED_PORT,LED_Y goto ISRcomplete ByteFailed: BSF LED_PORT,LED_Y goto ISRcomplete END