tmr0 ve tmr1 aynı anda nasıl kullanılır

Başlatan mikro29, 15 Şubat 2014, 20:39:36

mikro29

Merhaba,
Protonda Timer0 ile zamanlayıcı ve timer1 ile sayma yaptırmak istiyorum.Yardımcı olabilirmisiniz. Hocam sorun şu Timer1 65535 olduğunda Timer0 hızlanıyor.Timer0 Timer1 den bağımsız nasıl kullanabiliriz? Kod verebilirseniz sevinirim.



                                                                   
Device = 16F88   ' Selected PICMicro
Xtal = 4   ' Oscillator frequency  4 MHz
                                                                   
'-------------------------- Configuration --------------------
                                                                   
Config  CP_OFF, DEBUG_OFF, WRT_PROTECT_ALL, CPD_OFF, LVP_OFF, BODEN_OFF, MCLR_ON, PWRTE_ON, WDT_OFF,INTRC_CLKOUT ' XT_OSC
                                                                   
'-------------------------- LCD connection settings ------------------------
                                                                   
Declare  LCD_Type ALPHA   ' Alphanumeric LCD type
Declare  LCD_DTPin  PORTB.0   ' LCD data port
Declare  LCD_ENPin  PORTB.5   ' E line
Declare  LCD_RSPin  PORTB.4   ' RS line
Declare  LCD_Interface  4   ' 4-line or 8-line interface
Declare  LCD_CommandUs  2000   ' Time to wait (in uS) between commands sent to the LCD
Declare  LCD_DataUs  20   ' Time to wait (in microseconds) between data sent to the LCD
Declare  LCD_Lines   4   ' How many lines the LCD has
                                                                   
'-------------------------- Ports settings ---------------------------------
                                                                   
PortB_Pullups = On   
Declare  All_Digital = On
'bit 6-4 IRCF<2:0>: Internal RC Oscillator Frequency Select bits
'000 = 31.25 kHz
'001 = 125 kHz
'010 = 250 kHz
'011 = 500 kHz
'100 = 1 MHz
'101 = 2 MHz
'110 = 4 MHz
'111 = 8 MHz                                                                   
'         76543210
OSCCON = %01101100
TRISA  = %00000001
TRISB  = %01000000
PORTA  = %00000000
PORTB  = %00000000
CMCON  = 7

'-------------------------- TMR0 adjustment --------------------
On Interrupt GoTo KESME
OPTION_REG=%10000101
INTCON    =%11100000

PIE1 =  %00000000
                       
                                             
'-------------------------- TMR1 adjustment --------------------
TMR1L = $00   ' TMR1L register value
TMR1H = $00    ' TMR1H register value
T1CON = %00000111
Dim ILK As Word
Dim MESAFE As Float
Dim TEMP As Float
Dim X As Float
Dim Y As Float
Dim HRK As Bit ' HAREKET

Dim SALISE As Byte
Dim SANIYE As Byte
Dim DAKIKA As Byte
Dim SALISE1 As Byte
Dim SANIYE1 As Byte
Dim DAKIKA1 As Byte
Dim SAYAC As Byte
Dim SAYAC2 As Word
Dim i As Word
SAYAC2.Byte1=TMR1H
SAYAC2.Byte0 =TMR1L
TMR1H=0
TMR1L=0 

SALISE = 0
SANIYE = 0
DAKIKA = 0
SALISE1 = 0
SANIYE1 = 0
DAKIKA1 = 0

SAYAC = 0
Print $FE,1
TMR0 = 100

BASLA:
SAYAC2.HighByte=TMR1H
SAYAC2.LowByte=TMR1L

     Print $FE,$90,Dec2 DAKIKA,":",Dec2 SANIYE,":",Dec2 SALISE
    Print $FE,$D0,#SAYAC2

GoTo BASLA
End
'------------------------KESME FONKSIYONU[BAŞLA]--------------------------------
Disable
KESME:

SAYAC=SAYAC+1
If SAYAC=1 Then
SAYAC=0
SALISE=salise+1
If SALISE=100 Then
SALISE=0
SANIYE=saniye+1
If SANIYE=60 Then
SANIYE=0
DAKIKA = DAKIKA + 1
If DAKIKA = 60 Then
DAKIKA = 0
EndIf
EndIf
EndIf
EndIf
TMR0 = 100
INTCON.2=0
Resume
Enable


ete

