TOCKI girişi ile Frekans Sayma?

Başlatan Manolya, 13 Şubat 2007, 23:40:03

Manolya

Merhaba TOCKI girişi ile belli bir zaman içinde misal 1snde gelen pulsları sayacak bir program yazmaya calışıyorum. Bir nevi frekansmetre gibi. Hassas bir zamanlama ile, timer ve tocki girişini birlikte nasıl kullanabilirim?

aYe

Minumum 2 adet timer olan bir pic seçerseniz şöyle olabilir;

temp adında değişken tanımla (ihtiyaca göre 1 veya daha çok byte)

tmr1'i 1sn periyodla interrupt verecek şekilde set et

tmr0'i tocki clock girişli taşmada interrupt verecek şekilde set et

temp'i sıfırla

tmr0'ı sıfırla

tmr0'i başlat

tmr1'i başlat

(intterrupt rutin)
tmr0 taştı?
temp'i 1 arttır

tmr1 taştı?
sonuç=(temp*255)+tmr0

döngü....

Biraz tarzanca oldu ama bu pc'de elektroniğe dair bir tek program yok,  yeterli gelmezse yarın flowchart eklerim  :D
Dünyada iki şey sonsuzdur. İnsanın aptallığı ve evren. Ancak ikincisinden o kadar emin değilim... (Einstein)

armys2000

@Manolya Hangi Derleyiciyi kullanacağını ve ölçme hassasiyetinin ne olacağını  bilmiyorum ama.. @aye hocanın anlattığına benzer bir yolla yapılmış bir kod.  Bu Kod belki bir fikir verebilir. Hassasiyet önemli ise hocamın dediği gibi çift timer ı olan bir pic secip timer0 ı puls ölçmede timer1 i de (interuptla ) ölçme aralığını hesaplamada kullanırsan ve de asm de yazarsanız Sağlıklı olacağını düşünüyorum. Dikkat etmen gerek yer  aynı anda iki timer int kullanman olacak. Çünkü Timer1 i 1 sn lik ölçme aralığı için kullandığında buseferde timer0 ın puls kesmeleri gelecek  bir şekilde timer1 kesmesini durdurman gerekli  yok sa iç içe kesmeler olur.  
   ' Pulse counter
    ' =============
    '
    ' File name : Count_Display.bas
    ' Company : Mister E
    ' Programmer : Steve Monfette
    ' Date : 27/12/2004
    ' Device : PIC16F84A-20/P
    '
    '
    ' This program display to 3 x 7 segments dislay the result of
    ' pulses count on PORTA.4 pin/sec.
    '
    '
    ' Hardware connection :
    ' ---------------------
    '      1. 3 X 7 segments display on PORTB<7:0>
    '      2. 3 X PNP transistor on PORTA<3:0> to drive common anode
    '         of each 7 segments display
    '
    '
    ' Programming mode and PIC define
    ' -------------------------------
    '
        @ __config _HS_OSC & _WDT_ON & _PWRTE_ON
    ' HS oscillator
    ' Enable watch dog timer
    ' Enable power up timer
    '
    DEFINE OSC 20 ' use 20 MHZ oscillator


    ' I/O Definition
    ' --------------
    '
    TRISA = %11110000 ' PORTA  : <2:0> outputs to common Anode of 7 segment
                      '                1. PORTA.0 More significant
                      '                2. PORTA.2 Less significant
                      '        : PORTA.4 input for signal
                      '
    TRISB = 0         ' PORTB connected to 7 segments
                      '       B0 : segment a
                      '       B1 : segment b
                      '       B2 : segment c
                      '       B3 : segment d
                      '       B4 : segment e
                      '       B5 : segment f
                      '       B6 : segment g
                      '       B7 : segment decimal dot
                      

    ' Internal EEPROM definition
    ' --------------------------
    '
    Data @0,192,249,164,176,153,146,130,248,128,144 ' table to convert
                                                    ' numbers to 7 segments
                                                    ' pattern output when
                                                    ' drive invert
                                                    


    ' Interrupt and register definition
    ' ---------------------------------
    '
    OPTION_REG = %1111000   ' TMR0 clock source : RA4/T0CKI
                            ' increment on low to high transition
                            ' Prescaler assign to WDT
                            ' WDT rate 1:1
                            '
    INTCON = %10100000      ' Enable global interrupt
                            ' Disable EE write interrupt
                            ' Enable TMR0 overflow interrupt

        
    ' Variable definition
    ' -------------------
    '
    DisplayPort  VAR PORTB   ' Port for 7 Segments
    ClockInput   VAR PORTA.4 ' Input pin for signal
    _7Seg1       CON 14      ' enable more significant 7 segment display
    _7Seg2       CON 13      ' enable mid significant 7 segment display
    _7Seg3       CON 11      ' enable less significant 7 segment display
    Digit_1          VAR BYTE    ' Hundreds digit
    Digit_2          VAR BYTE    ' Tenth digit
    Digit_3          VAR BYTE    ' Unit digit
    ToBeDisplay  VAR WORD    ' Result of count to be send to 7 segment display
    Display      VAR BYTE    ' Temp variable
    DisplayLoop  VAR BYTE    '
    Delay        VAR WORD    ' Variable for Delay loop
    OverFlowVar  VAR WORD        '
    Thousands    VAR BIT         ' Flag for count >= 1000 & < 10 000
    TenThousands VAR BIT         ' Flag for count >= 10 000

    ' Variable and software initialisation
    ' ------------------------------------
    '
    tobedisplay = 0 ' set initial value of count
    TMR0 = 0        ' reset prescaller
    ON INTERRUPT GoTo SetVarToBeDisplay
    
