Proyek ini menunjukkan apa yang dapat dilakukan dengan mikro dan Anda dapat memodifikasi untuk mengatur alarm pada setiap count-nilai atau menetapkan batas seperti "menghitung-to-60." Anda dapat menambahkan bel atau me-relay atau meningkatkan tampilan untuk 3 digit. Anda harus ingat bahwa setiap tampilan tambahan akan mengurangi pencahayaan dari setiap digit karena mereka "multiplexing (time-sharing)."
The basic 2-Digit Up/Down Counter CircuitFull circuit diagram including programming socket
The "In Circuit Programming" Connectionsby jumpers at the top and bottom Any 7-Segment displays will work in this circuit. You need toidentify the pinout of any display you use.(Common Anode displays can be used providing you invert thevalues in the display table. A PNP transistor will need to be used.)PENGUJIAN SIRKUIT
;****************************************************************
;* 2 Digit UP / Down Counter 17/6/2009
;Port B drives two 7 segment displays
;Up Sw on RA2 Down Sw on RA3
;"Units" drive on RA0 "Tens" drive on RA1
;* *
;****************************************************************
list P = 16F628A ;microcontroller
include ;registers for F628A
__Config _cp_off & _lvp_off & _pwrte_on &
_wdt_off & _intRC_osc_noclkout & _mclre_off
;code protection - off
;low-voltage programming - off
;power-up timer - on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out
;****************************************************************
; variables - names and files
;****************************************************************
;Files for F628A start at 20h
temp1 equ 20h ;for delay
temp2 equ 21h ;for delay
SwUp equ 22h ;
SwDwn equ 23h ;
units equ 24h ;
tens equ 25h ;
Sw_Flag equ 26h ;
FastCount equ 27h ;counts loops fast incrementing
;****************************************************************
;Equates
;****************************************************************
status equ 0x03
cmcon equ 0x1F
rp1 equ 0x06
rp0 equ 0x05
portA equ 0x05
portB equ 0x06
trisA equ 0x85
trisB equ 0x86
;****************************************************************
;Beginning of program
;****************************************************************
reset org 00 ;reset vector address
goto SetUp
table addwf PCL,F ;02h,1 add W to program counter
retlw b'00111111' ; "0" -|F|E|D|C|B|A
retlw b'00000110' ; "1" -|-|-|-|C|B|-
retlw b'01011011' ; "2" G|-|E|D|-|B|A
retlw b'01001111' ; "3" G|-|-|D|C|B|A
retlw b'01100110' ; "4" G|F|-|-|C|B|-
retlw b'01101101' ; "5" G|F|-|D|C|-|A
retlw b'01111101' ; "6" G|F|E|D|C|-|A
retlw b'00000111' ; "7" -|-|-|-|C|B|A
retlw b'01111111' ; "8" G|F|E|D|C|B|A
retlw b'01101111' ; "9" G|F|-|D|C|B|A
;****************************************************************
;* port A and B initialisation *
;****************************************************************
SetUp bsf status,rp0
movlw b'00001100' ;Make RA0,1 out RA2,3 in
movwf 05h ;trisA
clrf 06h ;trisB Make all RB output
bcf status,rp0 ;select programming area - bank0
movlw b'10000000' ;Turn off T0CKI
movwf option_reg
clrf portB ;Clear Port B of junk
clrf units ;zero the units file
clrf tens ;zero the tens file
clrf Sw_Flag
movlw 07h ;turn comparators off and enable
movwf cmcon ; pins for I/O functions
goto Main
;Delay 10mS 10 x 1,000uS
D_10mS movlw 0Ah
movwf temp2
D_a nop
decfsz temp1,f
goto D_a
decfsz temp2,f
goto D_a
retlw 00
Up btfsc Sw_Flag,2
retlw 00
bsf Sw_Flag,2
incf units,f
movlw 0Ah ;put 10 into w
xorwf units,w ;compare units file with 10
btfss status,2 ;zero flag in status file. Set if units is 10
retlw 00
clrf units
incf tens,f
movlw 0Ah ;put 10 into w
xorwf tens,w ;compare units file with 10
btfsc status,2 ;zero flag in status file. Set if tens is 10
clrf tens
retlw 00 ;display passes 99 but not below 0
Dwn btfsc Sw_Flag,3
retlw 00
bsf Sw_Flag,3
decf units,f
movlw 0FFh ;put FFh into w
xorwf units,w ;compare units file with FFh
btfss status,2 ;zero flag in status file. Set if units is 10
retlw 00
movlw 09
movwf units ;put 9 into units file
decf tens,f
movlw 0FFh ;put 0FFh into w
xorwf tens,w ;compare tens file with 0FFh
btfsc status,2 ;zero flag status file). Set if tens is 0FFh
goto $+2 ;tens file is 0FFh Jump down 2 instructions
retlw 00
clrf tens
clrf units
retlw 00 ;display not below 0
Main btfss portA,2 ;test switch-press for UP
call Up ;UP switch pressed
btfss portA,3 ;test switch-press for Down
call Dwn ;Down switch pressed
movlw b'00000001' ;Make RA0 HIGH for units drive
movwf portA
movf units,f ;copy unit value into w
call table ;unit display value will return in w
movwf portB ;output units value
call D_10mS ;call delay
clrf portB ;clear display
movlw b'00000010' ;Make RA1 HIGH for tens drive
movwf portA
movf tens,f ;copy tens value into w
call table ;tens display value will return in w
movwf portB ;output tens value
call D_10mS ;call delay
clrf portB ;clear display
btfsc portA,2 ;bit will be zero when sw is pressed
bcf Sw_Flag,2
btfsc portA,3 ;bit will be zero when sw is pressed
bcf Sw_Flag,3
goto Main
END
Program di atas menggunakan petunjuk yang sangat sederhana dan sangat mudah untuk melihat bagaimana setiap baris kode bekerja. Satu-satunya instruksi Boolean adalah xorwf dan ini adalah mantan atau instruksi (eksklusif-atau) yang berarti dua file dibandingkan dengan masing-masing bit dalam satu file dibandingkan dengan bit yang sama dalam file lain. Hasilnya adalah "1" ketika salah satu (dan hanya satu) dari angka adalah "1." XOR mendeteksi MATCH a. Jika dua angka yang sama dibandingkan, jawaban untuk mengatakan bit terendah akan "0" karena hanya salah satu nomor harus "1." Jika kedua file berisi nilai yang sama, hasil XOR adalah "0"
Kita sekarang melihat berkas 03, (file Status) dan periksa bit 2. ini adalah bit nol. Hasil dari instruksi XOR adalah "0" dan dengan demikian bit nol SET.
Ini adalah kompleks sebagian besar instruksi yang digunakan dalam program ini.
Sekarang kita datang ke sebuah program yang ditulis oleh PROGRAMMER a.
Namun sangat menarik untuk melihat bagaimana program di "tingkat berikutnya pemahaman," dan kami akan mencakup beberapa fitur (ini terletak setelah program).
P16F628.INC P16F628A.INC
To add RESET to the up/down counter, add the following instructions:
SetUp bsf status,rp0
movlw b'00011100' ;Make RA0,1 out RA2,3,4 in
Put reset on RA4 pin3
put 22k to positive and the switch between pin3 and 0v.
When sw is pressed the input will go low.
in main, the least few lines will be
bcf Sw_Flag,2 ;button not pressed. Clear Up flag
bcf Sw_Flag,7 ;Clear Up repeat flag
clrf FastCount
btfss portA,4 ;test reset
goto SetUp
goto Main
END
;******************************************************************
; 2-Digit Up/Dn Counter, Isochronous Loop Example
; Isochronous - to occur at equal time intervals. *
;******************************************************************
processor PIC16F628
include "p16f628.inc"
errorlevel -302
__Config _cp_off & _lvp_off & _pwrte_on &
_wdt_off & _intRC_osc_noclkout & _mclre_off
;code protection - off
;low-voltage programming - off
;power-up timer - on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out
ones equ 0x20 ; 0..9
tens equ 0x21 ; 0..9
number equ 0x22 ; 00..99
swlatch equ 0x23 ; switch state latch variable
DelayHi equ 0x24 ; DelayCy() subsystem variable
#define DnSw 3 ; RA3
;******************************************************************
;
; DelayCy() subsystem macro generates four instructions
;
radix dec
clock equ 8 ; clock frequency in Megahertz
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf DelayHi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
;
; init hardware and program variables
;
org 0x000
Init
bsf STATUS,RP0 ; bank 1
movlw 07h ;turn comparators off and enable
movwf cmcon ; pins for I/O functions
movlw b'00001100' ;
movwf TRISA ; RA3-RA2 inputs, others outputs
clrf TRISB ; portb all outputs
bcf STATUS,RP0 ; bank 0
clrf PORTB ; clear portb output latches
movlw b'00000001' ; digit select bits (RA1-RA0)
movwf PORTA ; select the 'ones' display
clrf swlatch ; clear switch state latch
clrf ones ; clear 'ones'
clrf tens ; clear 'tens'
clrf number ; number = 00
;
; isochronous 8 msec main program loop (62.5Hz refresh rate)
;
Main clrf PORTB ; blank the display
movf PORTA,W ;
xorlw b'00000011' ; flip digit select bits
movwf PORTA ;
movf tens,W ; WREG = tens, 0..9
btfss PORTA,1 ; display tens? yes, skip, else
movf ones,W ; WREG = ones, 0..9
call segtbl ; get segment data
movwf PORTB ; display new digit
TstSw comf PORTA,W ; sample active low switches
andlw b'00001100' ; on RA3 and RA2 pins
xorwf swlatch,W ; changes (press or release)
xorwf swlatch,F ; update switch state latch
andwf swlatch,W ; filter out "new release" bits
bnz Bump ; branch on a "new press", else
DelayCy(8*msecs-23) ; precise 8 msec loop timing
goto Main ;
;
; bump 'number' up or down with limit checking
;
Bump andlw 1<<DnSw ; the "Dn" switch?
skpz ; no, skip (WREG=0), else
movlw -2 ; WREG = -2 (dn)
addlw 1 ; WREG = 1 (up) or -1 (dn)
addwf number,F ; number++ or number--
movf number,W ; WREG = number = -1..100
xorlw 100 ; test upper limit
skpnz ; upper limit? no, skip, else
decf number,F ; reset to 99
btfsc number,7 ; lower limit? no, skip, else
incf number,F ; reset to 00
movf number,W ; WREG = number = 00..99
;
; setup 'tens' and 'ones' for next loop
;
clrf tens ; isochronous bin2bcd routine
addlw -80 ; W = W - 80
rlf tens,F ; shift in 2^3*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 80 ; W = W + 80
addlw -40 ; W = W - 40
rlf tens,F ; shift in 2^2*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 40 ; W = W + 40
addlw -20 ; W = W - 20
rlf tens,F ; shift in 2^1*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 20 ; W = W + 20
addlw -10 ; W = W - 10, now W = "ones"
rlf tens,F ; shift in 2^0*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 10 ; W = W + 10, now W = "ones"
movwf ones ; save "ones"
DelayCy(8*msecs-54) ; precise 8 msec loop timing
goto Main ;
;
; segment data table (caveat, non-boundary tolerant)
;
segtbl
addwf PCL,F
retlw b'00111111' ; "0" -|F|E|D|C|B|A
retlw b'00000110' ; "1" -|-|-|-|C|B|-
retlw b'01011011' ; "2" G|-|E|D|-|B|A
retlw b'01001111' ; "3" G|-|-|D|C|B|A
retlw b'01100110' ; "4" G|F|-|-|C|B|-
retlw b'01101101' ; "5" G|F|-|D|C|-|A
retlw b'01111101' ; "6" G|F|E|D|C|-|A
retlw b'00000111' ; "7" -|-|-|-|C|B|A
retlw b'01111111' ; "8" G|F|E|D|C|B|A
retlw b'01101111' ; "9" G|F|-|D|C|B|A
;
; DelayCy() subsystem 16-bit timing subroutine
;
nop ; entry for (delay-11)%5 == 4
nop ; entry for (delay-11)%5 == 3
nop ; entry for (delay-11)%5 == 2
nop ; entry for (delay-11)%5 == 1
uDelay addlw -1 ; subtract "loop" cycle time
skpc ; borrow? no, skip, else
decfsz DelayHi,F ; done? yes, skip, else
goto uDelay ; do another loop
retlw 00 ;
end
Pada lulus pertama dari program ini, mikro melengkapi nilai port input, (Porta) dan beban itu ke w. instruksi bisa saja movwf PORTA, w dan instruksi berikut akan perlu b'11110011 andlw 'untuk menghasilkan hasil yang sama. Instruksi perubahan h semua "0" untuk "1" dan semua "1" untuk "0 ini." Proyek ini menggunakan "logika negatif." Ini berarti garis input "aktif" saat LOW.
Jika tidak ada tombol yang ditekan, pembacaan pada RA2 dan Ra3 akan "1" dan "1." Hasil PORTA h akan: xxxx00xx mana "x" tidak ditetapkan sebagai bit masukan.
instruksi: andlw b'00001100 'disebut "operasi masking." Semua bit kecuali bit 2 dan 3 yang bertopeng atau "dihapus" dari hasilnya.
Ketika xxxx00xx adalah AND'ed dengan 00.001.100 hasilnya adalah: aaaa00aa di w mendaftar, di mana "a" tidak diperhitungkan karena kami hanya diperbolehkan bit 2 dan 3 untuk "masuk persamaan."
swlatch adalah file bendera untuk switch. Hal ini awalnya dibersihkan dan hasil swlatch xorwf, w akan: xxxx00xx di "w" file.
Instruksi: xorwf swlatch, F melakukan operasi Boolean XOR pada xxxx00xx di "w" file dan 00000000 di file swlatch dan menempatkan hasilnya: 00000000 dalam file swlatch.
instruksi: swlatch andwf, W melakukan Boolean AND operasi pada: 00000000 di file w DAN 00000000 di file swlatch dan menempatkan hasilnya: 00000000 di w. mikro terlihat di bit nol dalam file STATUS dan hasilnya adalah nol, bit yang akan SET. Instruksi BNZ menyebabkan mikro untuk pergi Bump jika bit nol tidak diatur. Nol bit tidak diatur dan dengan demikian mikro tidak pergi ke Bump.
The clever part of these 6 instructions is this: The micro will only branch on the first detection of a button being pressed.
We will now look at how the first detection is created, but it will take a lot of investigation to see how the Boolean operations perform the task:
The result of comf PORTA will be: xxxx01xx and this will be stored in w.
andlw b'00001100' will AND xxxx01xx with 00001100 to get 00000100 in w.
xorwf swlatch,W will XOR 00000100 in w with 00000000 in swlatch to get 00000100 in w.
xorwf swlatch,F will XOR 00000100 in w with 00000000 in swlatch to get 00000100 in swlatch file.
andwf swlatch,W will AND 00000100 in w with 00000100 in swlatch to get 00000100 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will not be set and thus the micro will jump to the sub-routine Bump.
If the button is still pressed when the micro executes: TstSw the second time, we will see what happens:
The result of comf PORTA will be: xxxx01xx and this will be stored in w.
andlw b'00001100' will AND xxxx01xx with 00001100 to get 00000100 in w.
xorwf swlatch,W will XOR 00000100 in w with 00000100 in swlatch to get 00000000 in w.
xorwf swlatch,F will XOR 00000000 in w with 00000100 in swlatch to get 00000100 in swlatch file.
andwf swlatch,W will AND 00000000 in w with 00000100 in swlatch to get 00000000 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will be set and thus the micro will not jump to the sub-routine Bump.
If the button is released when the micro executes: TstSw we will see how the swlatch file is changed to: 00000000.
If no buttons are pressed, the reading on port A will be: xxxx11xx
The result of comf PORTA will be: xxxx00xx and this will be stored in w.
andlw b'00001100' will AND xxxx00xx with 00001100 to get 00000000 in w.
xorwf swlatch,W will XOR 00000000 in w with 00000100 in swlatch to get 00000100 in w.
xorwf swlatch,F will XOR 00000100 in w with 00000100 in swlatch to get 00000000 in swlatch file.
andwf swlatch,W will AND 00000000 in w with 00000000 in swlatch to get 00000000 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will be set and thus the micro will not jump to the sub-routine Bump. And the swlatch file will be changed to 00000000.The Bump sub-routineThe Bump sub-routine detects
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
Bump andlw 1<<DnSw ; the "Dn" switch?
skpz ; no, skip (WREG=0), else
movlw -2 ; WREG = -2 (dn)
addlw 1 ; WREG = 1 (up) or -1 (dn)
addwf number,F ; number++ or number--
movf number,W ; WREG = number = -1..100
xorlw 100 ; test upper limit
skpnz ; upper limit? no, skip, else
decf number,F ; reset to 99
btfsc number,7 ; lower limit? no, skip, else
incf number,F ; reset to 00
movf number,W ; WREG = number = 00..99
addwf number,F will increment the number file.
movf number,W the value in the number file will be copied to "w"
xorlw 100 The value in w will be XOR'ed with 100. The XOR operation detects a match. Since each binary digit will be the same (i.e. either a 0 or 1) the result will be 0000 0000. The result will set the zero flag in the status (03) file and by testing bit 2 (the Z flag) you can skip when SET.decf number,F The number file will be detected as 100. Decrement it to 99.
btfsc number,7 If the number file is decremented below zero, it rolls-over to 0FFh (255) and bit 7 is tested to see if it is SET.
incf number,F The number file is incremented (rolled over) from 256 to 000.
movf number,W The number file is copied to w. The Binary to Binary Coded Decimal RoutineThis routine is so complex that I am not going to explain it.
; isochronous bin2bcd routine
clrf tens
addlw -80 ; W = W - 80
rlf tens,F ; shift in 2^3*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 80 ; W = W + 80
addlw -40 ; W = W - 40
rlf tens,F ; shift in 2^2*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 40 ; W = W + 40
addlw -20 ; W = W - 20
rlf tens,F ; shift in 2^1*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 20 ; W = W + 20
addlw -10 ; W = W - 10, now W = "ones"
rlf tens,F ; shift in 2^0*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 10 ; W = W + 10, now W = "ones"
movwf ones ; save "ones"
DelayCy(8*msecs-54) ; precise 8 msec loop timing
goto Main ;
; Convert a binary number into two packed BCD digits
; ON ENTRY:
; w register has binary value in range 0 t o 9 9
; ON EXIT:
; output variables bcdLow and bcdHigh contain two
; BCD digits
; w contains two packed BCD digits
; Routine logic:
; The value 10 is subtracted from the source operand
; until the reminder is < 0 (carry cleared). The number
; of subtractions is the high-order BCD digit. 10 is
; then added back to the subtrahend to compensate
; for the last subtraction. The final remainder is the
; low-order BCD digit
; Variables:
; inNum storage for source operand
; bcdHigh storage for high-order nibble
; bcdLow storage for low-order nibble
; thisDig Digit counter
bin2bcd:
movwf inNum ; Save copy of source value
clrf bcdHigh ; Clear storage
clrf bcdLow
clrf thisDig
min10:
movlw .10
subwf inNum,f ; Subtract 10
btfsc STATUS,C ; Did subtract overflow?
goto sum10 ; No. Count subtraction
goto fin10
sum10:
incf thisDig,f ;increment digit counter
goto min10
; Store 10th digit
fin10:
movlw .10
addwf inNum,f ; Adjust for last subtract
movf thisDig,w ; get digit counter
movwf bcdHigh ; Store it
; Calculate and store low-order BCD digit
movf inNum,w ; Store units value
movwf bcdLow ; Store digit
; Combine both digits
swapf bcdHigh,w ; High nibble to HOBs
iorwf bcdLow,w ; ORin low nibble
retlw 00
; Binary-to-Decimal, 00..99
;
radix dec
btod99
clrf temp ; W = 0x00..0x63, 0..99 input
decf temp,F ; preset temp to -1
sub10 incf temp,F ; unconditionally
addlw -10 ; subtract 10. borrow?
btfsc status,0 ; no, test carry bit
goto sub10
addlw 10 ; fix 'ones' in Wreg
swapf temp,F ; put 'tens' in left nibble
iorwf temp,W ; W = packed bcd 0x00..0x99
retlw 00
selengkapnya kunjungi : http://www.talkingelectronics.com
The basic 2-Digit Up/Down Counter CircuitFull circuit diagram including programming socket
The "In Circuit Programming" Connectionsby jumpers at the top and bottom Any 7-Segment displays will work in this circuit. You need toidentify the pinout of any display you use.(Common Anode displays can be used providing you invert thevalues in the display table. A PNP transistor will need to be used.)PENGUJIAN SIRKUIT
;****************************************************************
;* 2 Digit UP / Down Counter 17/6/2009
;Port B drives two 7 segment displays
;Up Sw on RA2 Down Sw on RA3
;"Units" drive on RA0 "Tens" drive on RA1
;* *
;****************************************************************
list P = 16F628A ;microcontroller
include ;registers for F628A
__Config _cp_off & _lvp_off & _pwrte_on &
_wdt_off & _intRC_osc_noclkout & _mclre_off
;code protection - off
;low-voltage programming - off
;power-up timer - on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out
;****************************************************************
; variables - names and files
;****************************************************************
;Files for F628A start at 20h
temp1 equ 20h ;for delay
temp2 equ 21h ;for delay
SwUp equ 22h ;
SwDwn equ 23h ;
units equ 24h ;
tens equ 25h ;
Sw_Flag equ 26h ;
FastCount equ 27h ;counts loops fast incrementing
;****************************************************************
;Equates
;****************************************************************
status equ 0x03
cmcon equ 0x1F
rp1 equ 0x06
rp0 equ 0x05
portA equ 0x05
portB equ 0x06
trisA equ 0x85
trisB equ 0x86
;****************************************************************
;Beginning of program
;****************************************************************
reset org 00 ;reset vector address
goto SetUp
table addwf PCL,F ;02h,1 add W to program counter
retlw b'00111111' ; "0" -|F|E|D|C|B|A
retlw b'00000110' ; "1" -|-|-|-|C|B|-
retlw b'01011011' ; "2" G|-|E|D|-|B|A
retlw b'01001111' ; "3" G|-|-|D|C|B|A
retlw b'01100110' ; "4" G|F|-|-|C|B|-
retlw b'01101101' ; "5" G|F|-|D|C|-|A
retlw b'01111101' ; "6" G|F|E|D|C|-|A
retlw b'00000111' ; "7" -|-|-|-|C|B|A
retlw b'01111111' ; "8" G|F|E|D|C|B|A
retlw b'01101111' ; "9" G|F|-|D|C|B|A
;****************************************************************
;* port A and B initialisation *
;****************************************************************
SetUp bsf status,rp0
movlw b'00001100' ;Make RA0,1 out RA2,3 in
movwf 05h ;trisA
clrf 06h ;trisB Make all RB output
bcf status,rp0 ;select programming area - bank0
movlw b'10000000' ;Turn off T0CKI
movwf option_reg
clrf portB ;Clear Port B of junk
clrf units ;zero the units file
clrf tens ;zero the tens file
clrf Sw_Flag
movlw 07h ;turn comparators off and enable
movwf cmcon ; pins for I/O functions
goto Main
;Delay 10mS 10 x 1,000uS
D_10mS movlw 0Ah
movwf temp2
D_a nop
decfsz temp1,f
goto D_a
decfsz temp2,f
goto D_a
retlw 00
Up btfsc Sw_Flag,2
retlw 00
bsf Sw_Flag,2
incf units,f
movlw 0Ah ;put 10 into w
xorwf units,w ;compare units file with 10
btfss status,2 ;zero flag in status file. Set if units is 10
retlw 00
clrf units
incf tens,f
movlw 0Ah ;put 10 into w
xorwf tens,w ;compare units file with 10
btfsc status,2 ;zero flag in status file. Set if tens is 10
clrf tens
retlw 00 ;display passes 99 but not below 0
Dwn btfsc Sw_Flag,3
retlw 00
bsf Sw_Flag,3
decf units,f
movlw 0FFh ;put FFh into w
xorwf units,w ;compare units file with FFh
btfss status,2 ;zero flag in status file. Set if units is 10
retlw 00
movlw 09
movwf units ;put 9 into units file
decf tens,f
movlw 0FFh ;put 0FFh into w
xorwf tens,w ;compare tens file with 0FFh
btfsc status,2 ;zero flag status file). Set if tens is 0FFh
goto $+2 ;tens file is 0FFh Jump down 2 instructions
retlw 00
clrf tens
clrf units
retlw 00 ;display not below 0
Main btfss portA,2 ;test switch-press for UP
call Up ;UP switch pressed
btfss portA,3 ;test switch-press for Down
call Dwn ;Down switch pressed
movlw b'00000001' ;Make RA0 HIGH for units drive
movwf portA
movf units,f ;copy unit value into w
call table ;unit display value will return in w
movwf portB ;output units value
call D_10mS ;call delay
clrf portB ;clear display
movlw b'00000010' ;Make RA1 HIGH for tens drive
movwf portA
movf tens,f ;copy tens value into w
call table ;tens display value will return in w
movwf portB ;output tens value
call D_10mS ;call delay
clrf portB ;clear display
btfsc portA,2 ;bit will be zero when sw is pressed
bcf Sw_Flag,2
btfsc portA,3 ;bit will be zero when sw is pressed
bcf Sw_Flag,3
goto Main
END
Program di atas menggunakan petunjuk yang sangat sederhana dan sangat mudah untuk melihat bagaimana setiap baris kode bekerja. Satu-satunya instruksi Boolean adalah xorwf dan ini adalah mantan atau instruksi (eksklusif-atau) yang berarti dua file dibandingkan dengan masing-masing bit dalam satu file dibandingkan dengan bit yang sama dalam file lain. Hasilnya adalah "1" ketika salah satu (dan hanya satu) dari angka adalah "1." XOR mendeteksi MATCH a. Jika dua angka yang sama dibandingkan, jawaban untuk mengatakan bit terendah akan "0" karena hanya salah satu nomor harus "1." Jika kedua file berisi nilai yang sama, hasil XOR adalah "0"
Kita sekarang melihat berkas 03, (file Status) dan periksa bit 2. ini adalah bit nol. Hasil dari instruksi XOR adalah "0" dan dengan demikian bit nol SET.
Ini adalah kompleks sebagian besar instruksi yang digunakan dalam program ini.
Sekarang kita datang ke sebuah program yang ditulis oleh PROGRAMMER a.
Namun sangat menarik untuk melihat bagaimana program di "tingkat berikutnya pemahaman," dan kami akan mencakup beberapa fitur (ini terletak setelah program).
P16F628.INC P16F628A.INC
To add RESET to the up/down counter, add the following instructions:
SetUp bsf status,rp0
movlw b'00011100' ;Make RA0,1 out RA2,3,4 in
Put reset on RA4 pin3
put 22k to positive and the switch between pin3 and 0v.
When sw is pressed the input will go low.
in main, the least few lines will be
bcf Sw_Flag,2 ;button not pressed. Clear Up flag
bcf Sw_Flag,7 ;Clear Up repeat flag
clrf FastCount
btfss portA,4 ;test reset
goto SetUp
goto Main
END
;******************************************************************
; 2-Digit Up/Dn Counter, Isochronous Loop Example
; Isochronous - to occur at equal time intervals. *
;******************************************************************
processor PIC16F628
include "p16f628.inc"
errorlevel -302
__Config _cp_off & _lvp_off & _pwrte_on &
_wdt_off & _intRC_osc_noclkout & _mclre_off
;code protection - off
;low-voltage programming - off
;power-up timer - on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out
ones equ 0x20 ; 0..9
tens equ 0x21 ; 0..9
number equ 0x22 ; 00..99
swlatch equ 0x23 ; switch state latch variable
DelayHi equ 0x24 ; DelayCy() subsystem variable
#define DnSw 3 ; RA3
;******************************************************************
;
; DelayCy() subsystem macro generates four instructions
;
radix dec
clock equ 8 ; clock frequency in Megahertz
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf DelayHi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
;
; init hardware and program variables
;
org 0x000
Init
bsf STATUS,RP0 ; bank 1
movlw 07h ;turn comparators off and enable
movwf cmcon ; pins for I/O functions
movlw b'00001100' ;
movwf TRISA ; RA3-RA2 inputs, others outputs
clrf TRISB ; portb all outputs
bcf STATUS,RP0 ; bank 0
clrf PORTB ; clear portb output latches
movlw b'00000001' ; digit select bits (RA1-RA0)
movwf PORTA ; select the 'ones' display
clrf swlatch ; clear switch state latch
clrf ones ; clear 'ones'
clrf tens ; clear 'tens'
clrf number ; number = 00
;
; isochronous 8 msec main program loop (62.5Hz refresh rate)
;
Main clrf PORTB ; blank the display
movf PORTA,W ;
xorlw b'00000011' ; flip digit select bits
movwf PORTA ;
movf tens,W ; WREG = tens, 0..9
btfss PORTA,1 ; display tens? yes, skip, else
movf ones,W ; WREG = ones, 0..9
call segtbl ; get segment data
movwf PORTB ; display new digit
TstSw comf PORTA,W ; sample active low switches
andlw b'00001100' ; on RA3 and RA2 pins
xorwf swlatch,W ; changes (press or release)
xorwf swlatch,F ; update switch state latch
andwf swlatch,W ; filter out "new release" bits
bnz Bump ; branch on a "new press", else
DelayCy(8*msecs-23) ; precise 8 msec loop timing
goto Main ;
;
; bump 'number' up or down with limit checking
;
Bump andlw 1<<DnSw ; the "Dn" switch?
skpz ; no, skip (WREG=0), else
movlw -2 ; WREG = -2 (dn)
addlw 1 ; WREG = 1 (up) or -1 (dn)
addwf number,F ; number++ or number--
movf number,W ; WREG = number = -1..100
xorlw 100 ; test upper limit
skpnz ; upper limit? no, skip, else
decf number,F ; reset to 99
btfsc number,7 ; lower limit? no, skip, else
incf number,F ; reset to 00
movf number,W ; WREG = number = 00..99
;
; setup 'tens' and 'ones' for next loop
;
clrf tens ; isochronous bin2bcd routine
addlw -80 ; W = W - 80
rlf tens,F ; shift in 2^3*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 80 ; W = W + 80
addlw -40 ; W = W - 40
rlf tens,F ; shift in 2^2*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 40 ; W = W + 40
addlw -20 ; W = W - 20
rlf tens,F ; shift in 2^1*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 20 ; W = W + 20
addlw -10 ; W = W - 10, now W = "ones"
rlf tens,F ; shift in 2^0*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 10 ; W = W + 10, now W = "ones"
movwf ones ; save "ones"
DelayCy(8*msecs-54) ; precise 8 msec loop timing
goto Main ;
;
; segment data table (caveat, non-boundary tolerant)
;
segtbl
addwf PCL,F
retlw b'00111111' ; "0" -|F|E|D|C|B|A
retlw b'00000110' ; "1" -|-|-|-|C|B|-
retlw b'01011011' ; "2" G|-|E|D|-|B|A
retlw b'01001111' ; "3" G|-|-|D|C|B|A
retlw b'01100110' ; "4" G|F|-|-|C|B|-
retlw b'01101101' ; "5" G|F|-|D|C|-|A
retlw b'01111101' ; "6" G|F|E|D|C|-|A
retlw b'00000111' ; "7" -|-|-|-|C|B|A
retlw b'01111111' ; "8" G|F|E|D|C|B|A
retlw b'01101111' ; "9" G|F|-|D|C|B|A
;
; DelayCy() subsystem 16-bit timing subroutine
;
nop ; entry for (delay-11)%5 == 4
nop ; entry for (delay-11)%5 == 3
nop ; entry for (delay-11)%5 == 2
nop ; entry for (delay-11)%5 == 1
uDelay addlw -1 ; subtract "loop" cycle time
skpc ; borrow? no, skip, else
decfsz DelayHi,F ; done? yes, skip, else
goto uDelay ; do another loop
retlw 00 ;
end
Pada lulus pertama dari program ini, mikro melengkapi nilai port input, (Porta) dan beban itu ke w. instruksi bisa saja movwf PORTA, w dan instruksi berikut akan perlu b'11110011 andlw 'untuk menghasilkan hasil yang sama. Instruksi perubahan h semua "0" untuk "1" dan semua "1" untuk "0 ini." Proyek ini menggunakan "logika negatif." Ini berarti garis input "aktif" saat LOW.
Jika tidak ada tombol yang ditekan, pembacaan pada RA2 dan Ra3 akan "1" dan "1." Hasil PORTA h akan: xxxx00xx mana "x" tidak ditetapkan sebagai bit masukan.
instruksi: andlw b'00001100 'disebut "operasi masking." Semua bit kecuali bit 2 dan 3 yang bertopeng atau "dihapus" dari hasilnya.
Ketika xxxx00xx adalah AND'ed dengan 00.001.100 hasilnya adalah: aaaa00aa di w mendaftar, di mana "a" tidak diperhitungkan karena kami hanya diperbolehkan bit 2 dan 3 untuk "masuk persamaan."
swlatch adalah file bendera untuk switch. Hal ini awalnya dibersihkan dan hasil swlatch xorwf, w akan: xxxx00xx di "w" file.
Instruksi: xorwf swlatch, F melakukan operasi Boolean XOR pada xxxx00xx di "w" file dan 00000000 di file swlatch dan menempatkan hasilnya: 00000000 dalam file swlatch.
instruksi: swlatch andwf, W melakukan Boolean AND operasi pada: 00000000 di file w DAN 00000000 di file swlatch dan menempatkan hasilnya: 00000000 di w. mikro terlihat di bit nol dalam file STATUS dan hasilnya adalah nol, bit yang akan SET. Instruksi BNZ menyebabkan mikro untuk pergi Bump jika bit nol tidak diatur. Nol bit tidak diatur dan dengan demikian mikro tidak pergi ke Bump.
The clever part of these 6 instructions is this: The micro will only branch on the first detection of a button being pressed.
We will now look at how the first detection is created, but it will take a lot of investigation to see how the Boolean operations perform the task:
The result of comf PORTA will be: xxxx01xx and this will be stored in w.
andlw b'00001100' will AND xxxx01xx with 00001100 to get 00000100 in w.
xorwf swlatch,W will XOR 00000100 in w with 00000000 in swlatch to get 00000100 in w.
xorwf swlatch,F will XOR 00000100 in w with 00000000 in swlatch to get 00000100 in swlatch file.
andwf swlatch,W will AND 00000100 in w with 00000100 in swlatch to get 00000100 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will not be set and thus the micro will jump to the sub-routine Bump.
If the button is still pressed when the micro executes: TstSw the second time, we will see what happens:
The result of comf PORTA will be: xxxx01xx and this will be stored in w.
andlw b'00001100' will AND xxxx01xx with 00001100 to get 00000100 in w.
xorwf swlatch,W will XOR 00000100 in w with 00000100 in swlatch to get 00000000 in w.
xorwf swlatch,F will XOR 00000000 in w with 00000100 in swlatch to get 00000100 in swlatch file.
andwf swlatch,W will AND 00000000 in w with 00000100 in swlatch to get 00000000 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will be set and thus the micro will not jump to the sub-routine Bump.
If the button is released when the micro executes: TstSw we will see how the swlatch file is changed to: 00000000.
If no buttons are pressed, the reading on port A will be: xxxx11xx
The result of comf PORTA will be: xxxx00xx and this will be stored in w.
andlw b'00001100' will AND xxxx00xx with 00001100 to get 00000000 in w.
xorwf swlatch,W will XOR 00000000 in w with 00000100 in swlatch to get 00000100 in w.
xorwf swlatch,F will XOR 00000100 in w with 00000100 in swlatch to get 00000000 in swlatch file.
andwf swlatch,W will AND 00000000 in w with 00000000 in swlatch to get 00000000 in w.
bnz Bump will look at the zero flag in the STATUS file. This flag will be set and thus the micro will not jump to the sub-routine Bump. And the swlatch file will be changed to 00000000.The Bump sub-routineThe Bump sub-routine detects
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
If Up button is pressed, "w" will enter Bump sub-routine with: 00000100.
If Down button is pressed, "w" will enter Bump sub-routine with: 00001000
Bump andlw 1<<DnSw ; the "Dn" switch?
skpz ; no, skip (WREG=0), else
movlw -2 ; WREG = -2 (dn)
addlw 1 ; WREG = 1 (up) or -1 (dn)
addwf number,F ; number++ or number--
movf number,W ; WREG = number = -1..100
xorlw 100 ; test upper limit
skpnz ; upper limit? no, skip, else
decf number,F ; reset to 99
btfsc number,7 ; lower limit? no, skip, else
incf number,F ; reset to 00
movf number,W ; WREG = number = 00..99
addwf number,F will increment the number file.
movf number,W the value in the number file will be copied to "w"
xorlw 100 The value in w will be XOR'ed with 100. The XOR operation detects a match. Since each binary digit will be the same (i.e. either a 0 or 1) the result will be 0000 0000. The result will set the zero flag in the status (03) file and by testing bit 2 (the Z flag) you can skip when SET.decf number,F The number file will be detected as 100. Decrement it to 99.
btfsc number,7 If the number file is decremented below zero, it rolls-over to 0FFh (255) and bit 7 is tested to see if it is SET.
incf number,F The number file is incremented (rolled over) from 256 to 000.
movf number,W The number file is copied to w. The Binary to Binary Coded Decimal RoutineThis routine is so complex that I am not going to explain it.
; isochronous bin2bcd routine
clrf tens
addlw -80 ; W = W - 80
rlf tens,F ; shift in 2^3*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 80 ; W = W + 80
addlw -40 ; W = W - 40
rlf tens,F ; shift in 2^2*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 40 ; W = W + 40
addlw -20 ; W = W - 20
rlf tens,F ; shift in 2^1*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 20 ; W = W + 20
addlw -10 ; W = W - 10, now W = "ones"
rlf tens,F ; shift in 2^0*10 bit
btfss tens,0 ; borrow? no, skip, else
addlw 10 ; W = W + 10, now W = "ones"
movwf ones ; save "ones"
DelayCy(8*msecs-54) ; precise 8 msec loop timing
goto Main ;
; Convert a binary number into two packed BCD digits
; ON ENTRY:
; w register has binary value in range 0 t o 9 9
; ON EXIT:
; output variables bcdLow and bcdHigh contain two
; BCD digits
; w contains two packed BCD digits
; Routine logic:
; The value 10 is subtracted from the source operand
; until the reminder is < 0 (carry cleared). The number
; of subtractions is the high-order BCD digit. 10 is
; then added back to the subtrahend to compensate
; for the last subtraction. The final remainder is the
; low-order BCD digit
; Variables:
; inNum storage for source operand
; bcdHigh storage for high-order nibble
; bcdLow storage for low-order nibble
; thisDig Digit counter
bin2bcd:
movwf inNum ; Save copy of source value
clrf bcdHigh ; Clear storage
clrf bcdLow
clrf thisDig
min10:
movlw .10
subwf inNum,f ; Subtract 10
btfsc STATUS,C ; Did subtract overflow?
goto sum10 ; No. Count subtraction
goto fin10
sum10:
incf thisDig,f ;increment digit counter
goto min10
; Store 10th digit
fin10:
movlw .10
addwf inNum,f ; Adjust for last subtract
movf thisDig,w ; get digit counter
movwf bcdHigh ; Store it
; Calculate and store low-order BCD digit
movf inNum,w ; Store units value
movwf bcdLow ; Store digit
; Combine both digits
swapf bcdHigh,w ; High nibble to HOBs
iorwf bcdLow,w ; ORin low nibble
retlw 00
; Binary-to-Decimal, 00..99
;
radix dec
btod99
clrf temp ; W = 0x00..0x63, 0..99 input
decf temp,F ; preset temp to -1
sub10 incf temp,F ; unconditionally
addlw -10 ; subtract 10. borrow?
btfsc status,0 ; no, test carry bit
goto sub10
addlw 10 ; fix 'ones' in Wreg
swapf temp,F ; put 'tens' in left nibble
iorwf temp,W ; W = packed bcd 0x00..0x99
retlw 00
selengkapnya kunjungi : http://www.talkingelectronics.com