TMR0 ile TMR1 bağımsız çalışan sayaçlardır. Bir birlerinden etkilenmezler tabiiki etkiletmek sizin elinizde.
Tek ortak yanları vardır dahili CLK dan puls alınca her ikiside aynı CLK dan tetik almış olur.
Üstelik sizin alternatifinizde TMR1 harici kaynaktan tetiklenince ortak hiç bir bağlantıları da kalmamış olur.

Gelelim sizin meseleye. Daha öncede söyledim ya ne istediğinizi anlatamıyor yada anlattığınızı yapamıyorsunuz.
Bakın kusurlarınız neler;
On Interrupt GoTo KESME
OPTION_REG=%10000101
INTCON    =%11100000
şeklinde komut vermişsiziniz. INTCON.6 peripheral kesmeleri için aktive edilir. Bu konuda bir kesme aktif etmemişsiniz Yani TMR1 kesmesini kullanmamışsınız neden bunu açtınız?

Burada TMR0 kesmesi aktif gözüküyor TMR0=100 değeri vererek onun her 10 ms de bir kesme yaratmasını sağlamışsınız. Bu da tamam. Ama TMR1 (harici puls sayma işi) nasıl yönetiliyor çok açık değil.
Bir kesmeye bağlanmamış. Yalnızca program içinde  BASLA-GOTO BASLA arasında sürekli olarak TMR1 değerini alıp SAYAC2 registerine veriyorsunuz.  Bunu vermekle doğru bir yapmış olmuyorsunuz. Çünki program BASLA-GOTO BASLA arasında bir kesme aralığında (10 ms de) belkide 100 den fazla  BASLA-GOTO BASLA işlemi yapar. Buda 100 den fazla kere TMR1 değerini SAYAC2 registerine aktarmak demektir. Amaç nedir burada? belli değil. SAYAC2 registerinin göstermiş olduğu değer doğru bir değer olmayacaktır.
Nedir doğru değer derseniz, şayet TMR1 değerini belirli bir zaman dilimi içinde saymayı hedefliyorsanız;
Mesela 1000 ms de gelen puls adedi gibi yapmanız gereken şey, SAYAC2.byte0=TMR1L, SAYAC2.Byte1=TMR1H ile sayac değerini alıp TOPLAM=TOPLAM+SAYAC2 şeklinde 10 kesme için toplamak olmalıdır.
10 kesme oluştuğunda gelen toplam puls adedi TOPLAM isimli değişkende toplanmış olacaktır.
Bu şekilde doğru sayım yapmış olursunuz. Aksi taktirde SAYAC2 içinde rastgele bir değer görmüş olursunuz ki buda sizi önceden yaptığı gibi yanıltır.

Tabiiki 1000 ms içinde TMR1 toplam sayma değerinin 65535 değerini aşmamasına özen göstermeniz gerekir. Şayet aşma gibi bir durum var ise o zaman TMR1 bölme oranını 1/2 almanız gerekir.
Yada daha küçük bir zaman diliminde mesela 500 ms de bu ölçümü yapar sonra orantılarsınız.

Kesme içinde
SAYAC=SAYAC+1
If SAYAC=1 Then
SAYAC=0
şeklinde koda var. Hiç bir yerde kullanılmıyor bu işlem o halde ne arıyor orada. Ne amacı var. Her kesme sonucunda,
Toggle SAYAC desiniz bu kadar satırada gerek kalmaz. Bir kesmede sayac=1 olur diğerinde sayac=0 olur.
Zaten kullanılmayan bir şeyin orada boşuna komut gecikmesi yaratması da anlamsız.
Yukarıda anlattığım alternatife uygun program şekli şöyle olmalıdır;
Config  CP_OFF, DEBUG_OFF, WRT_PROTECT_ALL, CPD_OFF, LVP_OFF, BODEN_OFF, MCLR_ON, PWRTE_ON, WDT_OFF,INTRC_CLKOUT ' XT_OSC
                                                                   
'-------------------------- LCD connection settings ------------------------
                                                                   
Declare  LCD_Type ALPHA   ' Alphanumeric LCD type
Declare  LCD_DTPin  PORTB.0   ' LCD data port
Declare  LCD_ENPin  PORTB.5   ' E line
Declare  LCD_RSPin  PORTB.4   ' RS line
Declare  LCD_Interface  4   ' 4-line or 8-line interface
Declare  LCD_CommandUs  2000   ' Time to wait (in uS) between commands sent to the LCD
Declare  LCD_DataUs  20   ' Time to wait (in microseconds) between data sent to the LCD
Declare  LCD_Lines   4   ' How many lines the LCD has
                                                                   
