timer1 kesmesi

Başlatan black, 26 Eylül 2014, 16:36:05

black

Merhaba forum üyeleri,

	
BCF      PIR1,TMR1IF     
MOVLW    0xFC   
MOVWF    TMR1H           
MOVLW    0xFD
MOVWF    TMR1L


osilatör = 10mhz

prescaler = 1:2

tmr1h + tmr1l =64765

timer

x =((65536 - (tmr1h+tmr1l))* prescaler*count) / fkomut

x = (771*2*count)/2500000

x: süre sonra kesme olacak.

buradaki count nedir ?

Yardımlarınızı bekliyorum


ete

Hesaplamanın Hz cinsinden ve süreninde us cinsinden hesaplanması için count=1.000.000 değerini alan bir çevrim faktörüdür.
Ben hesabı şöyle yaparım.
TMR1= 64765 değerinden saymaya başlayacak. Nereye kadar 65536 ya kadar . O halde ne kadar sayacak 65536-64765= 771
Bölme oranı 1/2 olduğu için bu rakamı 2 ile çarparım. O halde sayılacak puls değeri 771*2=1542 puls.
OSC frekansı 10 Mhz olduğundan bir komut çevrimi 1/10=0,4us olacaktır. O halde 1542 komut çevrimi ,
1542 x 0,4=616,8 us bu durumda her 618,8 us de bir kesme oluşacak demektir.

Ete

black

yani count formülde olmaması gereken bir değişken.

matematiksel olarak hesapladığımızda zaten us veya ms çıkacaktır.

formülümden count değerini çıkarıyorum.

timer1 taşma süresi böyle hesaplanıyorum diyorum o zaman ete hocam teşekkürler.


ete

#3
İlla bir formül istiyorsan,

X=((65535-(TMR1)+1)*Bölme_Oranı*4)/Kristal Frekansı (Mhz)
Örneği tekrarlarsak,
X=((65536-64765)*2*4)/10
X=(771)*2*4/10=616,8 olarak bulunmuş olur.

Senin formülde yer alan yanlış bir ifadeyide düzeltmek gerekir. O da şu , (tmr1h+tmr1l)
Biliyorsun TMR1 16 bitlik bir sayac ve her biri 1 byte olan iki bileşeni var. Bunlar TMR1H ve TMR1L bileşenleri.
Bunları bir birine ekleyerek TMR1 değerine ulaşılmaz. Desimal sistemde bu iş (TMR1H*256+TMRL) hesabı ile yapılır.
Bu nedenle o formülde bu iki bileşen yerine direk TMR1 yazılması daha doğru olur. Sonuçta orada 65536 dan TMR1 değeri çıkartılmaktadır.

Ete

black

konu net bir şekilde anlaşıldı.

teşekkürler ete hocam.

Hattuşa

#5
sevgili ete hocam, timer0 ile bir kesme oluşturdum ve bu kesme ile yaklaşık 8mS de bir işlem yaptırıyorum buraya kadar sorun yok. sorunum şu; timer1 de aktif edip ölçtüğüm adc değerine göre değişen [min.500 hz (2mS)- max. 5khz (200uS)] bir çıkış alabilirmiyiz?
sorunum şu hocam 40mhz le çallıştığımız için min. 4khz altına inemiyoruz. o yüzden bu işi pwm e yaptırma şansımız yok.

ete

