Etepic

Diğer diller ve Derleyiciler => Assembly (ASM) => Konuyu başlatan: black - 26 Eylül 2014, 16:36:05

Başlık: timer1 kesmesi
Gönderen: black - 26 Eylül 2014, 16:36:05
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

Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 26 Eylül 2014, 18:36:22
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
Başlık: Ynt: timer1 kesmesi
Gönderen: black - 28 Eylül 2014, 10:00:34
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.

Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 28 Eylül 2014, 15:43:46
İ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
Başlık: Ynt: timer1 kesmesi
Gönderen: black - 29 Eylül 2014, 08:47:57
konu net bir şekilde anlaşıldı.

teşekkürler ete hocam.
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 23 Ocak 2015, 21:23:57
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.
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 24 Ocak 2015, 07:33:25
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
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 24 Ocak 2015, 13:52:41
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
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 24 Ocak 2015, 14:53:15
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


Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 24 Ocak 2015, 15:56:18
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 (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
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 24 Ocak 2015, 23:49:46
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.
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 07:51:56
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
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 25 Ocak 2015, 10:20:14
@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
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 11:27:23
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
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 25 Ocak 2015, 12:37:49
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?
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 15:01:57
Kesme ile kare dalga oluşturmada basit olan %50 duty ile çalışmaktır. Zira her kesmede konum değiştirince çıkan sinyal %50 duty değerine sahip olur. Duty ile oynamak istersen high süresinde başka tmr1 süresi low da başka tmr1 süresi uygulaman gerekir. Bu ise biraz kafa çalıştırma ve uygun algoritma geliştirmeyi gerektirir. Şu anda şöyle yapabiliriz diyebileceğim bir yöntem aklıma gelmedi daha doğrusu basit bir şey allıma geldi ama uygulanabilirliği şüphe götürür. İstersen biraz da sen kafa yor ve nasıl aypılabileceği konusunda öneride bulun bakalım ne düşüneceksin.
Toplam peryot sabit kalacak ama arada hig ve low süreleri bir birlerine borç verecek mesele burada. Bir ip ucu vereyim. Adc ölçümü hep low süresini hesaplasın. Hig süresine sıra gelince, senin 10 kademenden birisi kadar low süresine ekleme yapılsın ama toplam 5khz lik süreyide aşmamış olalım.

Ete
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 25 Ocak 2015, 15:49:11
ete hocam
sizin verdiğiniz bu kodda, frekansımız 500hz ile 5khz arasındaydı ya bu aralığı 2 katına alıp "ONdeger" değerimizi duty-cycle olarak kullanamayız mı? yani misal (olabildiği kadar zira timer helper programına hesaplatmadım) 250 hertz ile 10 khz arasına alıp, "Ondeger" değişkenimizi 10 kademeye alıp duty değişkeni olarak kullanabilirmiyiz. tabi bu seferde peryodu belirleyecek değişkeni nasıl ekleyeceğiz ona bir türlü akıl erdiremedim. yada tmr1 kesmesi içerisine pini high-low yapacak bir değişkeni nasıl ekleyebiliriz. atıyorum "ONdeger" değişkenimiz 500 hertzde 45543 değerini alıyor ya Ondeger değişkenimizin 2271. değerinde koda müdahale edip pini terslediğimizde %50-%50 olmaz mı?
....
hocam kafam durdu ben bir sigarayada daha asılayım. ;D

Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 16:21:22
Adc den peryot okumak ve buna uygun olarak duty değerinide yüzde cinsinden kullanarak arada low ve high süresi için timer değerlerini hesaplamak gerekir.Ama nasıl.? Epeyce kafa yormak gerekiyor.

Ete
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 17:19:12
Aklıma gelen sistem şöyle,
ADC den okunan değer 500us-5000us aralığında çıkıştan alınacak frekansın peryodu olsun ama us cinsinden hesaplansın.
Duty adından bir değişken tanımlansın ve buda olması gereken duty değerini belirlesin. Gerisini aşağıdaki örnekli uyglamadan takip etmek daha kolay olacak sanırım.
Diyelimki 1KHz (1000 Hz) lik bir sinyal çıkartacağız. Bunun Duty değeri %60 olsun. Yani %40 LOW, %60 High olacak şekilde çıkacak sinyalimiz.
1Khz lik sinyalin peryodu, us cinsinden şöyle bulunur: T=1000/1=1000us dir. Bunun %60 ı ise 1000*60/100=600 us olacaktır.
Low süresi ise 1000-600=400us olacaktır.  Şimdi bunlara uygun TMR1 değerlerini hesaplayalım.
20 Mhz de bir komut çevrimi 0,2us dir (20/4=5 ve 1/5=0,2us) 600us için TMR1 sayacının 600/0,2=3000 sayması gerekecektir.
Buna 7 komut gecikmesi eklemek doğru olacaktır. Bu sayacın TMR1 sayacında belirli bir sayıdan başlayıp tam 65535 i saydıktan sonra kesme oluşturabilmesi için 65536-3000+7=62543 sayısını TMR1 e ön yükleme değeri olarak vermek ve tam 65536 da kesme oluşmasını sağlamak gerekir.
LOW için de benzer bir hesap yaparsak,
400/0,2=2000, buna 7 ekliyoruz ve 65536 dan çıkartıyoruz. Böylece LOW için TMR1 ön yükleme değeri=65536-2007=63529 olarak bulunur.
Bu durumda ilk TMR1 kesmesi çıkış LOW iken 63529 ön yükleme değeri ile çalışmaya başlayacak.
Kesme oluşunca Çıkış Toggle ile konum değiştirecek ve TMR1 ön yükleme değeri olarak 62543 verilecektir.
Toparlarsak,
1. ADC den frekansın süresi peryot olarak us cinsinden hesaplanacak.
2. Duty değeri % olarak belirlenecek.
3. Hesaplanan peryot dan HIGH süresi hesaplanacak.
4. Hesaplanan peryottan HIGH çıkartılarak LOW süresi hesaplanacak.
5. HIGH-Önyükleme=HIGH_Süresi/0,2 (veya HighSüresi*10/2)+7+1 ) hesaplanarak hesaplanan değer 65535 den çıkartılacak. Bu süre HIGH ön yükleme süresi olarak verilecek.
6. LOW Önyükleme Süresi Low_Süresi/0,2  (veya LowSüresi*10/2)+7+1) hesaplanarak 65535 den çıkartılacak.
Hepsi bu kadar.
Umarım becerirsin.