'-------------------------- Ports settings ---------------------------------
                                                                   
PortB_Pullups = On   
Declare  All_Digital = On
'bit 6-4 IRCF<2:0>: Internal RC Oscillator Frequency Select bits
'000 = 31.25 kHz
'001 = 125 kHz
'010 = 250 kHz
'011 = 500 kHz
'100 = 1 MHz
'101 = 2 MHz
'110 = 4 MHz
'111 = 8 MHz                                                                   
'         76543210
OSCCON = %01101100
TRISA  = %00000001
TRISB  = %01000000
PORTA  = %00000000
PORTB  = %00000000
CMCON  = 7
'-------------------------- TMR0 adjustment --------------------
On Interrupt GoTo KESME
OPTION_REG=%10000101
INTCON    =%10100000                                             
'-------------------------- TMR1 adjustment --------------------
TMR1L = $00   ' TMR1L register value
TMR1H = $00    ' TMR1H register value
T1CON = %00000111

Dim ILK As Word
Dim MESAFE As Float
Dim TEMP As Float
Dim X As Float
Dim Y As Float
Dim HRK As Bit ' HAREKET

Dim SALISE As Byte
Dim SANIYE As Byte
Dim DAKIKA As Byte
Dim SALISE1 As Byte
Dim SANIYE1 As Byte
Dim DAKIKA1 As Byte
Dim SAYAC As Byte
Dim SAYAC2 As Word
Dim TOPLAM As WORD
Dim SURE   As WORD
Dim i As Word
SAYAC2.Byte1=TMR1H
SAYAC2.Byte0 =TMR1L
TMR1H=0
TMR1L=0 

SALISE = 0
SANIYE = 0
DAKIKA = 0
SALISE1 = 0
SANIYE1 = 0
DAKIKA1 = 0

SAYAC = 0
Print $FE,1
TMR0 = 100
SURE=0
TOPLAM=0
DelayMS 200

BASLA:
    Print $FE,$90,Dec2 DAKIKA,":",Dec2 SANIYE,":",Dec2 SALISE
    Print $FE,$D0,#SURE

GoTo BASLA
End
'------------------------KESME FONKSIYONU[BAŞLA]--------------------------------
Disable
KESME:
SAYAC2.byte0=TMR1L
SAYAC2.BYTE1=TMR1H
TMR1L=0:TMR1H=0
TOPLAM=TOPLAM+SAYAC2
SALISE=SALISE+1
If SALISE=100 Then
  SALISE=0:SURE=TOPLAM:TOPLAM=0
  SANIYE=saniye+1
  If SANIYE=60 Then
    SANIYE=0
    DAKIKA = DAKIKA + 1
    If DAKIKA = 60 Then DAKIKA = 0
  EndIf
EndIf

TMR0 = 100
INTCON.2=0
Resume
Enable


ete


gogoce

Hocam farklı konu açmak istemedim daha önce portb.0 , portb change ve usart kesmelerini sayenizde öğrenip kullandım. Şimdi bir projemde 2 farklı sensörden 1 saniye boyunca sinyal gelmemesi durumunda hata verdirmek istiyorum. bunu da tmr0 ve tmr1 timerleri ile yapmak istiyorum. TMR sayaçlarını harici kaynak olarak ilgili pinlere aktarmaız durumunda nasıl bir yol izlenecek.? Timer sayacını her sensör pulse sinde 1 arttıracak mı?
Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

ete

Mesajın çok açık değil. Ne sorduğuna ancak mesajın sonundaki cümleye bakarak karar verebildim ve cevabımda şöyle,Elbette Timer1 veya TMR0 sayaclarının saydırma kaynağı olarak harici pinlere aktarılması durumunda hariçten gelen her puls sayacları bir artıracaktır.

Ete

gogoce

Alıntı yapılan: ete - 25 Aralık 2019, 14:02:31Mesajın çok açık değil. Ne sorduğuna ancak mesajın sonundaki cümleye bakarak karar verebildim ve cevabımda şöyle,Elbette Timer1 veya TMR0 sayaclarının saydırma kaynağı olarak harici pinlere aktarılması durumunda hariçten gelen her puls sayacları bir artıracaktır.

Ete