#6
sorunun cevabını PicMultiCalc yardımcı programı ile bulmak mümkün.
"Timer Helper" seçeneğini seçip,
-OSC hanesine 40 yani 40 Mhz yazıp
- "Interrupt/Frequency" hanesinde Hz seçeneğini seçip kutuya 500 yazarsan
Sana aşağıda TMR1 seçeneklerini verecektir. Tercihen 1/1 bölme oranını kullanarak 500 Hz için Preload olarak 45543 değerini alıyoruz.
Benzer şekilde bu sefer de 5 Khz için yine 1/1 bölme oranı ile preload değerini 63542 olarak alıyoruz.
Bundan sonrası zor değil artık. Zira bu iki değerin farkı Fark=63542 - 45543= 17999 olarak bulunur. Bu değer bizim ADC ile değiştireceğimiz değer olacaktır. Yani ADC den sıfır değer okuduğumuzda TMR1 değerimiz 45543 olacak , ADC den 1023 okuduğumuzda ise TMR1 ön yükleme değerimiz 63542 olacaktır. Yapılacakları şöyle sıralayabiliriz.
- Timer1 kesmesi 1/1 bölme oranı ile aktive edilecek.
- ADC den okunacak olan 0-1203 (toplam 1024 aralık) aralığında bir değer elde edilecektir.
- Bu değeri Önyükleme değerine çevirecek bir formül kullanılacak ve öyükleme değeri hesaplanacak
- En sonunda kesme içinde kesmeden çıkmadan yeni önyükleme değeri olarak bu değer kullanılacaktır.
- Böylece sistem ADC değerine bağlı olarak istenilen aralıkta kesme üretecektir.

Bu aşamada bir formül hesaplamamız gerekiyor.
Fark=17999 idi. Bunu 18000 kabul edelim ve 1024'e bölelim. bölersek 17,5578125 gibi bir değer elde ediyoruz. Bunu 256 ile çarparak sabit çarpanımızı buluruz. Buda 4500 değeri olacaktır.
Bu durumda formülümüz , On_Yukleme=(Adc_Deger+1)*/4500+45542 şeklinde olacaktır.
Hemen bir deneme yaparsak , ADC=0 değerine karşılık Önyükleme =45543 , ADC=1023 değerine karşılık ise 63542 değeri hesaplanmış olacaktır. Bu da istediğimiz değerdir.

Kesmeye min değer olan 45543 değeri verilerek başlanmalıdır.
Hemen ardından ADC okunarak karşılık gelen ön yükleme hesaplanıp ilk kesme içinde yeni önyükleme değeri olarak bu hesaplanan değer verilmelidir. Bu şekilde sistem istenildiği gibi çalışacaktır.

Ete

Hattuşa

#7
slm ete hocam;

kusura bakmayın rahatsız edip duruyorum. bahsettiğiniz şekilde olursa şayet ben şuan üzerinde kullandığım devreden HPWM1 kanalını ve devamında cny-17 ve 555 i iptal edeceğim ki bu benim için çok iyi olur.
yukarıda bahsettiğiniz şekilde yaptım (yada anladığım kadarıyla yapmaya çalıştım)
kod şu şekilde acaba söylediklerinizi yanlış mı anladım hocam bir kontrol edebilirmisiniz? gerçekte henüz deneyemedim ama isisde deniyorum bir çıkış veriyor ancak isisde işlemciyi GLCD yüzünden 40 mhz de çalıştıramadığımız için çok yavaş çalıştırıyoruz (6mhz) buda çıkışı etkiliyor.

NOT: hocam kafama takıldı şimdi şöylesi bir sorum var, tmr0 8 bitlik bir sayaçta tmr1 ise 16 bitlik kesme içerisinde ifleri kullanırken öncelik tmr1 den mi başlamalıyım yoksa aşağıda ki gibi de olur mu?
kod şu şekilde;
 Print At 1,1,"TMR0 and TMR1"
Print At 2,1,"ADC:"
DelayMS 10
'500 herz = 1/1 oranında 45543
'5khz =1/1 oranında 63542
'fark = 63542 -45543 =17999 =fark =18000


INTCON.7 =1
B00_MaIn:
While KeS =1
KeS =0
T1 =1   
AdC =ADIn 0
While ADCON0.1 ==1 :Wend 
T1 =0   
OnDeGeR =(AdC +1) */4500 +45543
Print At 2,5,Dec AdC," "
Print At 3,5,Dec OnDeGeR," " 
Wend
GoTo B00_MaIn




Z0_KeSMe:
        Context Save
If INTCON.2 =1 Then
       INTCON.2 =0
         KeS =1
         EndIf
