;----------------------------------------------------------------------; ; this prog is setup to capture a pulse "ON" time in Num1_H,L and Num2_H,L ; the difference is the total "ON" time. ; Then a capture of "OFF" time in Num2_H,L and Num3_H,L ; the difference is the "OFF" time for a low pulse. ;----------------------------------------------------------------------; ; LIST P=16f876, F=INHX8M errorlevel - 301 ; no message 301 errorlevel - 302 ; no message 302 errorlevel - 305 ; no message 305 errorlevel - 306 ; no message 306 ;******************* ********************************************************** ; ; This program interfaces to a Hitachi HD77480-based LC-Display ; ; This program assembles for an 4-bit data interface. ; ; Fosc = 4M Hz ; Cycle_time = 1/ Fosc / 4 ; = 1/ (4*10^6) / 4 ; = 1u Sec ;******************* ********************************************************** include ;******************* ********************************************************** ; Define Information OSC_FREQ EQU D'4000000' ; Oscillator Frequency is 4 MHz LCD_DATA EQU PORTA ; LCD data lines interface LCD_DATA_TRIS EQU TRISA LCD_CTRL EQU PORTB ; LCD control lines interface #DEFINE LCD_RS PORTB, 1 #DEFINE LCD_E PORTB, 3 #DEFINE LCD_RW PORTB, 2 CBLOCK 20H LCD_TEMP ; a temporary variable temp temp1 temp2 temp3 temp4 char_h cntmsec ; holds character to be transmitted Num1_H ; holds count of bits when transmitting Num1_L ; used in counting milliseconds Num2_H ; holds count of bits when transmitting Num2_L ; used in counting milliseconds Num3_H ; holds count of bits when transmitting Num3_L ; used in counting milliseconds Num4_H ; holds count of bits when transmitting Num4_L ; used in counting milliseconds bitcnt digcnt Digt_1 Digt_2 Digt_3 Digt_4 Digt_5 Digt_6 Digt_7 Digt_8 ENDC ORG 4 ;***************************************************************************** ; Initialize processor registers ;***************************************************************************** CLRF STATUS ; Do initialization, Select bank 0 CLRF INTCON ; Clear int-flags, Disable interrupts CLRF PCLATH ; Keep in lower 2KByte MOVLW B'00000000' MOVWF PORTA MOVLW B'00000000' MOVWF PORTB MOVLW B'00000000' MOVWF PORTC clrf CCP1CON clrf TMR1H clrf TMR1L BSF STATUS,RP0 ;set to bank 1 MOVLW B'00000000' MOVWF TRISA MOVLW B'00000000' MOVWF TRISB MOVLW B'00000100' MOVWF TRISC clrf PIE1 BCF STATUS, RP0 ; Select bank 0 clrf PIR1 clrf CCPR1L clrf CCPR1H MOVLW B'00100001' ;prescale 4:1 MOVWF T1CON ; bsf T1CON,TMR1ON ;*************************************** Main call Lcd_Init ;initialize LCD display call Lcd_Clr movlw 0x28 ; DELAY IN msec call nmsec call Open_Msg movlw 0x28 ; DELAY IN msec call nmsec movlw 0x28 ; DELAY IN msec call nmsec movlw 0x28 ; DELAY IN msec call nmsec call Lcd_Clr movlw 0x28 ; DELAY IN msec call nmsec call Text_Disp ;*************************************** Set_Rise_Edge MOVLW B'00000101' ; this sets the capture module to detect rising edges MOVWF CCP1CON Rise_Edge btfss PIR1,CCP1IF ; This loop looks for the first rising edge and goto Rise_Edge ; when it is found timer1 values are put in Num1_H,l movf CCPR1H,w movwf Num1_H movf CCPR1L,w movwf Num1_L clrf CCP1CON ; TURNS CAPTURE MODULE OFF clrf CCPR1H clrf CCPR1L movlw B'00000100' ; this sets the capture module to detect falling edges movwf CCP1CON bcf PIR1,CCP1IF ; This loop looks for the first falling edge and ;*************************************** Fall_Edge btfss PIR1,CCP1IF ; when it is found timer1 values are put in Num2_H,l goto Fall_Edge movf CCPR1H,w movwf Num2_H movf CCPR1L,w movwf Num2_L clrf CCP1CON ; TURNS CAPTURE MODULE OFF clrf CCPR1H clrf CCPR1L movlw B'00000101' ; this sets the capture module to detect rising edges movwf CCP1CON bcf PIR1,CCP1IF ;*************************************** Rise_Edge1 btfss PIR1,CCP1IF ; This loop looks for the first rising edge and goto Rise_Edge1 ; when it is found timer1 values are put in Num3_H,l movf CCPR1H,w movwf Num3_H movwf Num4_H movf CCPR1L,w movwf Num3_L movwf Num4_L clrf CCP1CON ; TURNS CAPTURE MODULE OFF ;************************************ subtract routine for pulse at logic zero ********* movf Num2_L,w subwf Num3_L ;result, pulse width low byte movf Num2_H,w btfss STATUS,C incfsz Num2_H,w subwf Num3_H ;result, pulse width high byte ;************************************ subtract routine for pulse at logic one ********* movf Num1_L,w subwf Num2_L ;result, pulse width low byte movf Num2_L,w movwf temp1 movf Num1_H,w btfss STATUS,C incfsz Num1_H,w subwf Num2_H ;result, pulse width high byte movf Num2_H,w movwf temp2 bcf PIR1,CCP1IF ;***************************************************************************** Disp_Data movlw 0x8A ; Sets up display for "ON" time pulse width readout call Send_Cmd clrf Num1_H movlw 0x19 movwf Num1_L call Divide call Hex2Dec_Cv2 call Disp4_dgt ;***************************************************************************** ;***************************************************************************** movf Num3_H,w ; Sets up display for "OFF" time pulse width readout movwf Num2_H movf Num3_L,w movwf Num2_L movlw 0xCA call Send_Cmd clrf Num1_H movlw 0x19 movwf Num1_L call Divide call Hex2Dec_Cv2 call Disp4_dgt ;***************************************************************************** goto Set_Rise_Edge ;***************************************************************************** Text_Disp movlw 0x81 call Send_Cmd movlw 0x02 ; ON TIME LCD MESSAGE call outmsg movlw 0xC1 call Send_Cmd movlw 0x03 ; OFF TIME LCD MESSAGE call outmsg movlw 0x91 call Send_Cmd movlw 0x05 ; ON TIME LCD MESSAGE call outmsg movlw 0xD1 call Send_Cmd movlw 0x05 ; ON TIME LCD MESSAGE call outmsg movlw 0x96 call Send_Cmd return ;*************************************************************************** ; DIVIDE ROUTINE is 16 Bit by 16 bit Num2_H,L/Num1_H,L = Num2_H,L ; ;*************************************************************************** Divide movfw Num1_L iorwf Num1_H,w skpnz return ;goto Div0 Division by zero ! movlw 0x10 ;16 bit division movwf bitcnt clrf temp2 ;Clear remainder clrf temp1 ;Clear remainder Dvloop clrc ;Set quotient bit to 0 rlf Num2_L ;Shift left dividend and quotient rlf Num2_H ;Msb into carry rlf temp1 ;and then into partial remainder rlf temp2 movfw Num1_H ;Compare partial remainder and divisor subwf temp2,w skpz goto Testgt ;Not equal so test if remdrH is greater movfw Num1_L ;High bytes are equal,compare low bytes subwf temp1,w Testgt skpc ;Carry set if remdr >= divis goto Remrlt movfw Num1_L ;Subtract divisor from partial remainder subwf temp1 skpc ;Test for borrow decf temp2 ;Subtract borrow movfw Num1_H subwf temp2 bsf Num2_L,0 ;Set quotient bit to 1 ;Quotient replaces dividend which is lost Remrlt decfsz bitcnt goto Dvloop clrz ;Clear error flag (z) return ;Return with z set if error ;************************************************************************** ;****************************************************************************** ; HEX_BINARY TO DECIMAL CONVERTER ROUTINE FOR 2 BYTES ; IN (Num2_L & Num2_H) ;****************************************************************************** Hex2Dec_Cv2 call Clr_Dig movlw 0x10 ;16 bits to do movwf bitcnt Bit_Lp2 rlf Num2_L ;Shift lsb into carry rlf Num2_H ;Shift msb into carry movlw Digt_1 movwf FSR ;Pointer to digits movlw 0x05 ;5 digits for display movwf digcnt Adj_Lp2 rlf INDF ;Shift digit 1 bit left movlw -0xA addwf INDF,w ;Check and adjust for decimal overflow skpnc movwf INDF incf FSR ;Next digit decfsz digcnt goto Adj_Lp2 decfsz bitcnt ;Next bit goto Bit_Lp2 return Clr_Dig clrf Digt_1 ;LSB clrf Digt_2 clrf Digt_3 clrf Digt_4 clrf Digt_5 ;MSB clrf Digt_6 clrf Digt_7 clrf Digt_8 return ;************************************************************************************ ; This routine deletes leading zeros to be displayed to LCD ; ;************************************************************************************ ;Disp5_dgt clrw ; subwf Digt_5,0 ; btfss STATUS,Z ; goto Data52_LCD ; call Blank_C Disp4_dgt clrw subwf Digt_4,0 btfss STATUS,Z goto Data42_LCD call Blank_C Disp3_dgt clrw subwf Digt_3,0 btfss STATUS,Z goto Data32_LCD call Blank_C Data22_LCD movf Digt_2,0 call Out_Data Disp_dp movlw 0x2E ; Decimal Point call Send_Char movf Digt_1,0 ; LSB call Out_Data return Data32_LCD movf Digt_3,0 ; MSB call Out_Data goto Data22_LCD Data42_LCD movf Digt_4,0 ; MSB call Out_Data goto Data32_LCD ;Data52_LCD ; movf Digt_5,0 ; MSB ; call Out_Data ; goto Data42_LCD ;************************************************************************************ ;***************************************************************************** ; Initialize the LCD ; ;***************************************************************************** Lcd_Init bcf LCD_RW call Dlay160 ; Wait 160 usecs before Sending 1st Time movlw 0x30 ; Reset Command call Send_Cmd ; Send the Command call Dlay160 ; Wait 160 usecs before Sending 1st Time movlw 0x30 ; Reset Command call Send_Cmd ; Send the Command call Dlay160 ; Wait 160 usecs before Sending 1st Time movlw 0x30 ; Reset Command call Send_Cmd ; Send the Command call Dlay160 ; Wait 160 usecs before Sending 2nd Time movlw 0x20 ; Set 4 Bit Mode call Send_Cmd ; Send the Command call Dlay160 ; Wait 160 usecs before Sending movlw 0x28 ; 4 bit, 2 Line, 5x7 font call Send_Cmd ; Send the Command movlw 0x10 ; display shift off call Send_Cmd ; Send the Command movlw 0x01 ; Clear the Display RAM call Send_Cmd ; Send the Command movlw 0x05 call nmsec ; Wait 40 msecs before Reset movlw 0x06 ; increment cursor call Send_Cmd ; Send the Command movlw 0x0C ; display on cursor off call Send_Cmd ; Send the Command return ;***************************************************************************** ; Sends character to LCD ; Required character must be in W ; ; Out_Data adds 30h to craracter to make it ASCII for display ;***************************************************************************** Out_Data addlw 0x30 Send_Char MOVWF LCD_TEMP ; Character to be sent is in W call Check_Busy ; Wait for LCD to be ready BCF LCD_RW ; Set LCD in read mode BSF LCD_RS ; Set LCD in data mode swapf LCD_TEMP, w ; Send the High Nybble movwf LCD_DATA BSF LCD_E ; LCD E-line High BCF LCD_E ; LCD E-line Low MOVF LCD_TEMP, W MOVWF LCD_DATA ; Send data to LCD BSF LCD_E ; LCD E-line High BCF LCD_E ; LCD E-line Low movlw 0x10 ; DELAY IN msec call nmsec RETURN ;***************************************************************************** ; Send_Cmd to LCD ; command must be in W ;***************************************************************************** Send_Cmd MOVWF LCD_TEMP ; Character to be sent is in W CALL Check_Busy ; Wait for LCD to be ready BCF LCD_RW ; Set LCD in read mode BCF LCD_RS ; Set LCD in command mode swapf LCD_TEMP, w ; Send the High Nybble movwf LCD_DATA BSF LCD_E ; LCD E-line High BCF LCD_E ; LCD E-line Low MOVF LCD_TEMP, W MOVWF LCD_DATA ; Send data to LCD BSF LCD_E ; LCD E-line High BCF LCD_E ; LCD E-line Low RETURN ;***************************************************************************** ; LCDBUSY ; Returns when LCD busy-flag is inactive ; OK ;***************************************************************************** Check_Busy BSF STATUS,RP0 ; Select Register page 1 MOVLW 0x0F ; Set PORTB 0-3 for input MOVWF LCD_DATA_TRIS BCF STATUS, RP0 ; Select Register page 0 BCF LCD_RS ; Set LCD for command mode BSF LCD_RW ; Setup to read busy flag BSF LCD_E ; LCD E-line High MOVF LCD_DATA, W ; Read busy flag + DDram address BCF LCD_E ; LCD E-line Low ANDLW 0x08 ; Check Busy flag, High = Busy BTFSS STATUS, Z GOTO Check_Busy BCF LCD_RW BSF STATUS, RP0 ; Select Register page 1 MOVLW 0x00 MOVWF LCD_DATA_TRIS ; Set PORTB for output BCF STATUS, RP0 ; Select Register page 0 RETURN ;***************************************************************************** ; Clears display and returns cursor to home position 00(upper-left corner). ;***************************************************************************** Lcd_Clr MOVLW 0x01 CALL Send_Cmd RETURN ;***************************************************************************** ; Returns cursor to home position. ; Returns display to original position (when shifted). ;***************************************************************************** Lcd_Home MOVLW 0x02 CALL Send_Cmd RETURN ;***************************************************************************** ; sends hex bites A/D result to LCD ;***************************************************************************** Lcd_Dsply movlw 0x81 call Send_Cmd movf temp1,w ; 8 bit a/d result call CONV_BYTE_HEX call Send_Char ; sends out LSB (hex) to LCD movf char_h,w call CONV_NIBBLE_HEX call Send_Char ; sends out MSB (hex) to LCD return ;***************************************************************************** ;***************************************************************************** Blank_C movlw 0x20 ;blank character call Send_Char ; sends out LSB (hex) to LCD return ; goto outch ;***************************************************************************** ; time delay routines ; ;***************************************************************************** Dlay160: movlw D'41' ; delay about 160 usec micro4 addlw H'FF' ; subtract 1 from 'W' btfss STATUS,Z ; skip when you reach zero goto micro4 ; more loops return nmsec: movwf cntmsec ; delay for N (in W) millisec msecloop: movlw D'254' ; load takes .9765625 microsec call micro4 ; by itself CALL takes ... ; 2 + 253 X 4 + 3 + 2 = 1019 ; 1019 * .977 = 995 microsec nop ; .98 microsec decfsz cntmsec, f ; .98 skip not taken, else 1.95 goto msecloop ; 1.95 here: total ~1000 / loop return ; final time through ~999 to here ; overhead in and out ignored ;*********************************************************************** Open_Msg movlw 0x83 ; OPENING DISPLAY LCD LOCATION call Send_Cmd movlw 0x01 ; OPENING DISPLAY LCD MESSAGE call outmsg return ;*********************************************************************** ; CONV_BYTE_HEX - Converts the byte in w to two ASCII hex digits ('0'-'9', 'A'-'F' ) ; Returns with top nibble ASCII digit in char_hi and the bottom one in W ;*********************************************************************** CONV_BYTE_HEX MOVWF char_h ; save byte temporarily SWAPF char_h,W CONV_NIBBLE_HEX ANDLW 0x0F ; mask out top nibble, preserv low nibble ADDLW 0xF6 ; add 246, to check if 0-9 or a-f, w=nibble+246 BTFSC STATUS,C ; if carry set then a-f ADDLW 0x07 ; carry set, then add 7, w=nibble+246+7 ;( note nibble known to be a-f ) ADDLW 0x3a ; then finally add 26 to get ASCII characters ; 1) w = low(nibble+246+26) = 28+nibble ( if 0-9 ) ; 2) w = low(nibble+246+7+26) = 35+nibble ( if a-f ) ; nibble converted to ASCII hex in w RETURN ;******************************************************************* outmsg clrf temp2 movwf temp3 outmsg1 bsf PCLATH,3 bcf PCLATH,4 call Msg_Ptr bcf PCLATH,3 bcf PCLATH,4 clrf PCLATH addlw 0 btfsc STATUS,Z return call Send_Char incf temp2, f goto outmsg1 ;******************************************************************* org 0x800 ;******************************************************************* Msg_Ptr movlw 0x08 movwf PCLATH movfw temp3 addwf PCL,F nop goto msgtxt1 goto msgtxt2 goto msgtxt3 goto msgtxt4 goto msgtxt5 goto msgtxt6 ; goto msgtxt7 ; goto msgtxt8 ; goto msgtxt9 ; goto msgtxt10 msgtxt1 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw 'P' retlw 'U' retlw 'L' retlw 'S' retlw 'E' retlw ' ' retlw 'W' retlw 'I' retlw 'D' retlw 'T' retlw 'H' retlw ' ' ; retlw 'A' ; retlw 'N' ; retlw 'D' ; retlw ' ' ; retlw 'D' ; retlw 'U' ; retlw 'T' ; retlw 'Y' ; retlw ' ' ; retlw 'C' ; retlw 'Y' ; retlw 'C' ; retlw 'L' ; retlw 'E' ; retlw ' ' retlw 'M' retlw 'O' retlw 'N' retlw 'I' retlw 'T' retlw 'O' retlw 'R' retlw 0x00 msgtxt2 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw 'O' retlw 'N' retlw ' ' retlw 'T' retlw 'I' retlw 'M' retlw 'E' retlw 0x00 msgtxt3 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw 'O' retlw 'F' retlw 'F' retlw ' ' retlw 'T' retlw 'I' retlw 'M' retlw 'E' retlw 0x00 msgtxt4 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw 'D' retlw 'U' retlw 'T' retlw 'Y' retlw ' ' retlw 'C' retlw 'Y' retlw 'C' retlw 'L' retlw 'E' retlw 0x00 msgtxt5 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw 'm' retlw 's' retlw 'e' retlw 'c' retlw 0x00 msgtxt6 movlw 0x08 movwf PCLATH movfw temp2 addwf PCL retlw '%' retlw 0x00 end