Fonksiyon için interrupt seçimi.

Başlatan enrique34, 26 Mart 2016, 14:26:46

enrique34

Merhaba arkadaşlar;
Pek kesmelerle işim olmadı daha çok matematiksel çalıştım. Kesme yaptıysamda hesap kitap için, haberleşme,encoder okumak ve buton v.s. İçin yaptım.

Şimdi 4 farklı pinden gelen 50hz lik pulslerim var.
Ben bu pulse nin high da kalma süresini kesme kullanarak nasıl hesaplarım? Çözünürlük en yüksek şekilde...

Min puls high kalma süresi 1000uS
Max puls high kalma süresi 2000uS


Saygılarımla

ete

High da kalma süresi en güzel TMR ile hesaplanır. Frekans girişi için yükselen kenarda kesme aktive edilir. Kesme oluşunca TMR1 sıfırlanır ve Bölme oranı 1/1 olarak ayarlanarak (T1CON registerinden) kesme düşen kenara çevrilir.
Yeniden kesme oluştuğunda TMR1 sana HIGH süresini ms olarak verir. Bu dediklerim 4Mhz kristal ferkansı için geçerlidir.
Farklı frekanslar için TMR1 hesabı bir çevrim süresine bağlı olarak hesaplanmalıdır.

Yalnız 4 adet sinyalin var hangisini böyle ölçersin bilemem. Picde 4 timer yok. Bazı yeni nesillerde fazla timer var ama hangisi şu anda hatırlamıyorum.
Metod bu ama sen kendine göre bir yöntem bulacaksın artık.

Ete

enrique34

Ete hocam cevap için teşekkürler, bilgiler doğrultusunda bir deneme yapayım, en azından tmr ile olduğunu anladım, kodlarımı paylaşacağım...

enrique34

#3
Selam;
Vermiş olduğunuz fikir ile timer1 kullanarak high'da kalma süresini ölçebildim, Program 4Mhz 1:1 oran ile çalışıyor sorun yok....
Kesmeye gitmesi için PORTB 'nin changed kesmesini kullandım 4.5.6.7 için....
Belki birilerine lazım olur diyerek kodlarımı ekledim.
Ama benim tam olarak istediğim gibi olmadı biraz tabiri caiz amele işi oldu gibi..
Uzun tutmamak için 2 kanal okuyor şeklinde yaptım kesme içerisinde toplam 4mS 'lik bir gecikme sanırım kaçınılmaz. Her bir kanal okuma aralığında 2mS'lik bir gecikme oluşuyor.. Bunu 4 kanal için yaparsam 8mS heba oluyor.
Bir inceleyip değerlendirseniz memnun olurum...
Saygılarımla....

NOT : 1000uS pulse uyguladım 1000 ile 1005 arası değişiklik algılıyor. Bu fazlalık 5 'in sebebi kod gecikmesimidir?


Device 18F452
Xtal = 4
Declare LCD_Interface 4
Declare LCD_DTPin PORTD.4
Declare LCD_ENPin PORTD.2
Declare LCD_RSPin PORTD.3
TRISB =%11110000
'INTCON REGISTER KODLARI
Symbol RBIF   = INTCON.0  ' PORTB changed kesme bayrağı 1: Portlardan birinde değişiklik oldu (okuduktan sonra sıfır yapmalıyım)
Symbol INT0IF = INTCON.1  ' INT0 External kesme bayrağı 1: Değişiklik oldu (Okuduktan sonra sıfır yapmalıyım)
Symbol TMR0IF = INTCON.2  ' TMR0 Taşma bayrağı 1: Taşma oldu (okuduktan sonra, bir sonraki kesmeler için sıfır yapmalıyım) 
Symbol RBIE   = INTCON.3  ' PORTB changed  kesmesi
Symbol INT0IE = INTCON.4  ' INT0 External kesmesi enable biti
Symbol TMR0IE = INTCON.5  ' Timer0 overflow kesmesi enable biti
Symbol PEIE   = INTCON.6  ' Çevresel kesme enable biti
Symbol GIE    = INTCON.7  ' Global interrupt enable bit
RBIF   = 0
INT0IF = 0
TMR0IF = 0
RBIE   = 1
INT0IE = 0
TMR0IE = 0
PEIE   = 1
GIE    = 1