If INTCON3.0 =1 Then
INTCON3.0 =0
           Inc SaY
           If SaY =OnDeGeR Then SaY =45543 :Toggle P1
           EndIf
        Context Restore
        Stop 
End

ete

Sorduğun soru ADC den okunan değere bağlı olarak 500us de bir yada maksimum 200us de bir çıkış alabilirmiyiz şeklinde idi ve bende bunu nasıl TMR1 kesmesi ile yapacağını anlattım.
Bu son verdiğin programda TMR1 kesmesi ile ilgili bir şey göremedim.
Yaptıklarınıda anlamadım doğrusu.
İşin içine proton karışınca ve kod parçası tam verilmeyince anlamam zor oluyor. Ama anladığım kadarı ile TMR1 kesmesi oluşturmadanbir şeyler yapmaya kalkışmışsın.
Hem TMR0 hemde TMR1 kesmesi kullanırsan kesme etiketi altında her ikisinide kontrol etmen gerekiyor.
If INTCON.2 =1 Then
       INTCON.2 =0
         KeS =1
EndIf

kodları TMR0 kesmesine ait bu tamam. İşlemcin belli olmadığı için TMR1 kesmesi ile ilgili bir şey yazamadım.
Ancak , TMR1 kesmesi pek çok işlemcide PIE1 registerinden set edilir. Kesme bayrağı PIR1 registerinde yer alır.
Kesmeyi aktif ettiğini kabul edersek yine kesme etiketinde şunu yapman gerekirdi;
IF PIR1.0=1 then
    PIR1.0=0
    TOGGLE CIKIS  'hangi çıkış ise veya CIKIS=1 yazıp program içinde çıkışı LOW yapabilirsin.
    TMR1L=OneDeger.Byte0
    TMR1H=OneDeger.Byte1
ENDIF

Ete



Hattuşa

hocam tmr1 ile 500hertz ile 5khz arasında değişken frekans üretmek istiyorum. multicalc ile verdiğiniz değerler doğru geldi bana.
tmr1 conf. eklemedim k. bakmayın.hata benden kaynaklı..
konu ile ilgili dosya ektedir.
http://www.yukletr.com/download.php?file=70c294cc10a8623241a670defb3291ef

kod ise ;
Device 18F4520
Xtal 10
Config_Start
   OSC = HSPLL ; HS oscillator, PLL enabled (Clock Frequency = 4 x FOSC1)
   FCMEN = OFF ; Fail-Safe Clock Monitor disabled
   IESO = OFF ; Oscillator Switchover mode disabled
   PWRT = OFF ; PWRT disabled
   BOREN = OFF ; Brown-out Reset disabled in hardware and software
   WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
   MCLRE = On ; MCLR pin enabled; RE3 input pin disabled
   LPT1OSC = OFF ; Timer1 configured for higher power operation
   PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
'   CCP2MX = PORTB ; CCP2 input/output is multiplexed with RB3
   STVREN = OFF ; Stack full/underflow will not cause Reset
   LVP = OFF ; Disabled
   XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
   Debug = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
Config_End
Declare PLL_Req TRUE '40mhz


Declare All_Digital =0
Declare LCD_DTPort =PORTD
Declare LCD_ENPin =PORTB.2
Declare LCD_RWPin =PORTB.0
Declare LCD_RSPin =PORTB.1
Declare LCD_CS1Pin =PORTC.5
Declare LCD_CS2Pin =PORTC.4
Declare LCD_Type = Graphic
Declare Internal_Font =On
Declare Font_Addr = 0
TRISA =%00000001
TRISB =%00000000
TRISC =%00000000
TRISD =%00000000
TRISE =%00000000
PORTA =0
PORTB =0
PORTC =0
PORTD =0
PORTE =0

Symbol T1   =PORTA.5
Symbol P1 =PORTA.3
Symbol LmB  =PORTB.5
Output T1
Output P1
Output LmB

Declare All_Digital =FALSE


