;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ls_test.asm ; ; By Adriaan Van Nuffel and Robin Reusens ; afvnuffe@vub.ac.be, rreusens@vub.ac.be ; ; 10 may 2005 ; ; This program tests if the LDR's work correctly. You have to point the laser ; on an LDR, and if they work, the number of the detector appears on the ; display (digits). ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LIST P=PIC16F877A #INCLUDE P16F877A.INC __CONFIG _CP_OFF & _DEBUG_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _XT_OSC ORG 0 ; *** Giving names to the used registers *** TIMER1 EQU H'20' ; For the Delay routine TIMER2 EQU H'21' SH_REG1 EQU H'22' ; Used for accessing the shift registers (SH_REG1 controls SH_REG2 EQU H'23' ; the left digit, SH_REG2 the right one) INSDIG_COUNTER EQU H'24' ; Used as counter in the INSERDIGITS subroutine SCORE_DEC1 EQU H'25' ; Used in main loop to test the binary to decimal conversion SCORE_DEC2 EQU H'26' A_SH_REG EQU H'27' ; Used for the conversion to a decimal number of the score A_DEC EQU H'28' ; Idem. RELAYS EQU H'29' ; This one stores what relays are triggered (=1) or not (=0) LDRS EQU H'2A' ; Used to check the status of the LDRs DIG_0 EQU H'70' ; The digits DIG_1 EQU H'71' DIG_2 EQU H'72' DIG_3 EQU H'73' DIG_4 EQU H'74' DIG_5 EQU H'75' DIG_6 EQU H'76' DIG_7 EQU H'77' DIG_8 EQU H'78' DIG_9 EQU H'79' ; *** Configure all pins *** RESET ; Outputs: ; ; RB5-RB0 (Actuation of the relays) ; RA0 -> DS Shift Register 1 (Data Send) ; RA1 -> DS Sh Reg 2 ; RA2 -> OE Sh Reg 1&2 (Output Enable, active low) ; RA3 -> ST_CP Sh Reg 1&2 (Storage register clock pulse) ; RA4 -> SH_CP Sh Reg 1&2 (Shift register clock pulse) ; ; Inputs: ; ; RD2-RD7 (From comparators) ; ; Not used: ; ; RA5, RE0-RE2, RC0-RC3, RC4-RC7, RD0-RD1 (= 14 pins) ; RB6 & RB7 are only connected to the programming pins ; BCF STATUS, RP0 ; Go to Bank 0 BCF STATUS, RP1 CLRF PORTA ; Initialize Port A (See example datasheet p 41) CLRF PORTB ; " " B CLRF PORTD ; " " D (I'm not sure if all this is necessary...) BSF STATUS, RP0 ; Go to Bank 1 MOVLW B'00000110' ; Adjust the settings in ADCON1, to make all the pins MOVWF ADCON1 ; of port A digital I/O. See datasheet ('ds', from now on) p.128 MOVLW B'11000000' ; All pins of A are outputs, except RA7 and RA6, which MOVWF TRISA ; are non-existant CLRF TRISB ; All pins of port B are outputs. BCF TRISE, PSPMODE ; Port D pins are digital I/O. (ds p. 50) MOVLW B'11111111' ; And they are all inputs (but RD0 and RD1 MOVWF TRISD ; are not used.) ; *** Defining the digits *** BCF STATUS, RP0 ; Go to Bank 0 MOVLW B'01111011' MOVWF DIG_0 MOVLW B'01100000' MOVWF DIG_1 MOVLW B'00110111' MOVWF DIG_2 MOVLW B'01110110' MOVWF DIG_3 MOVLW B'01101100' MOVWF DIG_4 MOVLW B'01011110' MOVWF DIG_5 MOVLW B'01011111' MOVWF DIG_6 MOVLW B'01110000' MOVWF DIG_7 MOVLW B'01111111' MOVWF DIG_8 MOVLW B'01111110' MOVWF DIG_9 CLRF SCORE_DEC1 CLRF SCORE_DEC2 ; *** Main part *** ; We start by letting the digits blink. Then an infinite loop starts. MOVF DIG_0, 0 MOVWF SH_REG1 ; First we show zero's... MOVWF SH_REG2 CALL INSERTDIGITS CALL DELAY CALL DELAY CALL DELAY CALL DELAY BSF PORTA,H'2' ; Output disable: lettin' it blink a bit... CALL DELAY BCF PORTA,H'2' ; Output enable again... CALL DELAY BSF PORTA,H'2' CALL DELAY BCF PORTA,H'2' ; and after two 'blinks': output enabled again... MOVF DIG_0, 0 ; Store a zero in the left digit. MOVWF SH_REG1 mainloop MOVF PORTD, 0 ; The number zero is substracted from Port D, and if SUBLW B'00000000' ; the result is 0 (zero-bit = 1), we know none of the LDRs BTFSS STATUS, Z ; was hit. So we can return to the start of the loop, and CALL CHECK_LDRS ; check things again. Otherwise, we have to go check which LDR was hit. GOTO mainloop ; *** CHECK_LDRS ; This routine tests which LDR is hit, and displays the corresponding number. CHECK_LDRS MOVWF LDRS BTFSS LDRS, H'2' GOTO test_LDR_port_RD3 MOVF DIG_1, 0 MOVWF SH_REG2 GOTO end_check_ldrs ; We assume that you can't hit two LDRs simultaneously test_LDR_port_RD3 BTFSS LDRS, H'3' GOTO test_LDR_port_RD4 MOVF DIG_2, 0 MOVWF SH_REG2 GOTO end_check_ldrs test_LDR_port_RD4 BTFSS LDRS, H'4' GOTO test_LDR_port_RD5 MOVF DIG_3, 0 MOVWF SH_REG2 GOTO end_check_ldrs test_LDR_port_RD5 BTFSS LDRS, H'5' GOTO test_LDR_port_RD6 MOVF DIG_4, 0 MOVWF SH_REG2 GOTO end_check_ldrs test_LDR_port_RD6 BTFSS LDRS, H'6' GOTO test_LDR_port_RD7 MOVF DIG_5, 0 MOVWF SH_REG2 GOTO end_check_ldrs test_LDR_port_RD7 BTFSS LDRS, H'7' GOTO end_check_ldrs MOVF DIG_6, 0 MOVWF SH_REG2 end_check_ldrs CALL INSERTDIGITS ; Show the correct number that was hit. RETURN ; *** INSERTDIGITS: This subroutine 'inserts' the correct bits in the shift registers *** INSERTDIGITS BCF STATUS, RP0 ; Go to Bank 0 (in case we weren't there yet...) BCF STATUS, RP1 BSF INSDIG_COUNTER, H'3' ; 8 is the value, and we stick it in a counter! insdigloop CLRF PORTA ; (Remark: OE is active low, so clearing port A will enable the output) RLF SH_REG1,1 ; Check the next bit BTFSC STATUS, C ; and if it's set, then set the RA0 BSF PORTA, H'0' ; (which is connected to the DS of the first shift register). RLF SH_REG2,1 ; Now we do the same for the second shift register. BTFSC STATUS, C BSF PORTA, H'1' ; RA1 is connected to the DS of the second shift register. BSF PORTA, H'4' ; Then we give a pulse on the clock of the shift registers (SH_CP) DECFSZ INSDIG_COUNTER, 1 GOTO insdigloop BSF PORTA, H'3' ; Now we give a pulse on the clock of the storage registers (ST_CP) to show the result. RETURN ; End of subroutine ; *** Delay routine *** DELAY CLRWDT MOVLW D'255' MOVWF TIMER1 DELAY2 MOVLW D'255' MOVWF TIMER2 DECFSZ TIMER2,F GOTO $-1 DECFSZ TIMER1,F GOTO DELAY2 RETLW 0 END ; End of source code.