Ete
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 25 Ocak 2015, 19:18:28
slm ete hocam;
son mesajınızda ki maddeleri tek tek uyguladım ama 6. maddenin altında ki kısmı yapamadım.
o kısımsa "Umarım becerirsin" yani beceremedim.
şimdi hocam ekran alıntısında görüldüğü üzere;
2 kanal adc yi aktif edip 1. kanalı başlangıçta yaptığımız şekliyle frekansımızı değişken hale getirdik.
ekranın 2. satırındaki ADC1 değeri frekansımızı oluşturan ADC değerimiz, altında ki FR DEG: ise frekansımızı belirleyen ve hesaplamalar sonucu kesme süremizi belirleyen değer.yani TMRL ve TMRH değerimiz.
devamındaki ADC2 ise duty değerimizi belirleyeceğimiz adc değerimiz, YUZDE olarak görünen ise hesaplanacak duty değerinin yüzdesi yani
yuzde =adc2 /11 (ben kabaca hesaplattım yani %98 lerde kalabilir)
ekranda DUTY olarak gözüken kısım ise FR DEG, yani ondeger olarak kabul ettiğimiz değerin duty süresi
duty =(ondeger /100) *yuzde

hemen altındaki cycle ise duty değerinden sonraki low süresi
cycle =ondeger -duty

ekranda herşey güzel, sorun TMR1 kesme içerisinde verilecek komutları beceremedim.

Z0_KeSMe:
        Context Save
        If INTCON.2 =1 Then
        KeS =1
       INTCON.2 =0
       EndIf
    [b]   If PIR1.0 =1 Then
       PIR1.0 =0
      If OnDeGeR =DuTy Then Toggle P1 :OnDeGeR =CyClE
      TMR1L =OnDeGeR.Byte0
      TMR1H =OnDeGeR.Byte1
      EndIf [/b]
        Context Restore