Teşekkürler hocam . Demek istediğim 2 ayrı sensörden 1 saniye boyunca bilgi gelmez ise hata verdirmek istiyorum. TMR0 ve TMR1 ile nasıl yaparım yada yapabilirmiyim arayışlarına girdim. Derdimi tam anlatamamışım sanırım. TMR0 ve TMR1 i kullanmak isteme sebebim, hangi sensör den 1 saniye süreyle sinyal gelmez ise o sensörün kodunu hata olarak verdirmek istiyorum. Yada farklı bir yöntem olarak ne kullanabilirim?
İşlemci de farklı görevler de olacak kesmeleri kullanarak bunu yapmam mümkün mü? yol gösterirseniz sevinirim
Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

ete

Bir öneride bulunmadan önce sensörden bilgi geldiğini nasıl anlıyoruz yafa gelmediğini nasıl anlıyoruz bilmem gerekiyor.
Ete

gogoce

Alıntı yapılan: ete - 26 Aralık 2019, 20:39:33Bir öneride bulunmadan önce sensörden bilgi geldiğini nasıl anlıyoruz yafa gelmediğini nasıl anlıyoruz bilmem gerekiyor.
Ete

bilgi 1 ve 0 şeklinde hocam şöyle düşünebilirsiniz bant üzerinden ürün geçiyor. sensör ürünü görünce 1 veriyor ürün olmayınca 0 gibi...
Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

ete

Senden cevap gelene kadar ben yinede birşeyler karalayayım istedim.
Bu gibi durumlarda ben genelde TMR1 sayacını kullanırım. Şayet 4 Mhz OSC ile çalışıyor isek her bir dilimi 500ms olan döngüler kurarım ve döngüleri de sayan bir değişken kullanarak istediğimm süreyi oluştururum. Bu süre içinde sensörden bir bilgi gelirse döngüden çıkar ne yapacaksam onu yapar yeniden sensör bakmaya dönerim.
Bir örnekle açıklayayım.
4Mhz OSC frekansında 500 ms lik bir gecikme yaratmanın yolu şöyle;
TMR1 sayacına 3036 değerini önyükleme değeri olarak veririm. Bununda yolu TMR1H=$0B ve TMR1L=$DC değerlerini vermek. Ardından Bölme oranı 1/8 olacak ve bunuda T1CON=%00110001 şeklinde ayarlıyoruz. İllaki Global kesmeleri aktif etmek gerekmiyor. Ama sayac 65535+1 değerine ulaştığı anda PR1.0 biti set edilir. Bu TMR1 sayacı kesme bayrağıdır. Kesmeler açık olsada olmasada bu bit taşma olduğunda set edilir.
Şimdi geçmesini istediğimiz süre 1 sn yani 1000 ms olacak. O halde bize iki kesme zamanı gerekiyor demektir. Bu iş için bir bit değişkeni kullanabiliriz. KES olsun adı.
Şimdi bu saydıklarımızı kod şekline çevirelim. Bu arada sensör adedimiz iki tane olduğu için bir byte değişkeni ve onun ilk 2 bitini Bilgi gelip gelmediğini anlamak için kullanacağız.
Değişken adı BILGI olsun. BILGI.0=1 nolu sensörden bilgi gelirse 1 olacak gelmediği müddetçe 0 da kalacak. BILGI.1= 2 nolu sensörden bilgi gelir ise 1 olacak gelmediği müddetçe sıfır kalacak.

BASLA:
t1con=%00110001:kes=0:BILGI=%00000000
BASLA_BIR:
TMR1H=$0B ve TMR1L=$DC:PIR1.0
WHILE PIR1.0=0
  IF SENSOR_1=1 THEN BILGI.0=1 '1 nolu sensörden bilgi gelmiş ise
  IF SENSOR_2=1 THEN BILGI.1=1 '2 nolu sensörden bilgi gelmiş ise
  IF SENSOR=3 THEN BITIR  'iki sensörden de bilgi gelmiş ise Çıkışa git
WEND
KES=1-KES 'KES yeniden 0 olunca 1 sn geçmiş olacak
IF KES=1 then BASLA_BIR
İşte tam bu satırda 1 sn geçmiş olacak ve 2 sensörede bilgi gelmemiş olacak aynı zamanda. Çünki gelse idi program BITIR isimli etikete gidecek idi.
Burada bilgi gelmemiş ise ne yapılacak ise onu yapacaksın.
Ardından Goto Basla diyeceksin herhalde.
Buraya da BITIR etiketi gelecek ve altında 2 sensörden de bilgi gelmiş ise ne yapılacak ise onu yapacaksın.
Mesajı yazarken cevabın gelmiş ama beklediğim şekilde geldiği için mesajı değiştirmiyorum.

Ete

gogoce

Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

Powered by EzPortal