;; Хронограф с выводом результата на LCD дисплей (8х2 в одну строку) и COM порт. ;; Распиновка микросхемы ;; PIN I/O FROM TO ;;---------------------------------------------------------------------- ;; A0 O E LCD E ;; A1 O RS LCD RS ;; A2 I BIT 2 SENSOR_1 ;; A3 I BIT 3 SENSOR_2 ;; A4 O ;; A5 O ;; A6 O ;; A7 O ;; ;; B0 0 ;; B1 I RS232 RX PC RX ;; B2 O RS232 TX PC TX ;; B3 O ;; B4 O BIT 4 LCD BIT 4 ;; B5 O BIT 5 LCD BIT 5 ;; B6 O BIT 6 LCD BIT 6 ;; B7 O BIT 7 LCD BIT 7 ;;---------------------------------------------------------------------- list p=16F628A #include #include __CONFIG _LVP_OFF & _MCLRE_OFF & _XT_OSC & _BODEN_OFF & _CP_OFF & _WDT_OFF & _PWRTE_ON ERRORLEVEL -302 #DEFINE E PORTA, 0 ;; OUTPUT TO LCD #DEFINE RS PORTA, 1 ;; OUTPUT TO LCD #DEFINE SENSOR_1 PORTA, 2 ;; INPUT #DEFINE SENSOR_2 PORTA, 3 ;; INPUT CBLOCK 0X20 CNTJ ;; FOR MS_DELAY ; BIT8, CNT1, CNT2, TEMP_MUL, HI16, LO16 ;; FOR MUL_BY_1000 MS_TIME, MS_TIME_TEMP LO_BYTE, HI_BYTE ;; FOR LCD DRIVER CHAR ;; FOR DATA CONVERTION TEN_K, THOU, HUND, TENS, ONES DIVIDEND1, DIVIDEND2, DIVIDEND3, DIVISOR1, DIVISOR2 DVDEND_HI, DVDEND_LO TIME_HI, TIME_LO, NUMH, NUML IF_ERROR ;; Признак ошибки ENDC ACC EQU 0x5C ; Most significant Byte SIGN EQU 0x62 ; save location for sign in MSB TEMP EQU 0x68 ; temporary storage DIVIDEND EQU 0x5C ; Most significant Byte DIVISOR EQU 0x65 ; Most significant Byte REMAIN EQU 0x60 ; Most significant Byte LOOPCOUNT EQU 0x63 ; loop counter ORG 0x000 CALL init_pic GOTO MAIN ORG 0x004 GOTO int_t init_pic ;----------------------------PORT I/O CONFIGURATION/SETUP------------------------------- BANK0 MOVLW 0X07 MOVWF CMCON ;; DISABLE CAPTURE/COMPARE MODULES. BANK1 LOADF TRISA, B'00101100' LOADF TRISB, B'00000110' ;; SET BITS 1, 2 FOR USART. BSF OPTION_REG, NOT_RBPU ;; BCF/BSF = ENABLE/DISABLE PULL-UP. ;------------------POWER ON RESET CONFIGURATION/SETUP-------------------------- BSF PCON, OSCF ;BCF/BSF = 37KHZ/4MHZ INTRC OR ER OSCILLATOR SPEED. ;--------------------------INTERRUPT CONFIGURATION/SETUP------------------------------- ; BANK1 ; BCF INTCON, GIE ;BCF/BSF = DIS/ENABLE GLOBAL INTERRUPT. ; BCF INTCON, PEIE ;BCF/BSF = DIS/ENABLE Разрешение прерываний от переферийных модулей ; BCF INTCON, T0IE ;BCF/BSF = DIS/ENABLE Разрешение прерывания по переполнению TMR0 ; BCF INTCON, INTE ;BCF/BSF = DIS/ENABLE RB0 INTERRUPT. ; BCF INTCON, RBIE ;BCF/BSF = DIS/ENABLE RB7-4 INTERRUPT. BSF PIE1, TMR1IE ;BCF/BSF = DIS/ENABLE Разрешение прерывания по переполнению TMR1 ;-------------------------------------------------------------------------------------- ;-------------------------USART CONFIGURATION/SETUP------------------------------------ BANK1 BCF PIE1, TXIE ;BCF/BSF = DIS/ENABLE TX INTERRUPT. BSF TXSTA, CSRC ;BCF/BSF = EXT/INTERNAL GENERATOR. BCF TXSTA, TX9 ;BCF/BSF = 8-BIT/9-BIT TRANSMISSION. BSF TXSTA, TXEN ;BCF/BSF = DIS/ENABLE TRANSMISSION. BCF TXSTA, SYNC ;BCF/BSF = A/SYNCHRONOUS MODE. BSF TXSTA, BRGH ;BCF/BSF = LO/HI SPEED BAUD RATE SELECT. LOADF SPBRG, .12 ;SET BAUD RATE TO 19.2 KBPS. BANK0 BSF RCSTA, SPEN ;BCF/BSF = DIS/ENABLE SERIAL PORT. BCF RCSTA, RX9 ;BCF/BSF = 8-BIT/9-BIT TRANSMISSION. BSF RCSTA, SREN ;BCF/BSF = DIS/ENABLE SINGLE RECEIVE. BCF RCSTA, CREN ;BCF/BSF = DIS/ENABLE CONTINUOS RECEIVE. BSF RCSTA, SPEN ;BCF/BSF = DIS/ENABLE SERIAL PORT. ;-------------------------------------------------------------------------------------- RETURN ;*********************MAIN*********************** MAIN: CALL INIT_LCD ERR_TEST: CALL CLEAR CALL GET_ERROR BTFSC IF_ERROR, 7 GOTO ERR_TEST CALL CLEAR CALL LCD_1 GET: CALL GET_VELOCITY CALL SEND_USART CALL LCD_UPDATE GOTO GET ;*****************END 0F MAIN****************** int_t BCF T1CON, TMR1ON ;BCF/BSF = DISABLE/ENABLE TIMER1 ON. BCF PIE1, TMR1IF ;BCF/BSF = DISABLE/ENABLE Разрешение прерывания по переполнению TMR1 CLRF TMR1L ;; THEN, START TIMING. CLRF TMR1H MOVF_F TMR1L, TIME_LO ;; FINALY, COPY TIMER1 INTO LO/HI BYTES. MOVF_F TMR1H, TIME_HI GOTO ERR_TEST ;Проверяем датчики GET_ERROR: ;; DUAL SENSOR DETECTION. BCF IF_ERROR, 7 LOADF CHAR, 0X00 CALL SET_ADDRESS BTFSS SENSOR_1 GOTO $ + 3 CALL D1_ER GOTO $ + 2 CALL D1_OK LOADF CHAR, 0X40 CALL SET_ADDRESS BTFSS SENSOR_2 GOTO $ + 3 CALL D2_ER GOTO $ + 2 CALL D2_OK LOADF MS_TIME, .250 ;; 1.5 SEC DELAY. CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY RETURN D1_OK: CHR_LCD_OUT 'D' CHR_LCD_OUT '1' CHR_LCD_OUT '-' CHR_LCD_OUT 'O' CHR_LCD_OUT 'K' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' RETURN D1_ER: CHR_LCD_OUT 'D' CHR_LCD_OUT '1' CHR_LCD_OUT '-' CHR_LCD_OUT 'E' CHR_LCD_OUT 'R' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' BSF IF_ERROR, 7 RETURN D2_OK: CHR_LCD_OUT 'D' CHR_LCD_OUT '2' CHR_LCD_OUT '-' CHR_LCD_OUT 'O' CHR_LCD_OUT 'K' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' RETURN D2_ER: CHR_LCD_OUT 'D' CHR_LCD_OUT '2' CHR_LCD_OUT '-' CHR_LCD_OUT 'E' CHR_LCD_OUT 'R' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' CHR_LCD_OUT ' ' BSF IF_ERROR, 7 RETURN ;--------------------------------------- ;Первоначальная надпись на LCD LCD_1: LOADF CHAR, 0X00 CALL SET_ADDRESS CHR_LCD_OUT 'A' CHR_LCD_OUT 'W' CHR_LCD_OUT 'A' CHR_LCD_OUT 'I' CHR_LCD_OUT 'T' CHR_LCD_OUT ' ' CHR_LCD_OUT '-' CHR_LCD_OUT ' ' LOADF CHAR, 0X40 CALL SET_ADDRESS CHR_LCD_OUT 'S' CHR_LCD_OUT 'H' CHR_LCD_OUT 'O' CHR_LCD_OUT 'O' CHR_LCD_OUT 'T' CHR_LCD_OUT '!' CHR_LCD_OUT '!' CHR_LCD_OUT '!' RETURN ;--------------------------------------- ;DETECTION AND TIMING OF PROJECTILE GET_VELOCITY: ;; DUAL SENSOR DETECTION. CLRF TMR1L ;; THEN, START TIMING. CLRF TMR1H BSF INTCON, GIE ;BCF/BSF = DISABLE/ENABLE Глобальное разрешение прерываний BSF INTCON, PEIE ;BCF/BSF = DIS/ENABLE Разрешение прерываний от переферийных модулей BTFSS SENSOR_1 ;; AWAIT DETECTION: ACTIVE HI. GOTO $ - 1 BSF T1CON, TMR1ON ;BCF/BSF = DISABLE/ENABLE TIMER1 ON. BTFSS SENSOR_2 ;; NEXT, AWAIT DETECTION: ACTIVE HI. GOTO $ - 1 BCF T1CON, TMR1ON ;BCF/BSF = DISABLE/ENABLE TIMER1 ON. BCF INTCON, GIE ;BCF/BSF = DISABLE/ENABLE Глобальное разрешение прерываний BCF INTCON, PEIE ;BCF/BSF = DIS/ENABLE Разрешение прерываний от переферийных модулей MOVF_F TMR1L, TIME_LO ;; FINALY, COPY TIMER1 INTO LO/HI BYTES. MOVF_F TMR1H, TIME_HI LOADF MS_TIME, .250 ;; 1 SEC DELAY BEFORE NEXT MEASUREMENT. CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY CALL MS_DELAY RETURN ;--------------------------------------- ;Отсылаем данные в RS232 SEND_USART: CALL TXWAIT MOVF_F TIME_HI, TXREG CALL TXWAIT MOVF_F TIME_LO, TXREG CALL TXWAIT RETURN ;--------------------------------------- ;Использовать эту задержку перед отправкой данных TXREG. TXWAIT: BANK1 BTFSS TXSTA, TRMT ;; IF TX IS COMPLETED, GOTO $ - 1 ;; ELSE, WAIT BANK0 ;; THEN, CONTINUE. LOADF MS_TIME, .1 CALL MS_DELAY RETURN ;-------------------------------------- ;Вычисление скорости и вывод на LCD LCD_UPDATE: CALL CLEAR MOVF_F TIME_HI, HI_BYTE MOVF_F TIME_LO, LO_BYTE CALL HEX16_TO_DEC5 ;; CONVERT HEX TO DECIMAL, CALL DEC_TO_LCD ;; THEN DECIMAL TO LCD DISPLAY. MEM_LCD_OUT TEN_K MEM_LCD_OUT THOU CHR_LCD_OUT '.' MEM_LCD_OUT HUND MEM_LCD_OUT TENS MEM_LCD_OUT ONES CHR_LCD_OUT 'm' CHR_LCD_OUT 's' ; CALL LCD_TO_DEC ;; CALCULATIONS TO METERS PER SECOND. ; LOADF BIT8, .40 ;; DETECTOR DISTANCE = 40 MILLI-METERS ; CALL MUL_BY_1000 ;; MULTIPLY DISTANCE MILLI-METERS BY 1000 ; ; MOVF_F HI16, DIVIDEND1 ;; DIVIDE MILLI-METERS BY TIMING ; MOVF_F LO16, DIVIDEND2 ;; 40,000 / TIME_HI:TIME_LO LOADF DIVIDEND1, 0x9C ;; Для дистанции 40мм LOADF DIVIDEND2, 0x40 ;; 40,000 / TIME_HI:TIME_LO MOVF_F TIME_HI, DIVISOR1 MOVF_F TIME_LO, DIVISOR2 CALL DIVIDE_16_16 ;; RETURNS DIVIDEND+0:DIVIDEND+1 MOVF_F DIVIDEND+0, HI_BYTE ;; VELOCITY RESULT COPY MOVF_F DIVIDEND+1, LO_BYTE ;; VELOCITY RESULT COPY CALL HEX16_TO_DEC5 CALL DEC_TO_LCD LOADF CHAR, 0X40 ;; GOTO LCD SECOND LINE. CALL SET_ADDRESS CHR_LCD_OUT ' ' MEM_LCD_OUT THOU ;; DISPLAY "XXXXX M/S" MEM_LCD_OUT HUND MEM_LCD_OUT TENS MEM_LCD_OUT ONES CHR_LCD_OUT 'm' CHR_LCD_OUT '/' CHR_LCD_OUT 's' ; CALL LCD_TO_DEC RETURN ;--------------------------------------- ;BORROWED FROM MICROCHIP APP NOTES. EXTENSIVELY ;MODIFIED TO SUPPORT 16F628. ;DIVIDE 16BIT BY 16BIT ;INPUT : DVDEND_HI, DVDEND_LO, DVSOR_HI, DVSOR_LO ;OUTPUT: DIVIDEND+0, DIVIDEND+1 ;----Define divide register variables--- ; ACC EQU 0x5C ; Most significant Byte ; SIGN EQU 0x62 ; save location for sign in MSB ; TEMP EQU 0x68 ; temporary storage ; DIVIDEND EQU 0x5C ; Most significant Byte ; DIVISOR EQU 0x65 ; Most significant Byte ; REMAIN EQU 0x60 ; Most significant Byte ; LOOPCOUNT EQU 0x63 ; loop counter ;--------------------------------------- DIVIDE_16_16: MOVF_F DIVIDEND1, DIVIDEND+0 MOVF_F DIVIDEND2, DIVIDEND+1 MOVF_F DIVISOR1, DIVISOR+0 MOVF_F DIVISOR2, DIVISOR+1 CLRF REMAIN+0 CLRF REMAIN+1 MOVLW .16 MOVWF LOOPCOUNT LOOP1616: RLF ACC+0, W RLF REMAIN+1, F RLF REMAIN+0, F MOVF DIVISOR+1, W SUBWF REMAIN+1, F MOVF DIVISOR+0, W BTFSS STATUS, C INCFSZ DIVISOR+0, W SUBWF REMAIN+0, F BTFSC STATUS, C GOTO CONT1616 MOVF DIVISOR+1, W ADDWF REMAIN+1, F MOVF DIVISOR+0, W BTFSC STATUS, C INCFSZ DIVISOR+0, W ADDWF REMAIN+0, F BCF STATUS, C CONT1616: RLF ACC+1, F RLF ACC+0, F DECFSZ LOOPCOUNT, F GOTO LOOP1616 RETURN ;--------------------------------------- ;MULTIPY 8-BIT BY 1000 ;INPUT = BIT8, ;OUTPUT = HI16, LO16 ;MUL_BY_1000: ; CLRF HI16 ; CLRF LO16 ; MOVF_F BIT8, TEMP_MUL ; LOADF CNT1, .100 ; LOADF CNT2, .10 ;MUL1 ; MOVF TEMP_MUL, W ; ADDWF LO16, F ; BTFSS STATUS, C ;; IF CARRY IS SET, ; GOTO $ + 2 ;; ELSE: SKIP ; INCF HI16, F ;; THEN: PROCESS ; ; DECFSZ CNT1, F ; GOTO MUL1 ; LOADF CNT1, .100 ; DECFSZ CNT2, F ; GOTO MUL1 ; RETURN ;--------------------------------------- ;CONVER 16BIT HEX INTO 5 DIGIT BCD ;INPUT : HI_BYTE, LO_BYTE ;OUTPUTS: TEN_K, THOU, HUND, TENS, ONES HEX16_TO_DEC5: MOVF_F HI_BYTE, NUMH ;; MOVF f,d Пересылка регистра F MOVF_F LO_BYTE, NUML SWAPF NUMH,W ;; SWAPF f,d Обмен местами тетрад в f ANDLW 0X0F ;; ANDLW k Логическое "И" константы и W ADDLW 0XF0 ;; ADDLW k Сложение константы с W MOVWF THOU ;; MOVWF f Пересылка W в F ADDWF THOU,F ;; ADDWF f,d Сложение W с f ADDLW .226 ;; ADDLW k Сложение константы с W MOVWF HUND ;; MOVWF f Пересылка W в F ADDLW .50 ;; ADDLW k Сложение константы с W MOVWF ONES ;; MOVWF f Пересылка W в F MOVF NUMH,W ;; MOVF f,d Пересылка регистра F ANDLW 0X0F ;; ANDLW k Логическое "И" константы и W ADDWF HUND,F ;; ADDWF f,d Сложение W с f ADDWF HUND,F ;; ADDWF f,d Сложение W с f ADDWF ONES,F ;; ADDWF f,d Сложение W с f ADDLW .233 ;; ADDLW k Сложение константы с W MOVWF TENS ;; MOVWF f Пересылка W в F ADDWF TENS,F ;; ADDWF f,d Сложение W с f ADDWF TENS,F ;; ADDWF f,d Сложение W с f SWAPF NUML,W ;; SWAPF f,d Обмен местами тетрад в f ANDLW 0X0F ;; ANDLW k Логическое "И" константы и W ADDWF TENS,F ;; ADDWF f,d Сложение W с f ADDWF ONES,F ;; ADDWF f,d Сложение W с f RLF TENS,F ;; RLF f,d Вращение f влево через перенос RLF ONES,F ;; RLF f,d Вращение f влево через перенос COMF ONES,F ;; COMF f,d Инверсия регистра f RLF ONES,F ;; RLF f,d Вращение f влево через перенос MOVF NUML,W ;; MOVF f,d Пересылка регистра F ANDLW 0X0F ;; ANDLW k Логическое "И" константы и W ADDWF ONES,F ;; ADDWF f,d Сложение W с f RLF THOU,F ;; RLF f,d Вращение f влево через перенос MOVLW 0X07 ;; MOVLW k Пересылка константы в W MOVWF TEN_K ;; MOVWF f Пересылка W в F MOVLW .10 ;; MOVLW k Пересылка константы в W HD1: ADDWF ONES,F ;; ADDWF f,d Сложение W с f DECF TENS,F ;; DECF f,d Декремент регистра f BTFSS 3,0 ;; BTFSS f,b Пропустить команду, если бит b=1 GOTO HD1 ;; GOTO k Переход по адресу HD2: ADDWF TENS,F ;; ADDWF f,d Сложение W с f DECF HUND,F ;; DECF f,d Декремент регистра f BTFSS 3,0 ;; BTFSS f,b Пропустить команду, если бит b=1 GOTO HD2 ;; GOTO k Переход по адресу HD3: ADDWF HUND,F ;; ADDWF f,d Сложение W с f DECF THOU,F ;; DECF f,d Декремент регистра f BTFSS 3,0 ;; BTFSS f,b Пропустить команду, если бит b=1 GOTO HD3 ;; GOTO k Переход по адресу HD4: ADDWF THOU,F ;; ADDWF f,d Сложение W с f DECF TEN_K,F ;; DECF f,d Декремент регистра f BTFSS 3,0 ;; BTFSS f,b Пропустить команду, если бит b=1 GOTO HD4 ;; GOTO k Переход по адресу RETURN ;--------------------------------------- ;PREREQUISITE: LOAD THOU, HUND, TENS, ONES ; ;LCD_TO_DEC: ; MOVLW 0X30 ; SUBWF TEN_K, F ; SUBWF THOU, F ; SUBWF HUND, F ; SUBWF TENS, F ; SUBWF ONES, F ; RETURN ;--------------------------------------- ;PREREQUISITE: LOAD TEN_K, THOU, HUND, TENS, ONES ; DEC_TO_LCD: MOVLW 0X30 ADDWF TEN_K, F ADDWF THOU, F ADDWF HUND, F ADDWF TENS, F ADDWF ONES, F RETURN ;----------------------------------------------- ; LCD DRIVER AND COMMANDS FOR 4-BIT INTERFACE ;----------------------------------------------- ;PREREQUISITES: E, RS - OUTPUT ; PORTB 4-7 - OUTPUT ; MS_DELAY - SUBROUTINE INIT_LCD: LOADF MS_TIME, .40 CALL MS_DELAY ;; FUNCTION SET BCF RS ;; SET LCD TO COMMAND MODE LOADF PORTB, B'00100000' CALL PULSE_E LOADF PORTB, B'00100000' CALL PULSE_E LOADF PORTB, B'10000000' CALL PULSE_E LOADF MS_TIME, .1 ;; DISPLAY CONTROL CALL MS_DELAY LOADF PORTB, B'00000000' CALL PULSE_E LOADF PORTB, B'11110000' CALL PULSE_E LOADF MS_TIME, .1 ;; CLEAR DISPLAY CALL MS_DELAY LOADF PORTB, B'00000000' CALL PULSE_E LOADF PORTB, B'00010000' CALL PULSE_E LOADF MS_TIME, .1 ;; ENTRY MODE SET, .2 CALL MS_DELAY LOADF PORTB, B'00000000' CALL PULSE_E LOADF PORTB, B'01100000' CALL PULSE_E LOADF MS_TIME, .2 CALL MS_DELAY CALL BLINK_OFF CALL CURSOR_OFF RETURN PULSE_E: BSF E GOTO $ + 1 GOTO $ + 1 GOTO $ + 1 BCF E LOADF MS_TIME, .1 CALL MS_DELAY RETURN ;------------------------------------------- ;INPUT : CHAR, 'X' ;OUTPUT: SENDS THE CHARACTER TO THE LCD ;SEND_CHAR: ; BSF RS ;; SET LCD TO CHARACTOR MODE ; MOVF CHAR, W ; MOVWF PORTB ; CALL PULSE_E ; SWAPF CHAR, W ; MOVWF PORTB ; CALL PULSE_E ; RETURN ;--------------------------------------- ;INPUT : CHAR, 'X' ;OUTPUT: SENDS THE COMMAND TO THE LCD SEND_CHAR: BSF RS ;; SET LCD TO CHARACTOR MODE GOTO $ + 2 SEND_COMM: BCF RS ;; SET LCD TO COMMAND MODE MOVF CHAR, W MOVWF PORTB CALL PULSE_E SWAPF CHAR, W MOVWF PORTB CALL PULSE_E RETURN ;--------------------------------------- MS_DELAY: MOVF_F MS_TIME, MS_TIME_TEMP CLEAR: LOADF CHAR, B'00000001' CALL SEND_COMM LOADF MS_TIME, .2 CALL MS_DELAY RETURN ;HOME: ; LOADF CHAR, B'00000010' ; CALL SEND_COMM ; LOADF MS_TIME, .2 ; CALL MS_DELAY ; RETURN SET_ADDRESS: BSF CHAR, 7 CALL SEND_COMM RETURN BLINK_OFF: LOADF CHAR, B'00001110' CALL SEND_COMM RETURN CURSOR_OFF: LOADF CHAR, B'00001100' CALL SEND_COMM RETURN ;--------------------------- END