hocam sizi sıktım farkındayım ama şunu yapmaya çalıştım (en azından sizin anlatımınızdan anladığım kadarıyla,
ondeger değişkeni duty değişkenine eşitlenince P1 çıkışının konunumu değiştirdim ve aynı zamanda ondeger değişkenine söylediğiniz gibi cycle değişkenine yükledim. ki P1 in konumunu tekrar değiştirebilelim. ama o kısmı beceremedim.
Başlık: Ynt: timer1 kesmesi
Gönderen: ete - 25 Ocak 2015, 20:03:04
Öncelikle ADC-0 kanalından Peryodu hesaplayalım. Frekans 500 Hz ile 5000 hz arasında idi. Min frekans Peryodu 1000/500=2ms yada 2000 us olacaktır. Maksimum Frekans Peryodu, 1000/5000=0,2ms yada 200us olacaktır.
O halde 2000-200=1800 us lik bir değişim söz konusu olacaktır. (1800/1024)*256=450 sabit çarpan olarak bulunur. Formül,
Peryot=(Ham+1)*/450+200 şeklinde bulunur. Bu formülü bu şekilde kullanırsak ADC maksimumda iken min. frekans min. da iken ise maksimum frekansı hesaplamış oluruz. Halbuki tersi olsa daha güzel olurdu. O halde;
Peryot=(1024-Ham)*/450+200 şeklinde uygularsak maksimum ADC de min peryot yani maksimum frekans hesaplamış olacağız.

Bu formül ile frekansa karşılık gelen peryodu bulduktan sonra şimdi DUTY hesabını da ADC-1 kanalından yapalım.
Maksimum değer 100 olacağına göre (100/1024)*256=25 bizim sabit çarpanımız olur. Formül ise;
Duty=(Ham+1)*/25 şeklinde hesaplanır.
Şimdi TMR1 değerlerini hesaplayalım.
Temp=Peryot*duty/100
HighYukleme=temp*10/2
HighYukleme=65535-HighYukleme+8  'buradaki 8 rakamı 7+1 dan geliyor. 1 rakamı 65536 yerine 65535 yazmak zorunluluğundan , 7 ise komut gecikmelerinden kaynaklanıyor.

Şimdide Low Yükleme Değerini hesaplayalım.
Temp=Peryot-HighYukleme
LowYukleme=Temp*10/2
LowYukleme=65535-LowYukleme+8
Bütün bu hesaplamalar programın ADC okuma kısmında yapılacaktır.
Kesme kısmında
..
..
If PIR1.0=1 then
PIR1.0=0
Toggle CIKIS
If CIKIS=1 THEN
  TMR1L=HighYukleme.Byte0
  TMR1H=HighYukleme.Byte1
Else
  TMR1L=LowYukleme.Byte0
  TMR1H=LowYukleme.Byte1
Endif
Endif
Context Restore

Hepsi bu kadar bu seferde yapamazsan bu işi yapmaktan vaz geç derim çünki artık ne yapman gerekenlerin kendisini yapıp verdim. Bu tür hesapları kendin yaparsan daha iyi öğrenirsin diye düşünüp detaya girmemiş ancak yolunuda göstermiş idim.
Çok zor olmasa gerek. Yalnızca mantık çalıştırıp neyin nerede nasıl yapılacağına anlattıklarıma bakarak karar verecektin ama sanırım temel epeyce zayıf. Her neyse bu sefer başar artık. Bak umarım başarırsın demiyorum başar artık diyorum. Zira her şey elinin altında artık.

Ete
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 25 Ocak 2015, 20:40:20
Alıntı YapPeryot=(Ham+1)*/450+200 şeklinde bulunur. Bu formülü bu şekilde kullanırsak ADC maksimumda iken min. frekans min. da iken ise maksimum frekansı hesaplamış oluruz. Halbuki tersi olsa daha güzel olurdu.

hocam tam tersi derken hesaplama daha rahat olacaksa yüksekten küçüge hesaplatalım, onuda öğrenmiş oluruz.
bu arada duty değeri de dediğiniz şekliyle oluyor, ancak sanki bir yerde hata var gibi, belki isisin azizliği olabilir. hata derken verdiğiniz şekilde kesme içinde dediklerinizi aynen yazdığımda duty değerini düşüremiyorum. iflerin içindeki

  If PIR1.0 =1 Then
       PIR1.0 =0
       Toggle P1
       If P1 =1 Then
   TMR1L=loWyUkLeMe.Byte0
  TMR1H=loWyUkLeMe.Byte1     
 
Else
  TMR1L=hIgHyUkLeMe.Byte0
  TMR1H=hIgHyUkLeMe.Byte1
EndIf
EndIf


şeklinde değiştirince duty değeri düşüyor, yükseliyor ancak frekans düşmüyor. verdiğiniz şekilde de frekans sağlıklı çalışıyor ancak duty tam sağlıklı çalışmıyor.

ama şu var hocam inanın benim için çok zor olan birşeyi siz çok güzel ve basit bir şekilde yaptınız. tşk ederim.

NOT: hocam mantığını anladım artık, tşk ederim. gerisi ile ben uğraşırım eğer aşamazsam size dönerim
Başlık: Ynt: timer1 kesmesi
Gönderen: Hattuşa - 27 Ocak 2015, 23:35:58
slm ete hocam;
hocam kendimin bir eksiğini farkettim. farkedemediğim okuduklarımı anlayamayışımmış, 2 gündür yazdıklarınızı okuyup durdum. ama sonunda başardım. vermiş olduğunuz kodu kendi devreme adapte edip kodları bir kenara attım. ben buton kontrollü duty-cycle değerini 10 kademeye aldım ki böyle olmasını istiyordum. çokta güzel oldu hocam ya. inanın önceki halinden (analog yaptığım şeklinden) çok çok güzel oldu bunun için size bu tşk yazısını yazma mecburiyetinde hissettim kendimi. hocam "TEŞEKKÜR EDERİM"

bu arada hocam, sorularım bitmedi bilesiniz. şu işlemci ile yaptığımız 4 işlem üzerine bir dizi soru yağmuruna tutmayı planlıyorum. şimdilik özel hayatımda biraz yoğunluk var gene rahatsız edeceğim sizi...