A00_kUr:
INTCON =%11100000    '
INTCON2 =%11000100
INTCON3.3 =1
T0CON =%11000111         '1:128 bölme oranı
T1CON =%11111001
ADCON1 =%00001110   '1 kanal Adc
ADCON2.7 =1
Declare Adin_Res 10         ' 10-bit result required      '-----------------------bvuraya hexi yüklerken baaaaaaaaaaaaak
Declare Adin_Tad =64_FOSC       ' RC OSC chosen
Declare Adin_Stime 3   ' Allow 50us sample time

On_Hardware_Interrupt GoTo Z0_KeSMe
INTCON.7 =0


A01_DeG:
Dim AdC As Word
Dim KeS As Byte            :KeS =0
Dim OnDeGeR As Word
Dim SaY As Word
SaY =45543
A02_BASLA:   
Cls
DelayMS 100
Print At 1,1,"TMR0 and TMR1"
Print At 2,1,"ADC:"
DelayMS 10
'500 herz = 1/1 oranında 45543
'5khz =1/1 oranında 63542
'fark = 63542 -45543 =17999 =fark =18000


INTCON.7 =1
B00_MaIn:
While KeS =1
KeS =0
T1 =1   
AdC =ADIn 0
While ADCON0.1 ==1 :Wend 
T1 =0   
OnDeGeR =(AdC +1) */4500 +45543
Print At 2,5,Dec AdC," "
Print At 3,5,Dec OnDeGeR," " 
Wend
GoTo B00_MaIn




Z0_KeSMe:
        Context Save
If INTCON.2 =1 Then
       INTCON.2 =0
         KeS =1
         EndIf
If INTCON3.0 =1 Then
INTCON3.0 =0
           Inc SaY
           If SaY =OnDeGeR Then SaY =45543 :Toggle P1
           EndIf
        Context Restore
        Stop 
End
Include "FONT.INC"


bu arada TMR1L ve TMR1H değerleri hiç aklıma gelmedi.  ;D

Hattuşa

ete hocam yapamadım ya;
Z0_KeSMe:
        Context Save
If INTCON.2 =1 Then
       INTCON.2 =0
         KeS =1
         EndIf
If PIR1.0 =1 Then
PIR1.0 =0
TMR1L =OnDeGeR.Byte0
TMR1H =OnDeGeR.Byte1
P1 =1
           EndIf
        Context Restore
        Stop 


böyle yapınca tmr1 den hiç çıkmıyor ve adc dahi okumuyor.

ete

#11
Data sheet kurcalamak en büyük eksikliğin ve bu konuda ısrar ediyorsun hala.
TMR1 sayacı T1CON registeri tarafından kontrol ediliyor. BU registere verdiğin değere bakalım.
T1CON =%11111001
Data sheet'e de bakarsak,
Bit7:TMR1 in 16 bit mi yoksa 8 bitmi çalışacağını belirliyor 1=16 bit
Bit6:TMR1 osc sinin aynı zamanda işlemci osilatörümü olacağını belirliyor buraya sıfır verilmeli
Bit5-4: Bölme oranı , buraya 00 verilmeli
Bit3: TMR1 enabled veya kapalı seçimi buraya 1 verilmeli
Bit2: TMR1 external CLK select biti burası sıfır yada 1 farketmez asıl değeri 1 ama bir sonraki bit sıfır olunca bu bit göz ardı ediliyor zaten.
Bit1: TMR1 CLK kaynağı seçme biti , buraya 0 erilmeli yani internal clk.
bit0: Enable Tmr1 yani buraya 1 verilmeli
Bu durumda TMR1 resigerine=%10000001 değerinin verilmesi gerekiyor.
Kesmeyi aktive etmek için;
Önce RCON.7=0 verilmeli. Bu kesmelerde öncelik biti olup kesmeler senin anlayacağın şekilde çalışsın istiyorsan bu biti sıfır yapman daha doğru.
Sonra;
INTCON=%11100000
PIE1.0=1
PIR1.0=0
Şeklinde kesmeleri aktive etmen gerekir.
PBP da ayrıca ON INTERRUPT GOTO KESME diye bir komut daha ekliyoruz. Proton karşılığı neyse eklersin.
Kesmeye bağlı bir karedalga üretebilmek için her kesme oluştuğunda sinyalin çıkacağı pine konum değiştirmek gerekir. Bunu yapan komut da TOGGLE komutudur. Yada 1-ÇıkışPini demek yeterli olur. Seninkodlarında buna benzer bir şey göremedim.
TMR0 kesmesi ne işe yarıyor acaba? Görünüşe bakılırsa sadece Kes=1 yapıyor ne amacı var bunun.?
Her neyse ben TMR1 kesmesine odaklanayım.

