;********************************************************************** ;********************************************************************** ; ; Copyright Tech Systems, 2002 ; ; Set your editor for 3 space tabs for the best viewing of this file. ; ;********************************************************************** ;********************************************************************** ; ; THIS SOFTWARE IS PROVIDED "AS IS". THERE ARE NO WARRANTIES THAT APPLY ; TO THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, ; BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ; FOR A PARTICULAR PURPOSE . THE COMPANY, OR THE SOFTWARE'S AUTHOR, ; SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, CONSEQUENTIAL ; OR INCIDENTAL DAMAGES, FOR ANY REASON. ; ;********************************************************************** ;********************************************************************** ; ; This program can serve as a template for further code development. ; It uses Timer 1 to create a real-time interrupt every 2 milliseconds. ; From this interrupt there are 3 periodic routines created: a 500 Hz ; routine (every 2 milliseconds), a 10 Hz routine (every 100 milli- ; seconds), and a 1 Hz routine (every 1 second). The 2 millisecond ; interrupt should occur in real time, only losing the instruction ; cycles to load the high and low timer 1 registers while the timer 1 ; clock is turned off. ; Certain bits of port B are toggled in this program to examine timing ; with an oscilloscope. ; These are: ; ; - B2 is toggled during the timer 0 interrupt to examine the interrupt ; timing caused by timer 0 overflow. A flag is set in this interrupt ; by which the 2 millisecond routine is engaged in the main loop by ; polling. ; ; - B4 is toggled during the 2 millisecond routine. This can be com- ; pared to the timer 1 interrupt (B2) to examine any polling lat- ; encies caused by tasks being performed in other routines in the ; main loop, or caused by other interrupt latencies. ; ; - B3 is toggled during the 100 millisecond routine to examine its ; timing. ; ; - B1 is toggled during the 1 second routine to examine its timing. ; B1 is wired to the green LED on the Flash PIC Proto board, so ; you should be able to see it toggled at a 1 Hz rate when running ; this program. ; ; File: 877Temp.asm ; ; Company: Tech Systems ; Author: Tim Hawkins ; Date: 02/19/02 ; Revision: ; ; E-mail: tim@techsystemsembedded.com ; Web: www.techsystemsembedded.com ; ;********************************************************************** ;********************************************************************** list P=PIC16F877, F=INHX32; list directive to define processor #include ; processor specific variable definitions ;********************************************************************** ;******* CONFIGURATION BITS ********************************* ;********************************************************************** ; ; Set the configuration registers with the following lines of code. ; Consult P16F877.inc, towards the end of the file, for options ; of the various configuration values. By doing this you will not ; have to manually set the configuration bits when using a programmer ; such as PICSTART PLUS. __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_ON & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC ; ;********************************************************************** ;******* RAM VARIABLES ****************************************** ;********************************************************************** cblock 0x000020 ; Bank 0, 96 bytes TEM_STATUS TEM_WREG TEM_PCLATH INTERRUPT_COUNT HUN_MILLI_COUNT ONE_SEC_COUNT BYTE_FLAGS1 endc TWO_MILLI_FLAG EQU 0x01 ;********************************************************************** ;******* VECTORS ********************************************* ;********************************************************************** ORG 0x000000 goto Start ;******* INTERRUPT ******* ORG 0x000004 movwf TEM_WREG ; save W movf STATUS, W ; save STATUS movwf TEM_STATUS movf PCLATH, W ; save PCLATH movwf TEM_PCLATH IntPoll ; Poll to find the interrupt source btfsc PIR1, TMR1IF ; Check for Timer 1 interrupt goto Timer1Int movf TEM_PCLATH, W movwf PCLATH movf STATUS, W movwf STATUS movf TEM_WREG, W retfie ; Return from interrupt ;******* INTERRUPT HANDLERS ******* Timer1Int ; TMR1 = 0xFFFF - (Fos/4)/IntRateDesired, bcf T1CON, TMR1ON ; Turn off timer 1 ; movlw 0xFE ; Load timer 1 with 0xFEF0 movlw 0xD8 ; Load timer 1 with 0xD8F0 movwf TMR1H movlw 0xF0 movwf TMR1L bsf T1CON, TMR1ON ; Turn on timer 1 btfsc PORTB, 0x02 ; Toggle port B, bit 2 to goto ClearB2 ; check interrupt timing bsf PORTB, 0x02 goto FinishB2Tog ClearB2 bcf PORTB, 0x02 FinishB2Tog bsf BYTE_FLAGS1, TWO_MILLI_FLAG ; Set 2 ms routine flag decf INTERRUPT_COUNT, 1 ; Decrement count bcf PIR1, TMR1IF ; Clear TMR1 interrupt flag goto IntPoll ; Before leaving, check other sources ;*********************************************************************** ;******* TABLES ************************************************** ;*********************************************************************** ; No tables used in this program ;*********************************************************************** ;******* MAIN PROGRAM ******************************************** ;*********************************************************************** Start call Init ; Initializations clrf ONE_SEC_COUNT ; clear 1 sec count movlw 0x32 ; reset count for creating 100 ms routine movwf INTERRUPT_COUNT movlw 0x0A ; reset count for creating 1 sec routines movwf HUN_MILLI_COUNT ; movlw 0xFF ; Load timer 1 with 0xFFF0 movlw 0xD8 ; Load timer 1 with 0xD8F0 movwf TMR1H movlw 0xF0 movwf TMR1L bsf T1CON, TMR1ON ; Turn on timer 1 bcf PORTB, 0x01 ; Turn on LED MainLoop ; Main loop btfss BYTE_FLAGS1, TWO_MILLI_FLAG ; See if ready for 2 ms ; routine goto Continue0 ; if not continue call TWO_MILLI_ROUTINE ; if so go to 2 ms routine Continue0 movf INTERRUPT_COUNT,1 ; Copy int_count to itself btfss STATUS, Z ; see if it is zero goto Continue1 ; if not continue movlw 0x32 ; if so load it with 50 movwf INTERRUPT_COUNT decfsz HUN_MILLI_COUNT,1 ; decrement 100 ms count goto Resume ; do not reset 100 ms count movlw 0x0A ; reset 100 ms count if it movwf HUN_MILLI_COUNT ; is 0 call ONE_SEC_ROUTINE ; go to 1 sec routine Resume call HUN_MILLI_ROUTINE ; and go to 100 ms routine Continue1 goto MainLoop ;*********************************************************************** ;******* SUBROUTINES ********************************************* ;*********************************************************************** ;******* INITIALIZATIONS ******* Init clrf PORTB ; Clear port B data latch bcf STATUS, RP1 ; Select bank 1 bsf STATUS, RP0 movlw 0x00 ; Value for data direction movwf TRISB ; Set port B as all outputs bcf STATUS, RP1 ; Select bank 0 bcf STATUS, RP0 movlw 0xC0 ; 7-1 GIE, Enable interrupts ; 6-1 PEIE, Enable Peripheral interrupts ; 5-0 T0IE, Disable TMR0 overflow interrupt ; 4-0 INTE, Disable RB0/INT external interrupt ; 3-0 RBIE, Disable RB port change interrupt ; 2-0 T0IF, Clear TMR0 overflow flag ; 1-0 INT0IF, Clear RB0/INT interrupt flag movwf INTCON ; 0-0 RBIF, Clear RB7:RB4 change-state flag bcf STATUS, RP1 ; Select bank 1 bsf STATUS, RP0 movlw 0x01 ; 7-0 Disable parallel slave port R/W interrupt ; 6-0 Disable A/D interrupt ; 5-0 Disable USART receive interrupt ; 4-0 Disable USART transmit interrupt ; 3-0 Disable Sync serial port interrupt ; 2-0 Disable CCP1 interrupt ; 1-0 Disable TMR2 to PR2 match interrupt movwf PIE1 ; 0-1 Enable TMR1 overflow interrupt movlw 0x00 ; 7-0 Unimplemented ; 6-0 Reserved, should always be clear ; 5-0 Unimplemented ; 4-0 EEIE, EEPROM Write int disabled ; 3-0 Disable Bus collision interrupt ; 2-0 Unimplemented ; 1-0 Unimplemented movwf PIE2 ; 0-0 Disable CCP2 interrupt ; Timer 1 used in this program for 2ms intterrupt bcf STATUS, RP1 ; Select bank 0 bcf STATUS, RP0 bcf PIR1, TMR1IF ; Clear timer 1 overflow flag return ;******* 2 MILLISECOND ROUTINE, 500 Hz ******* TWO_MILLI_ROUTINE btfsc PORTB, 0x04 ; Toggle G1 bit to compare 2 ms interrupt goto ClearB4 ; timing to 2 ms routine timing bsf PORTB, 0x04 goto FinishB4Tog ClearB4 bcf PORTB, 0x04 FinishB4Tog bcf BYTE_FLAGS1, TWO_MILLI_FLAG ; Clear 2 ms routine flag return ;******* 100 MILLISECOND ROUTINE, 10 Hz ******* HUN_MILLI_ROUTINE btfsc PORTB, 0x03 ; Toggle B3 bit to check 100 ms timing goto ClearB3 bsf PORTB, 0x03 goto FinishB3Tog ClearB3 bcf PORTB, 0x03 FinishB3Tog return ;******* 1 SECOND ROUTINE, 1 Hz ******* ONE_SEC_ROUTINE btfsc PORTB, 0x01 ; Toggle port B, bit 1 (LED) to goto ClearB1 ; check 1 sec timing bsf PORTB, 0x01 goto FinishB1Tog ClearB1 bcf PORTB, 0x01 FinishB1Tog incf ONE_SEC_COUNT, 1 ; Increment 1 sec count return ;*********************************************************************** ;*********************************************************************** END ; required directive ;*********************************************************************** ;***********************************************************************