'T1CON REGISTER KODLARI
Symbol TMR1ON  = T1CON.0  'Timer1 on off
Symbol T1CKPS1 = T1CON.4   'Timer1 Input Clock Prescale Select bits with t1ckp0
Symbol T1CKPS0 = T1CON.5   ' 00:1/1
T1CON = 1
T1CKPS1=0
T1CKPS0=0
'tmr1h=$FF
'TMR1L=$F6
TMR1H=$00
TMR1L=$00

'PIR1 REGİSTER KODLARI
Symbol TMR1F = PIR1.0  'Timer1 interrupt flag
TMR1F=0

Symbol CH1 = PORTB.7
Symbol CH2 = PORTB.6
Symbol CH3 = PORTB.5
Symbol CH4 = PORTB.4
Dim ch1_count As Word
Dim ch2_count As Word
Dim ch3_count As Word
Dim ch4_count As Word
Dim i As Byte


On Interrupt GoTo int
Enable

start:
Print At 1,1, Dec9 ch1_count
Print At 2,1, Dec5 ch2_count

GoTo start

Disable
int:
'READ FOR FIRST CHANNEL 2MS KAYIP
If CH1=0 Then '  'LOW 'da catch yapmış olabiliriz
    While CH1=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH1=1    ' temiz high kadar bekle
    Wend
    ch1_count.Byte0=TMR1L
    ch1_count.Byte1=TMR1H
Else           ' high 'da catch yapmış olabiliriz.
    While CH1=1    'high çıkana kadar bekle
    Wend
    While CH1=0    'low çıkana kadar bekle
    Wend            'çıktığında high olacak
    TMR1H=0
    TMR1L=0
    While CH1=1     'temiz high kadar bekle
    Wend
   ch1_count.Byte0=TMR1L
   ch1_count.Byte1=TMR1H
EndIf

'READ FOR SECOND CHANNEL 2MS KAYIP
If CH2=0 Then '  'LOW 'da catch yapmış olabiliriz
    While CH2=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH2=1    ' temiz high kadar bekle
    Wend
    ch2_count.Byte0=TMR1L
    ch2_count.Byte1=TMR1H
Else           ' high 'da catch yapmış olabiliriz.
    While CH2=1    'high çıkana kadar bekle
    Wend
    While CH2=0    'low çıkana kadar bekle
    Wend            'çıktığında high olacak
    TMR1H=0
    TMR1L=0
    While CH2=1     'temiz high kadar bekle
    Wend
   ch2_count.Byte0=TMR1L
   ch2_count.Byte1=TMR1H
EndIf

'TOPLAM 4MS KAYIP İLE ÇIKIŞ YAPTIK
TMR1F = 0
RBIF   = 0 
Resume
Enable
End

MB_77

#4
bu mesaj tarafımdan silinmiştir.

MB_77

#5
bu mesaj tarafımdan silinmiştir.

enrique34

Merhaba asıl yapmak istediğim zaten sizin söylediğiniz gibi ama ufak bir sorun var. Bunu int0 kesmesi ile yapabiliyoruz sadece. Yani bunun için ayrılmış sadece bir kesme var. Ben 4 kanallı bir kesme istiyorum buda pic'de sadece portb değişiklik kesmesi, Ama bundada yüksek kenar alçak kenar ayarlaması yapılamıyor.
low-high kesme oluşuyor,
high-low kesme oluşuyor...
iki kere kesmeye giriyor...

enrique34

#7
4 Farklı kanala ait osiloskop görüntüsünü ekledim
Biraz daha az gecikmeli soft kesme rutinim şu şekilde;

Disable
int:
If CH1=0 Then
    While CH1=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH1=1    ' temiz high kadar bekle
    Wend
    ch1_count.Byte0=TMR1L
    ch1_count.Byte1=TMR1H
