list p=PIC16F873A #include P16F873A.inc ; ; 16.000 MHz __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON& _HS_OSC &_LVP_OFF &_CPD_OFF errorlevel -302 #define sin_ok Modes,0 ;ако сме определили синхро импулс #define sin_fal Modes,1 ;ако е инало синхрониация и е пропаднала #define ready_in Modes,2 ;ако е минал цял цикъл приемане и ; ако е запазена и синхронизацията => прехвърля buf_in в buf_r #define sub_proc Modes,4 #define Carry_fl Modes,5 ;използва се за да се запази състоянието на преноса при ;блоковата обработка на информацията #define cin PORTC,2 #define stmacro_ st macro v #ifdef stmacro CBLOCK 0x79 mtot:2 ;за stmacro endc movlw v & H'FF' ;Mask to get LSB addwf mtot+1,f btfsc STATUS,C incf mtot,f movlw v >>D'08' & H'FF' addwf mtot,f call delay_200iS movf mtot,w movwf TMR1H movwf CCPR1H movf mtot+1,w movwf TMR1L movwf CCPR1L bsf PIR1,CCP1IF #else nop nop #endif endm ; -------------------------------------------------- CBLOCK 0x7B W_TEMP ;storage for WREG during interrupt STATUS_TEMP ;storage for STATUS during interrupt PCLATH_TEMP ;storage for PCLATH during interrupt FSR_TEMP ;storage for FSR during interrupt Modes endc ;0x7F CBLOCK 0x20 CCP1_Mode ;съхраняваме режима на работа на CCP1 DigVal ;цифрови изходи buf_r:.30 ;СИ + СП + 6 аналогови + 6 цифрови + СИ CCP1_buf:.2 ;буфер за съхранение на CCP1 CCP1_prev:2 ;буфер за съхранение на CCP1 CCP1_Ti:2 ;буфер за изчислената продължителност на импулса in_pass ;брояч на миналите приемания на информацията CCP1_Tmp ;временна променлива за работа в CCP1 buf_CCP2:12 ;тук ще се съхранява информацията за стойностите за машинките Calc_CCP2:2 ;изчисленото CCP2 - къде трябва да спре машинката CCP2_pass ;за цикъла за обработка на стойностите CCP2_tmp:2 ;временна променлива dig_tmp ;временна промелива за цифровите сигнали pass_ix ;брояч за указване коя машинка пускаме PPM_ix ;указател за пуснатата машинка eed ;променлива за работа с EEPROM d1 ;ЗА ЗАКЪСНЕНИЕТО d2 endc org 0x0000 start nop goto main nop nop org 0x0004 goto interrupt main bsf STATUS, RP0 ;bank 1 movlw b'00000111' movwf CMCON ; компараторите - изключени movlw 0x06 movwf ADCON1 movlw 0xc0 ;6 изхода за дискретни команди movwf TRISA movlw b'11000000' ;6 изхода за аналогови команди movwf TRISB movlw b'11111111' ;всички входове movwf TRISC bsf PIE1,CCP1IE ;enable interrupt CCP1 bsf PIE2,CCP2IE ;enable interrupt CCP2 ;ще се пусне за първи път след приемане на пълен пакет данни bcf PIE2,EEIE ;disable interrupt EEPROM bcf PIE1,TMR1IE ;disable interrupt TMR1 bsf PIE1,TMR2IE ;disable interrupt TMR2 ;ще се пусне за първи път след приемане на пълен пакет данни movlw .118 movwf PR2 ; Fosc/(4*16*(118+1)*7) = 0.0033 S movlw b'01000111' ; вкл притягащите резистори, movwf OPTION_REG ; TMR0 с предделител 256 bcf STATUS, RP0 ;bank 0 bcf INTCON,TMR0IE ;disable interrupt TMR0 movlw b'00110001' movwf T1CON ; TMR1 - Fosc/4, prescale 8,TMR1 включено movlw b'00110010' movwf T2CON ; TMR2 - Fosc/4, prescale 16*(118+1)*7,TMR2 включено ;очаква се да предизвиква прекъсване на 3.3 mS clrf ADCON0 ;ADC изключено movlw b'00000100' ; movwf CCP1_Mode ;запазваме си режима на работа на CCP1 clrf CCP1CON ; Capture mode, every rising clrf CCP2CON ;спираме CCP2 bsf INTCON,PEIE ;enable interrupt's bsf INTCON,GIE ;enable interrupt's clrf PORTA goto end_test_start test_start ;PORTC,2 е установен като изход clrf CCP1CON ;спираме CCP1 bsf STATUS, RP0 ;bank 0 bcf PIE2,CCP2IE ;enable interrupt CCP2 bcf PIE1,CCP1IE ;enable interrupt CCP1 bcf STATUS, RP0 ;bank 0 movf CCP1_Mode,w ;запазваме си режима на работа на CCP1 movwf CCP1CON ; Capture mode, every rising ttt nop nop nop goto $-2 bsf Modes,6 btfss PORTC,2 bcf Modes,6 ; bsf PORTC,2 movlw 0xeb movwf TMR1H movlw 0xd0 movwf TMR1L btfss Modes,6 bsf PORTC,2 btfsc Modes,6 bcf PORTC,2 call Delay_19k rise nop btfsc cin goto check_rise goto rise check_rise nop btfss cin goto rise goto capture fall nop btfsc cin goto check_fall goto fall check_fall nop btfss cin goto fall goto capture capture ; movlw 1 ;xorwf CCP1CON ,f bsf Modes,6 btfss PORTC,2 bcf Modes,6 ; bsf PORTC,2 movlw 0xf5 movwf TMR1H movlw 0x90 movwf TMR1L btfss Modes,6 bsf PORTC,2 btfsc Modes,6 bcf PORTC,2 call Delay_19k bsf Modes,6 btfss PORTC,2 bcf Modes,6 ; bsf PORTC,2 movlw 0xff movwf TMR1H movlw 0x50 movwf TMR1L btfss Modes,6 bsf PORTC,2 btfsc Modes,6 bcf PORTC,2 call Delay_19k ; movlw 1 ;xorwf CCP1CON ,f nop st 0x0603 ;1 nop ts_loop st 0x09c0 ;2 nop st 0x07c0 ;3 nop st 0x0501 ;4 nop st 0x0300 ;5 nop st 0x0302 ;6 nop st 0x0180 ;7 nop st 0x0603 ;8 nop st 0x0180 ;9 nop st 0x0504 ;10 nop st 0x0300 ;11 nop st 0x0405 ;12 nop st 0x0180 ;13 nop st 0x06a6 ;14 nop st 0x0300 ;15 nop goto ts_loop end_test_start #ifdef stmacro movlw 0xff movwf mtot movlw 0x50 movwf mtot+1 #endif movlw 1 movwf PPM_ix ;подготвяме за пускане първата машинка bcf sin_ok clrf DigVal clrf in_pass clrf Modes clrf pass_ix movf CCP1_Mode,w ;запазваме си режима на работа на CCP1 movwf CCP1CON ; Capture mode, every rising main_loop st 0x09c0 ;2 nop st 0x07c0 ;3 nop st 0x0581 ;4 nop st 0x0300 ;5 nop st 0x0382 ;6 nop st 0x0180 ;7 nop st 0x0683 ;8 nop st 0x0180 ;9 nop st 0x0584 ;10 nop st 0x0180 ;11 nop st 0x0485 ;12 nop st 0x0180 ;13 nop st 0x06a6 ;14 nop st 0x0300 ;15 nop nop nop nop nop nop nop nop goto main_loop interrupt bcf INTCON, PEIE ; turn off interupts movwf W_TEMP swapf STATUS,w movwf STATUS_TEMP clrf STATUS movf PCLATH,w ;save PCLath movwf PCLATH_TEMP clrf PCLATH ;assume that this ISR is in page 0 movf FSR,w movwf FSR_TEMP interrupt_TMR1 btfss PIR1,TMR1IF goto interrupt_CCP2 ; goto interrupt_TMR2 ; не е от TMR1 bcf PIR1,TMR1IF goto interrupt_done interrupt_CCP2 btfss PIR2,CCP2IF goto interrupt_TMR2 bcf PIR2,CCP2IF clrf PORTB ;свършило е времето за работа на машинката clrf CCP2CON ;и спираме CCP2 incf eed,f goto interrupt_done interrupt_TMR2 btfss PIR1,TMR2IF goto interrupt_CCP1 ; не е от TMR2 bcf PIR1,TMR2IF btfss ready_in ;имаме ли валидни данни goto interrupt_done movlw buf_CCP2+1 movwf FSR btfss STATUS,C rlf pass_ix,w addwf FSR,f incf FSR,f movf INDF,w addwf TMR1L,w movwf CCPR2L decf FSR,f movf INDF,w btfsc STATUS,C incf INDF,w addwf TMR1H,w movwf CCPR2H ; clrf CCP2CON ; incf eed,f movlw 0x0A movwf CCP2CON ;ако сме имали предишен СИ пускаме CCP2 ;следващ индекс incf pass_ix,f movf pass_ix,w sublw 6 btfsc STATUS,Z clrf pass_ix movf PPM_ix,w movwf PORTB bcf STATUS,C rlf PPM_ix,f movlw 0x41 btfsc PPM_ix,6 xorwf PPM_ix,f ;нулираме старшия бит и установяваме младшия goto interrupt_done interrupt_CCP1 ;приемане на информацията и предварителна обработка btfss PIR1,CCP1IF goto interrupt_done bcf PIR1,CCP1IF clrf CCP1CON ;изключваме CCP1 ;обръщаме фронта на сработване на CCP1 movlw 1 xorwf CCP1_Mode,w movwf CCP1_Mode ; movwf CCP1CON ;запазваме сработилото CCP1 movf CCPR1H,w ;запазваме CCPR1H:L във временна променлива CCP1_prev movwf CCP1_buf ; btfsc STATUS,Z ;ако е 0 имаме лъжливо сработване ; goto get_tmr1 movf CCPR1L,w movwf CCP1_buf+1 ; goto CCP1_valid_data ;get_tmr1 ; movf TMR1L,w ; movwf CCP1_buf+1 ; movf TMR1H,w ; movwf CCP1_buf CCP1_valid_data movf in_pass,w btfss STATUS,Z ;ако in_pass <> 0 goto CCP1_next in_pass_add goto incf_pass ; in_pass == 0 ;продължаваме с обработката - in_pass е по голямо или равно на 1 CCP1_next ;да си определим продължителността на импулса movf CCP1_buf+1,w subwf CCP1_prev+1,w movwf CCP1_Ti+1 btfss STATUS,C decf CCP1_buf,f movf CCP1_buf,w subwf CCP1_prev,w movwf CCP1_Ti ; определили сме продължителността на импулса ; сега ще си го обработим movlw buf_r-2 movwf FSR bcf STATUS,C rlf in_pass,w addwf FSR,f incf FSR,f movf CCP1_prev+1,w subwf CCP1_buf+1,w btfss STATUS,C decf CCP1_buf,f movwf INDF ;младша част decf FSR,f movf CCP1_prev,w subwf CCP1_buf,w movwf INDF ;старша част ;дали in_pass ==1 movlw .1 subwf in_pass,w btfsc STATUS,Z goto check_SI movlw .15 subwf in_pass,w btfss STATUS,Z goto incf_pass check_SI ;ако in_pass==1 или in_pass==15 ще проверяваме за СИ ;ще определяме дали е равно на СИ 0x9C0 ; decf FSR,F ;вече сме го изчислили и знаем къде е movlw 0x09 subwf INDF,w btfss STATUS,Z goto do_not_si incf FSR,f movf INDF,w andlw 0x80 xorlw 0x80 btfss STATUS,Z ;младшата част на приетото 0x80 ли е? goto do_not_si ;определили сме СИ ; movlw 0 ; btfsc sin_ok ;дали сме имали предишен СИ ; movlw 0x0a ; movwf CCP2CON ;ако сме имали предишен СИ пускаме CCP2 movf in_pass,w btfsc sin_ok ;дали сме имали предишен СИ movlw 1 movwf in_pass ;ако сме имали СИ и пак го получаваме in_pass==1 movlw 0 btfss sin_ok ;ако сме имали предишен СИ goto set_si movf INDF,w movwf buf_r+1 decf FSR,f movf INDF,w movwf buf_r ;тук ще обработим информацията за предаване на изходите movlw 6 movwf CCP2_pass ;имаме 6 машинки CCP2_Calc_Loop ;вземаме информацията от buf_r + CCP2_pass*4 movlw buf_r movwf FSR movf CCP2_pass,w movwf CCP2_tmp bcf STATUS,C rlf CCP2_tmp,f rlf CCP2_tmp,w addwf FSR,f decf INDF,w ;изваждаме 0х100 movwf CCP2_tmp ;съхраняваме в междинна променлива incf FSR,f movf INDF,w movwf CCP2_tmp+1 ; подготвяме buf_CCP2+CCP2_pass*2 movlw buf_CCP2 movwf FSR bcf STATUS,C rlf CCP2_pass,w addwf FSR,f movf CCP2_tmp+1,w movwf INDF ;и записваме decf FSR,f movf CCP2_tmp,w movwf INDF ;и записваме decfsz CCP2_pass,f goto CCP2_Calc_Loop ; и цифровите команди movlw 6 movwf CCP2_pass ;имаме 6 машинки clrf dig_tmp movlw buf_r+8 movwf FSR movf CCP2_pass,w movwf CCP2_tmp bcf STATUS,C rlf CCP2_tmp,f rlf CCP2_tmp,w addwf FSR,f decf FSR,f decf FSR,f dig_Calc_Loop movlw 4 subwf FSR,f decf INDF,w bcf STATUS,C btfss STATUS,Z bsf STATUS,C rlf dig_tmp,f decfsz CCP2_pass,f goto dig_Calc_Loop movf dig_tmp,w movwf DigVal ;прехвърляме стойността в реалния буфер movwf PORTA ;и на PORTA btfsc ready_in goto set_si ;избягваме повторно предизвикване на прекъсване bsf ready_in ;минал е цял цикъл приемане и е запазена синхронизацията bsf T2CON,2 ;TMR2 On ; bsf PIR1,TMR2IF ;и предизвикваме прекъсване по TMR ; call WriteEE set_si bsf sin_ok goto incf_pass do_not_si clrf CCP2CON ;спираме CCP2 clrf in_pass bcf sin_ok ;нямаме минал СИ bcf ready_in ;нямаме валидна информация incf_pass incf in_pass,f movf CCPR1H,w ;запазваме CCPR1H:L във временна променлива CCP1_prev movwf CCP1_prev movf CCPR1L,w movwf CCP1_prev+1 movf CCP1_Mode,w movwf CCP1CON ; goto interrupt_done interrupt_done movf FSR_TEMP,w movwf FSR movf PCLATH_TEMP,w movwf PCLATH swapf STATUS_TEMP,w movwf STATUS swapf W_TEMP,f swapf W_TEMP,w bsf INTCON,PEIE ;enable interrupt's retfie #ifdef stmacro ;само ако се използва st delay_200iS ;798 cycles movlw 0x9F movwf d1 movlw 0x01 movwf d2 Delay_0 decfsz d1, f goto $+2 decfsz d2, f goto Delay_0 ;2 cycles goto $+1 return #endif Delay_19k ;19968 cycles ;19968 cycles movlw 0x99 movwf d1 movlw 0x10 movwf d2 Delay_19k_loop decfsz d1, f goto $+2 decfsz d2, f goto Delay_19k_loop return WriteEE ;зациклено е ; bsf PORTA,0 movlw .51 movlw 0x33 movwf eed btfsc Modes,3 goto Write_exit movlw 0x20 ; movlw wcb movwf FSR ;source bsf STATUS,RP1 ;bank 2 movlw 0x00 ;0x2100 movwf EEADR bsf STATUS,RP0 ;bank 3 bcf EECON1, EEPGD ; ще записваме в EEPROM bcf INTCON,GIE ;малко да спрем прекъсванията bsf EECON1,WREN ;разрешаваме записа bcf STATUS,RP0 ;bank 2 write_loop movf INDF,w movwf EEDATA bsf STATUS,RP0 ;bank 3 ; btfsc EECON1,WR ; goto $-1 ;задължителния код movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR ;write ;край задължителния код btfsc EECON1,WR goto $-1 nop ; bcf EECON1,WREN ;разрешаваме записа bcf STATUS,RP0 ;bank 2 incf FSR,f incf EEADR,f decfsz eed,f goto write_loop bsf STATUS,RP0 ;bank 3 bcf EECON1,WREN ;разрешаваме записа bcf STATUS,RP0 ;bank 0 bcf STATUS,RP1 ;bank 0 bcf PIR2,EEIF bsf INTCON,GIE ;малко да пуснем прекъсванията bsf Modes,3 bcf INTCON,PEIE ;disable interrupt's nop nop goto $-2 Write_exit return ;EEPROM данни ORG 0X2100 AN_Cor de 0x00,0x01,0x02,0x03 end