Sonra Kesme içinde,
Z0_KeSMe:
        Context Save
If INTCON.2 =1 Then
       INTCON.2 =0
         KeS =1
         EndIf
If PIR1.0 =1 Then
   PIR1.0 =0
   Toggle CıkısPini veya CıkısPini=1-CıkısPini yazman sinyali oluşturacaktır.
   TMR1L =OnDeGeR.Byte0
   TMR1H =OnDeGeR.Byte1
   P1 =1 'bu neyse silinebilir
EndIf
        Context Restore

Bu işlemcide bir kesme önceliği sistemi olduğunu belirtmiştim. Şayet aynı anda kesme oluştuğu zaman öncelik TMR1 kesmesine verilsin istiyor isen bu özelliği kullanabilirsin. Bunun için RCON.7=1 vereceksin. Ayrıca IPR1.0=1 vermen gerekiyor. Böylece bu kesme önceliğe sahip olmuş olacaktır.
Ancak yukarıdaki kullanım şeklinde ilk bakılan TMR0 registeri olacak ve şayet aynı zamanda TMR1 kesmeside oluşmuş ise onunda işlemi aynı seferde yapılacaktır. Bence öncelik kullanmaya gerek yok.
Hepsi bu kadar.
Ete

Hattuşa

#12
@ete hocam
bizim sorunumuz şu (en azından benim), bu yazılımı öğrenirken kopyele yapıştır yapıyoruz. yani bir yerlerden kopyelediğimiz kodları zaman içerisinde değişikliğe uğrattığımızda bu tip sıkıntılar yaşıyoruz.

hocam herneyse hazır bir cevap yazmışken sizi biraz daha sıkıştırayım. ;D

proton veya basicte iki tip kesme var sanırım. bunlardan birisi sizin kullandığınız "ON INTERRUPT GOTO KESME" ve benim kullandığım "On_Hardware_Interrupt GoTo KeSMe"


ON INTERRUPT GOTO KESME de


 disable
kesme:
' kodlar
resume
enable



On_Hardware_Interrupt GoTo KeSMe de ise
kesme:
context save
' kodlar
context restore


kullanılmaktadır. aralarında ki fark nedir, birbirlerine üstünlükleri veya dezavantajları varmıdır?


bu arada mesajda yazdıklarınızı ilk fırsatta deneyeceğim. bize tahammül ettiğiniz için tşk ederim.

NoT: hocam az önce denedim isisde doğru çalışıyor. ben neden ekledim bilmiyorum ama INTCON3.3 =1 yapmışım onu silince çalıştı.  ;D

ete

Biri yaılım diğeri donanım kesmesi olarak gözüküyor. Donanım kesmesinde işlemcinin can alıcı registerleri kayıt edilip kesmeden çıkarken yeniden geri yükleniyorki bu olması gereken gerçek kesme. PBP bunu yapamadığı için basic komutu bitmeden kesme oluşturamıyor. Donanım kesmesinde komuta bağımlı olmadan kesme oluşacaktır sanırım. Daha fazla detay bilmiyorum.
Ete

Hattuşa

hocam ya size özel mesaj yazayım dedim beceremedim.
bu konu ile ilgili son bir soru daha sormak istiyordum ama çok olmaktan çekiniyorum.
sorum şuydu. oluşturduğumuz frekans 500 hertz ile 5 khz değerinde buraya kadar sorun yok. sorunum şu oluşan frekans %50-%50  duty değerinde ve en azından duty değeri ile 10 basamak oynama şansımız varmı? varsa öneriniz nedir?

Powered by EzPortal