EndIf

If CH2=0 Then
    While CH2=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH2=1    ' temiz high kadar bekle
    Wend
    ch2_count.Byte0=TMR1L
    ch2_count.Byte1=TMR1H
EndIf

If CH3=0 Then
    While CH3=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH3=1    ' temiz high kadar bekle
    Wend
    ch3_count.Byte0=TMR1L
    ch3_count.Byte1=TMR1H
EndIf
If CH4=0 Then
    While CH4=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH4=1    ' temiz high kadar bekle
    Wend
    ch4_count.Byte0=TMR1L
    ch4_count.Byte1=TMR1H
EndIf   



TMR1F = 0
RBIF   = 0 
Resume
Enable
End

MB_77

#8
bu mesaj tarafımdan silinmiştir.

enrique34

ilk denemem şu şekilde idi ;
alel acele yazıyorum yanlışlık olabilir,mantık olarak

If CH1=1 And ch1_status=0 Then
ch1_status=1
tmr1_first.Byte0=TMR1L
tmr1_first.Byte1=TMR1H
EndIf
If CH1=0 And ch1_status=1 Then
ch1_status=0
tmr1_second.Byte0=TMR1L
tmr1_second.Byte1=TMR1H
ch1_count=tmr1_second-tmr1_first
EndIf

MB_77

#10
bu mesaj tarafımdan silinmiştir.

enrique34

#11
Baya problemli bir algoritma oldu maalesef :)

Şimdi aşağıda iki farklı kod yazdım denedim, default 1000uS lik bir puls ile;
Bu kodun sonucu : 1805uS olmadı :/ 805us fazlalık var

If CH1=1 And ch1_status=0 Then
        tmr1_first.Byte0=TMR1L
        tmr1_first.Byte1=TMR1H
        ch1_status=1
EndIf
If CH1=0  And ch1_status=1 Then
    ch1_status=0
    tmr1_second.Byte0=TMR1L
    tmr1_second.Byte1=TMR1H
    If tmr1_second < tmr1_first Then
            tmr1_first=65535-tmr1_first
            ch1_count=tmr1_first+tmr1_second
        Else   
            ch1_count=tmr1_second-tmr1_first
    EndIf
EndIf


Bu kod çıktısı : 1005uS :) ama while istemediğim bir komut ile yazdım...Kesmeden hemen çıkamıyorum dediğiz gibi...Amele yöntemi diyorum buna çünkü çabuk sonuca vardım :)


If CH1=0 Then
    While CH1=0  ' low'da iken bekle
    Wend          'çıktığında temiz high olacak
    TMR1H=0       
    TMR1L=0
    While CH1=1    ' temiz high kadar bekle
    Wend
    ch1_count.Byte0=TMR1L
    ch1_count.Byte1=TMR1H
EndIf

MB_77

#12
bu mesaj tarafımdan silinmiştir.

enrique34

#13
kodlarım aynen bu şekilde; başka üst tanımlamalarım ilk mesajımdaki gibi.... Dönüp duruyorum ama bir hata bulamadım :) bide siz bakın başım döndü.. :)


On Interrupt GoTo int
Enable

start:
Print At 1,1, Dec4 ch1_count
GoTo start

Disable
int:
If CH1=1 And ch1_status=0 Then
        tmr1_first.Byte0=TMR1L
        tmr1_first.Byte1=TMR1H
        ch1_status=1
EndIf
If CH1=0  And ch1_status=1 Then
    ch1_status=0
    tmr1_second.Byte0=TMR1L
    tmr1_second.Byte1=TMR1H
    If tmr1_second < tmr1_first Then
            tmr1_first=65535-tmr1_first
            ch1_count=tmr1_first+tmr1_second
        Else   
            ch1_count=tmr1_second-tmr1_first
    EndIf
EndIf
TMR1F = 0
RBIF   = 0 
Resume
Enable
End



MB_77

#14
bu mesaj tarafımdan silinmiştir.

Powered by EzPortal