Код: Выделить всё
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 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 ;буфер за съхранение на предишната стойнист на TMR1(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 ;указател за пуснатата машинка
TMR1HH ;натрупване на сработването на препълването на TMR1
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 b'11000000' ;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 ;enable 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 ;спираме CCP1
clrf CCP2CON ;спираме CCP2
bsf INTCON,PEIE ;enable interrupt's
bsf INTCON,GIE ;enable interrupt's
clrf PORTA
clrf PORTB
clrf TMR1HH
; goto end_test_start
test_start
end_test_start
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
; clrf TMR1L
; clrf TMR1H
main_loop
st 0x0a03 ;1
nop
st 0x0b03 ;1
nop
st 0x0a03 ;1
nop
st 0xab03 ;1
nop
main_2loop
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_2loop
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
incf TMR1HH,f
btfsc TMR1HH,2 ;дали имаме 4 препълвания 0.13s*4 = 0.52s
goto Stop_PPM
goto interrupt_done
Stop_PPM
bcf T2CON,TMR2ON ;TMR2 OFF - с което си спиране и машинките
bcf ready_in ;данните са невалидни
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 T2CON,TMR2ON ;имаме ли разрешение за работа на машинките
; goto interrupt_done
movlw buf_CCP2+1
movwf FSR
bcf 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
nop
nop
; 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 pass_inc ; in_pass == 0
;продължаваме с обработката - in_pass е по голямо или равно на 1
CCP1_next
;да си определим продължителността на импулса
movf CCP1_prev+1,w
subwf CCP1_buf+1,w
movwf CCP1_Ti+1 ;младша част
btfss STATUS,C
decf CCP1_buf,f
movf CCP1_prev,w
subwf CCP1_buf,w
movwf CCP1_Ti ;старша част
; определили сме продължителността на импулса в Ti
; сега ще си го обработим
;1 дали е по малко от 0x100
movf CCP1_Ti,w
btfsc STATUS,Z
goto pass_0 ; ще отидем да нулираме in_pass
movlw 0x0A
subwf CCP1_Ti,w
btfsc STATUS,C
goto pass_0 ; ще отидем да нулираме in_pass
;импулса е над 0x100 и под 0xA00
;записваме го
movlw buf_r-2
movwf FSR
bcf STATUS,C
rlf in_pass,w
addwf FSR,f
incf FSR,f
movf CCP1_Ti+1,w
movwf INDF ;младша част
decf FSR,f
movf CCP1_Ti,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 pass_inc
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
bsf STATUS, RP0 ;bank 1
bsf PIE1,TMR1IE ;enable interrupt TMR1
bcf STATUS, RP0 ;bank 0
clrf TMR1HH ;изчистване на променливата за натрупване на прекъсванията
btfsc ready_in
goto set_si ;избягваме повторно предизвикване на прекъсване
bsf ready_in ;минал е цял цикъл приемане и е запазена синхронизацията
bsf T2CON,TMR2ON ;TMR2 On
; bsf PIR1,TMR2IF ;и предизвикваме прекъсване по TMR
; call WriteEE
set_si
bsf sin_ok
goto pass_inc
do_not_si
pass_0
; clrf CCP2CON ;спираме CCP2
clrf in_pass
bcf sin_ok ;нямаме минал СИ
bcf ready_in ;нямаме валидна информация
pass_inc
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
/*
Примите под внимание наличе макроса stmacro. Он сделан для подстройки программъ в тестовом режиме.
Имейте в виду, что с WriteEE въхода нет. Она замкнута на себе. Тоже для тестовъх режимов - просмотр изменение длинъ даннъх при реальнъх работ.
Давни делал. Ета версия кажется с 2013г.
*/