TA2CBA Barbaros Aşuroğlu
E-Mail: ta2cba@www.antrak.org.tr
URL: http://www.antrak.org.tr/~ta2cba
Geçen ay PIC ile Lojik devre tasarımı uygulaması olan
PICBIT PLC yazılımını incelemeyi
tamamlamıştık. Bu ay ne yazacağım diye düşünürken aklıma
PIC kullanılarak
yapılabilecek ;karmaşık dijital uygulamaların PIC 16F84
yardımıyla bir,iki entegre ile
çözümlenmesini içeren PIC 16F84 UYGULAMALARI diye bir
yazı dizisi hazırlamak geldi.
Bu yazı dizisinin amacı daha önce yaptığımız programlayıcı
yardımıyla pic16f84
kullanarak amatör elektronik hobbymize mikroişlemci gücünü
katabilmek.
Bunu yaparken program yazmayı değilde uygulamayı ele
alacağım. Mümkün olduğu kadar
assembler listesini ve uygulamayı tamamlamak için gerekli
ekipmanı (F84 ASM ve HEX
program,pcb tasarımı,şema, vs.) detaylarıyla vermeye
çalışacağım.
Bu ay ele alacağımız uygulama radyo amatörleri için en
gerekli ölçü aleti olan bir Frekans
Sayıcı. Bu frekans sayıcı Slovak radyo amatörü olan bir
baba-oğul tarafından geliştirilmiş
ve başarıyla kullanılmaktadır. Uygulamanın geliştirilmesini
sağlayan Peter Halicky
OM3CPH ve oğlu Peter Halicky Jr. OM2APH ile baskı devre
tasarımını yapan
Tibor Madarasz OM2ATM ye teşekkür etmek isterim.
Frekans sayıcı şemadanda görüleceği gibi temel olarak
16f84 ve 4051 den olşmaktadır.
Bunlar dışında transistorler ve birkaç pasif eleman bulunmaktadır.
Frekans sayıcı HF bir amatör cihazın frekansını görmek
için tasarlanmıştır, ölçüm aralığı
10hz – 35 Mhz dir. Bu aralık girişine bir prescaler (örn:
U664B) konularak 1.2 Ghz’e
kadar kolayca çıkarılabilir.
Yazar gösterge olarak eski bir hesap makinesinin 7 segment
göstergesini kullanmış
fakat herhangi bir ortak katotlu gösterge kullanılabilir.
Gösterge sürücü Transistörleri kritik olmayıp BC547 rahatlıkla
iş görür.
Giriş transistörü yüksek frekanslı bir NPN olmalıdır.
BF serisi herhangi
bir transistör olabilir.
Devreyi yaparken aşagıdaki PCB, yerleşim planını kullanabilirsiniz.
Biraz da devreyi inceleyelim…
Devrede bulunan PIC 16F84 hem ölçüm hem de göstergelerin
sürülmesi işinden
sorumludur. 4051 ise pic bacak sayısı yeterli olmadığından
çoğullayıcı olarak her display
elemanını pic komutlarına göre adresler. Belki dikkatinizi
çekmiştir burada kullanılan
kristal 10Mhz'dir tabii Pic de 10Mhzlik PIC16F84 10
I/P
tipi olmalıdır gibi bir kanı oluşabilir aslında doğrusuda
budur ama hiç gerek yok ufak bir
kandırmacayla 4 Mhzlik piyasada bol bulunan PIC16F84
– 04 I/P ile bu işi halledebiliriz.
Yapmamız gereken tek şey programlama öncesi programlayıcı
yazılımında OSC
seçeneğinde XT yerine HS yani Hızlı seçeneğini seçmektir.
Bunu yaparsak sorunsuz bir
10 Mhz'lik pic elde ederiz.
Pic bacaklarındaki A, B, C, D, E, F, G harfleri display
sisteminde segmentlere gidecek ve
0, 1, 2, 3, 4, 5, 6 sayıları ise ilgili displayin ortak
katoduna gidecektir.
Sistem multiplex sürme sistemini kullanmaktadır dolayısıyla
7 gösterge elemanının aynı
olan segmentleri birbirlerine bağlanmalı katodları ise
ayrı olarak rakam grubuna sırayla
soldan sağa gitmelidir.
Besleme voltajı olarak 2.5 – 5.0 volt denmektedir ama
en sağlıklı sonuç +5V ile alınır.
Nokta sabit olarak Mhz displayinden sonraki ilk nokta
olarak yakılmalıdır. Bu bir direnç
(270 ohm) ile ilgili bacak +5V asılarak sağlanır…
Counter.hex dosyası compile
edilmiş programı içerir, counter.asm ise assenmbler
programdır. Siz counter.hex
ile PIC 16F84 ‘ü programlayabilirsiniz .
Assembler Listesini aşağıda veriyorum.
Counter.zip dosyası içinde
ise gerekli tüm dosyalar mevcuttur.
PICBIT yazılımının son versiyonunu picbit05.zip
vermeyi ihmal etmeyelim.
Bu aylık da bu kadar gelecek ay başka bir uygulamada
görüşmek dileğiyle…
Pic Counter Assembler Listesi:
; ------------------------------------------------------------------------
; FILE : counter.asm
*
; CONTENTS : Simple low-cost 7-digit counter using
a PIC16F84
*
; COPYRIGHT: Peter Halicky OM3CPH
*
; AUTHORS : Peter Halicky OM3CPH &
Peter Halicky Jr., OM2APH
*
; PCB : Tibor Madarasz
OM2ATM
*
;--------------------------------------------------------------------------
; E-Mail: halicky@cepoe.minv.sk or om3cph@oe3xbs.aut.eu
;
peto-h@writeme.com or om2aph@om0pbm.svk.eu
;
; Bratislava, Slovakia, February 1998
;
;--------------------------------------------------------------------------
; This is 7-digit counter counting up to 35 MHz.
The decimal point
; is after MHz digit.
;
; Power consumption with calculator display: 2.5V/9mA,
3V/13mA, 5V/35mA.
;
; Hardware is very simple:
;
; It contains : PIC 16F84
;
4051 (BCD -> 1 of 8 decoder)
;
8 NPN low power Si transistors,
;
7-digit calculator display (common cathode),
;
some resistors, capacitors and 2 switching diodes
;
(see schematic in counter.pcx)
;
; Note:
; "Calculator display" means minimum 7 digit LED
multiplexed display.
; Both common cathode and common anode can be used.
Software is written
; for common cathode display. For common anode displays
it requires very
; slight software and hardware modification.
;
; The counter uses internal prescaler of PIC as low
byte of counter,
; TMR0 as middle byte and some register as high byte
of counter.
;
; Some ideas were taken from "Simple low-cost digital
frequency meter
;
using a PIC 16C54" (frqmeter.asm)
;
written by James Hutchby, MadLab Ltd. 1996
;
; ------------------------------------------------------------------------
;
; This software is free for private usage. It was
created for HAM radio
; community members. Commercial exploatation is allowed
only with permission
; of authors.
;
; ------------------------------------------------------------------------
IndF equ
00h ; Indirect addr. register
Timer0 equ
01h ; TMR0 register
- RP0=0
OptionR equ
01h ; Option register -
RP0=1
PC
equ 02h
; Program counter
Status equ
03h ; Status register
FSR
equ 04h
; Pointer register
PortA equ
05h ; Port A - RP0=0
TrisA equ
05h ; Tris A - RP0=1
PortB equ
06h ; Port B - RP0=0
TrisB equ
06h ; Tris B - RP0=1
;PortC equ
07h ; Port C - 16C54+84
not implmented
EEData equ
08h ; 16C84
EEAdr equ
09h ; 16C84
PCLath equ
0Ah ; 16C84
IntCon equ
0Bh ; 16C84
Index equ
0Ch ; dummy register
Count equ
0Dh ; inkremental register
Help equ
0Eh ; dummy register
LED0 equ
0Fh
LED1 equ
010h
LED2 equ
011h
LED3 equ
012h
LED4 equ
013h
LED5 equ
014h
LED6 equ
015h
LED7 equ
016h
TimerH equ
017h ; higher byte of SW
counter
LowB equ
018h ; low byte of resulted
frequency
MidB equ
019h ; middle byte of resulted
frequency
HigB equ
01Ah ; high byte of resulted
frequency
Temp equ
01Bh ; temporary register
HIndex equ
01Ch ; index register
LEDIndex equ
01Dh ; LED pointer
; ------------------------------------------------------------------------
; timing loop values
; must be from 1 to 255!!!
T1
equ .70
; rough timing loop
T2
equ .3
; timing loop
T3
equ .20
; fine timing loop
; values for 4 194 kHz
; ------------------------------------------------------------------------
;
; Measuring period is 100 000 us.
; Procesor cycle is T = 4/fx us [MHz],
fx is Xtal frequency
;
; Number of procesor cycles per measuring period:
;
; N = 100
000/T procesor cycles
; N = fx
x 100 000/4 = 25 000 x fx
;
; The main steps of measuring period:
;
; 1. start
measurement,
; 2. precode
decimal value of digit to segments,
; 3. if
it's 5th digit set decimal point,
; 4. output
to PortB,
; 5. output
digit number to PortA
;
(numbers from left to right are 6543210),
; 6. test
TMR0 overflow bite, if YES increase TimerH,
; 7. leave
digit to light,
; 8. increase
digit number,
; 9. if
<7 goto 2,
; 10. else zero
digit number,
;
decrease counter and goto 2,
; 11. stop measurement,
; 12. shift out
precounter content,
; 13. precode
3-byte value into 7 decimal numbers,
; 14. goto 1
;
; ------------------------------------------------------------------------
;
; Total timing formula:
;
; N = 25 000 x fx = 60x[(36 + 3xT1 + X)x7 + 2 + 3xT2
+ Y] + 19 + 3xT3 + Z
;
; where T1,T2,T3 are initial values of timing loops,
; X, Y, Z
are additional tunig NOPs.
;
; ------------------------------------------------------------------------
W
equ 0
; destination is accumulator
F
equ 1
; register
; ------------------------------------------------------------------------
; Flag bits:
CF
equ 0
; Carry
DC
equ 1
; DC
ZF
equ 2
; Zero
RP0
equ 5
RP1
equ 6
IRP
equ 7
; ------------------------------------------------------------------------
org 0
Start clrf
Index
clrf LEDIndex
clrf LED0
clrf LED1
clrf LED2
clrf LED3
clrf LED4
clrf LED5
clrf LED6
clrf LED7
clrf LowB
clrf MidB
clrf HigB
bsf Status,RP0
movlw b'00010000' ; RA0..RA3 outputs
movwf TrisA
; RA4 input
movlw b'00000000' ; RB0..RB7 outputs
movwf TrisB
clrwdt
;
movlw b'00100111' ; Prescaler -> Timer0,
movwf OptionR ; 1:256,
rising edge
bcf Status,RP0 ;
goto Go
;------------------------------------------------------------------------
; 3 byte substraction of the constant from the table
which sets carry if
; result is negative
;------------------------------------------------------------------------
Subc24 clrf
Temp ; it will temporary save
CF
movf Index,W
; pointer to low byte of constant
movwf HIndex
; W -> HIndex
call DecTable ; W
returned with low byte of constant
bsf Status,CF ; set
CF
subwf LowB,F
; LowB - W -> LowB
; if underflow -> CF=0
btfsc Status,CF
goto Step1
bsf Status,CF
movlw 1
subwf MidB,F
; decrement MidB
; if underflow -> CF=0
btfsc Status,CF
goto Step1
bsf Status,CF
movlw 1
subwf HigB,F
; decrement HigB
btfsc Status,CF ; if underflow
-> CF=0
goto Step1
bsf Temp,CF
; set CF
Step1 decf
HIndex,F
movf HIndex,W ; pointer
to middle byte of const
call DecTable
bsf Status,CF
subwf MidB,F
; MidB - W -> MidB
btfsc Status,CF ; if underflow
-> CF=0
goto Step2
bsf Status,CF
movlw 1
subwf HigB,1
; decrement HigB
btfsc Status,CF ; if underflow
-> CF=0
goto Step2
bsf Temp,CF
; set CF
Step2 decf
HIndex,F
movf HIndex,W ; pointer
to middle byte of constatnt
call DecTable
bsf Status,CF
subwf HigB,F
; HigB - W -> HigB
btfsc Status,CF ; if underflow
-> CF=0
goto ClearCF
bsf Status,CF
goto SubEnd
ClearCF rrf
Temp,CF ; CF -> Status
SubEnd retlw
0
; ------------------------------------------------------------------------
; 3 byte addition of the constant from the table
which sets carry if
; result overflows
; ------------------------------------------------------------------------
Addc24 clrf
Temp ; register for temporary
storage of CF
movf Index,W
; pointer to lower byte of const into W
movwf HIndex
; save it into HIndex
call DecTable ; W
contains low byte of const
bcf Status,CF ; clear
CF
addwf LowB,1
; W + LowB -> LowB
btfss Status,CF ; test overflow
goto Add2
bcf Status,CF ; clear
CF
movlw 1
addwf MidB,F
; increment MidB
btfss Status,CF
goto Add2
bcf Status,CF
movlw 1
addwf HigB,F
; increment HigB
btfss Status,CF ; test overflow
goto Add2
bsf Temp,CF
; store CF
Add2 decf
HIndex,F ; pointer to middle byte into W
movf HIndex,W
call DecTable
bcf Status,CF
addwf MidB,1
; W + MidB -> MidB
btfss Status,CF
goto Add3
bcf Status,CF ; clear
CF
movlw 1
addwf HigB,1
; increment HigB
btfss Status,CF
goto Add3
bsf Temp,CF
Add3 decf
HIndex,F ; pointer to higher byte into W
movf HIndex,W
call DecTable
bsf Status,CF
addwf HigB,F
; W + HigB -> HigB,
btfss Status,CF
goto ClarCF
bsf Status,CF
goto AddEnd
ClarCF rrf
Temp,CF ; CF -> Status
AddEnd retlw
0
; ------------------------------------------------------------------------
; Tables for 3 byte constants
; ------------------------------------------------------------------------
; Table of decades
; ------------------------------------------------------------------------
DecTable addwf
PC,F ; W + PC -> PC
retlw 0
; 10
retlw 0
;
retlw 0Ah
;
retlw 0
; 100
retlw 0
;
retlw 064h
;
retlw 0
; 1 000
retlw 03h
;
retlw 0E8h
;
retlw 0
; 10 000
retlw 027h
;
retlw 010h
;
retlw 01h
; 100 000
retlw 086h
;
retlw 0A0h
;
retlw 0Fh
; 1 000 000
retlw 042h
;
retlw 040h
;
; ------------------------------------------------------------------------
; Conversion BCD -> 7 segments
; ------------------------------------------------------------------------
LEDTable addwf
PC,F ; W + PC -> PC
retlw b'00111111' ; ..FEDCBA = '0'
retlw b'00000110' ; .....CB. = '1'
retlw b'01011011' ; .G.ED.BA = '2'
retlw b'01001111' ; .G..DCBA = '3'
retlw b'01100110' ; .GF..CB. = '4'
retlw b'01101101' ; .GF.DC.A = '5'
retlw b'01111101' ; .GFEDC.A = '6'
retlw b'00000111' ; .....CBA = '7'
retlw b'01111111' ; .GFEDCBA = '8'
retlw b'01100111' ; .GF..CBA = '9'
retlw b'10000000' ; H....... = '.'
; ------------------------------------------------------------------------
; Table for RF shift
; example: 10.7 MHz is set as 1 070 000 = 10 53 B0
hex
; ------------------------------------------------------------------------
MFTable addwf
PC,F
retlw 010h
retlw 053h
retlw 0B0h
; ------------------------------------------------------------------------
; Routine for conversion of 3 byte number into 7
digits
; ------------------------------------------------------------------------
Go
movlw 6*3-1
; pointer to dec. table
movwf Index
; 6*3-1 -> Index
movlw 9
; maximum of substractions
movwf Count
; 9 -> Count
clrf Help
movlw 6
movwf LEDIndex
Divide call
Subc24 ; substract untill result is negative,
btfsc Status,CF ; add last substracted
number
goto Add24
; next digit
incf Help,F
decf Count,F
btfss Status,ZF
goto Divide
movlw 3
subwf Index,F
goto Next
Add24 call
Addc24
movlw 03h
subwf Index,F
Next movlw
9
movwf Count
movlw LED1
; LED1 -> W
addwf LEDIndex,W ; LED1 + LEDIndex
-> W
movwf Temp
decf Temp,F
; LEDIndex+LED1-1 -> TEMP
movf Temp,W
movwf FSR
; W -> FSR
movf Help,W
; Help -> W
clrf Help
; save result at LEDx
movwf IndF
; W -> LED(6..1)
decf LEDIndex,F
movlw 1
addwf Index,W
btfss Status,ZF
goto Divide
movf LowB,W
movwf LED0
; the rest -> LED0
; -------------------------------------------------------------------------
; registers LED0..LED6 are filled with values
; -------------------------------------------------------------------------
clrf TimerH
clrf Timer0
nop
nop
clrf LEDIndex
movlw .60
; set initial counter value
movwf Index
; 60 -> Index
clrf IntCon
; global INT disable, Timer0 INT disable
; clear Timer0 overflow bite
; ------------------------------------------------------------------------
; Start measurement: RA3 + RA4 set input
; ------------------------------------------------------------------------
movlw b'00010000' ; all ports set L, RA4
set H
movwf PortA
bsf Status,RP0
movlw b'00011000' ; RA0..RA2 output,RA3,RA4
input
movwf TrisA
bcf Status,RP0
; -------------------------------------------------------------------------
; 7-step cycle of digits
; -------------------------------------------------------------------------
LEDCycle movlw
LED0
addwf LEDIndex,W ; LED1 + LEDIndex
-> W
movwf FSR
; W -> FSR
movf IndF,W
; LED(0..6) -> W
call LEDTable ; W
contains segments
movwf Temp
; test for decimal point
movlw 5
bsf Status,ZF
subwf LEDIndex,W
btfss Status,ZF
goto NoDot
bsf Temp,7
NoDot movf
Temp,W
movwf PortB
; segments -> PortB
movf LEDIndex,W ; LEDIndex ->
W
nop
movwf PortA
; digit number -> PortA
; ------------------------------------------------------------------------
; Test for TMR0 overflow
; ------------------------------------------------------------------------
btfss IntCon,2
goto DoNothing
incf TimerH,F ; YES!
Increment SW counter
bcf IntCon,2
; clear overflow bite
goto O_K
DoNothing nop
nop
nop
; ------------------------------------------------------------------------
; The first timing loop 2+3*T1+X procesor cycles
; ------------------------------------------------------------------------
O_K
movlw T1
movwf Temp
Pause decfsz
Temp,F
goto Pause
nop
;
nop
; X times NOP
;
nop
; ------------------------------------------------------------------------
incf LEDIndex,F
movlw 7
; is 7th?
bcf Status,ZF
subwf LEDIndex,W
btfss Status,ZF
goto LEDCycle ; next
digit
nop
; ------------------------------------------------------------------------
; The second timing loop 2+3*T2+Y procesor cycles
; ------------------------------------------------------------------------
movlw T2
movwf Temp
Again decfsz
Temp,F
goto Again
nop
nop
; Y times NOP
nop
; ------------------------------------------------------------------------
clrf LEDIndex
decfsz Index,F
goto LEDCycle ; next
7xLED
nop
; ------------------------------------------------------------------------
; The third timing loop 2+3*T3+Z procesor cycles
; ------------------------------------------------------------------------
movlw T3
movwf Temp
EndPause decfsz
Temp,F
goto EndPause
nop
nop
; Z times NOP
nop
; ------------------------------------------------------------------------
; Final test for TMR0 overflow
; ------------------------------------------------------------------------
btfss IntCon,2
goto Nothing2Do
incf TimerH,F
bcf IntCon,2
goto Nx
Nothing2Do nop
nop
nop
; ------------------------------------------------------------------------
; Stop the measurement
; ------------------------------------------------------------------------
Nx
clrw
movwf PortB
movlw b'00010000' ; RA0..RA3 = 0
movwf PortA
; W -> PortA
bsf Status,RP0
movlw b'00010000' ; RA0..RA3 output
movwf TrisA
; RA4 input
bcf Status,RP0
; ------------------------------------------------------------------------
; Analyse precounter and store counted value in registers
; ------------------------------------------------------------------------
movf Timer0,W
movwf MidB
; TMR0 -> MidB
movf TimerH,W
movwf HigB
; TimerH -> HigB
clrf Temp
CountIt incf
Temp,F
bsf PortA,3
; _| false impulz
bcf PortA,3
; |_
bcf IntCon,2
movf Timer0,W ; actual
Timer0 -> W
bcf Status,ZF
subwf MidB,W
btfsc Status,ZF
goto CountIt
incf Temp,F
comf Temp,F
incf Temp,F
incf Temp,W
movwf LowB
goto Go
; start new cycle
; ------------------------------------------------------------------------
org 0
end
|