MainLoop:

    ' MainLoop
    ' ---------
    '
    ' 1. display the result of the count on RA4 pin
    ' 2. refresh display
    ' 3. reset Timer0
    ' 4. reload prescaler.
    '
    ' Duration of the procedure : 1 sec
    '           fine tuned by DelayBetweenEachDisplay Sub
    '
    ' Looping 1 sec and get results of the pulse count in
    ' TMR0 + OverFlowVar
    '
DisplayRefresh:
        '
    ' Testing amount of count
    ' -----------------------
    '
    ' Get the result of count and place decimal point flag
    ' on the according 7 segments
    '
    IF tobedisplay >= 1000 Then
        tobedisplay = tobedisplay / 10
        IF tobedisplay >= 1000 Then
                tobedisplay = tobedisplay / 10
                thousands = 0
                tenthousands = 1
        Else
                tenthousands = 0
                thousands = 1
        End IF
     Else
        thousands = 0
        tenthousands = 0
    End IF
    '
    ' convert digit to 7 segment output pattern
    ' -----------------------------------------
    display=ToBeDisplay DIG 2 ' Read hundreds digit
    Read display, digit_1     ' Convert hundreds
        IF thousands==1 Then digit_1=digit_1 & $7F ' enable decimal dot
                                                   ' by clearing PORTB.7

    display=ToBeDisplay DIG 1 ' Read tenths digit
    Read display, digit_2     ' Convert tenths
    IF tenthousands==1 Then digit_2=digit_2 & $7F ' enable decimal dot                          '
                                                  ' by clearing PORTB.7
                                                  
    display=ToBeDisplay DIG 0 ' Read units digit
    Read display, digit_3     ' Convert units
    '
    '
    ' Send digit to 7 segments
    ' ------------------------
    For displayloop = 0 TO 111 ' loop for about 1 sec

        ' display hundreds
        ' ----------------
        PORTA=_7seg1        ' enable hundreds 7 segment
        displayport = digit_1 ' display
        GoSub DelayBetweenEachDigit
        
        ' display tenth
        ' -------------
        PORTA=_7seg2        ' enable tenth 7 segment
        displayport = digit_2 ' display
        GoSub DelayBetweenEachDigit
        
        ' display units
        ' -------------
        PORTA=_7seg3        ' enable unit 7 segment
        displayport = digit_3 ' display
        GoSub DelayBetweenEachDigit
        
    Next
    tobedisplay = OverFlowVar + TMR0
    OverFlowVar = 0 ' Reset OverFlowVar
    TMR0 = 0        ' reset prescaller
    GoTo DisplayRefresh


DelayBetweenEachDigit:

    ' DelayBetweenEachDigit
    ' ---------------------
    ' Produce delay of about 3 mSec
    '
    ' Fine tuned with MPLAB StopWatch to get MainLoop = 1 sec
    '
        For delay = 1 TO 307
            @ nop
        Next
        @ nop
        @ nop
        @ nop
        @ nop
        @ nop
        @ nop
        @ nop
    Return


    Disable
SetVarToBeDisplay:
    '
    ' SetVarToBeDisplay
    ' -----------------
    ' interrupt routine of TMR0 overflow
    '
    ' Reset prescaller
    ' Reset overflow flag
    '
    OverFlowVar = OverFlowVar + 256
    INTCON 0.2 = 0 ' clear overflow flag
    TMR0 = 0     ' reload TMR0
    Resume
    Enable

Manolya

Proton derleyici kullanıyorum. lojik çıkış veren bir sistemden ölçme yapmam gerek dakikada kaç kez 1 yada kaç kez 0 geldiğini bulmam gerek işin doğrusu bu. İşlemci olarak 16F877 kullanmam gerek. Datasheetini inceledim 2 adet timer mevcut. Bu iş için Tocki kullanmam gerekiyor. diğer yandan ;
Counter komudu ile hassas olmuyor. Birde programı çok aksatıyor. Bu timer ve tocki sanırım programdan bağımsız çalışabiliyor. Fakat hassas bir zamanlama yakalayamadım. ilginiz için teşekkürler

aYe

armys2000 hocamım da dediği gibi hassas birşey istiyorsanız kodu asm yazmak zorundasınız zaten 30-40 byte'i geçmez.

Ölçme de bir kaç cycle'lik hata olası bir ihtimal ama göz ardı edilebilir.
Dünyada iki şey sonsuzdur. İnsanın aptallığı ve evren. Ancak ikincisinden o kadar emin değilim... (Einstein)

Maxim

Galiba aynı sorunu bende yaşıyorum ,
Capture komutu yeterli gelmiyor ,
16F876 da 16 bitlik hardware capture özelliğini kullanmak için uğraşıyorum .