18F serisinde Timer neden çalışmaz?

Başlatan DigMan, 15 Eylül 2015, 23:30:03

DigMan

Ete hocam ve herkese selam,
Kısa bir timer programı yazdım fakat timer bir türlü düzgün çalışmadı.28 e kadar geliyor ve orada kalıyor, kilitleniyor.Geriye doğru saydırayım dedim bu sefer de 32 de kalıyor. Yani 60 a tamamlanıyor gibi bir durum var.Timer0 ve Timer2 için de sonuç aynı.Hem 18F252 hemde 18F2620 işlemcileri ile denedim yine aynı.En son seriyi değiştirip 16F876A ile denedim bunda sadece timer register ayarlarını değiştirerek sorunsuz çalıştırdım. problem nedir, eksik bir şeymi yapıyorum bir türlü çözemedim.Programın tamamını veriyorum yardımcı olursanız sevinirim ne yaptıysam olmadı, kafayı yicem.


Device = 18F252
XTAL = 20
ALL_DIGITAL = True

' ******************* DEĞİŞKENLER

Dim BirSaniye   As Bit

Dim SAYI        As Byte
Dim SAYI_1      As Byte
Dim X           As Byte
Dim Kesme_Say   As Byte
Dim Saniye_Say  As Byte
Dim Dakika_Say  As Byte
Dim Saat_Say    As Byte
Dim ARADEGER    As Word
Dim ADDRESS     As Word
Dim DATAREG     As Word
Dim SAY1        As Word
Dim SAY2        As Word
Dim DERECE      As Word
Dim ONDALIK     As Word
Dim HAMDEGER    As Word
Dim Menu_Limit  As Word

' ******************* GİRİŞLER

Symbol SCL      = PORTC.2   
Symbol SDA      = PORTC.3   
'Symbol SHT_DTA  = PORTC.0 
Symbol DQ       = PORTC.0   
Symbol SHT_CLK  = PORTC.1 

Symbol SW2      = PORTA.0   
Symbol SW1      = PORTA.1   
Symbol BUTON    = PORTC.4   

' ******************* ÇIKIŞLAR

Symbol SES      = PORTA.4   
Symbol ALARM    = PORTB.0   
Symbol EXT_SH   = PORTA.2   
Symbol EXT_LT   = PORTA.3   
Symbol EXT_DT   = PORTA.5   
Symbol L1       = PORTC.5   
Symbol L2       = PORTC.6   
Symbol L3       = PORTC.7   
Symbol L4       = PORTB.1   
Symbol C1       = PORTB.2   
Symbol C2       = PORTB.3   
Symbol MAX_LD   = PORTB.4   
Symbol C4       = PORTB.5   
Symbol MAX_CK   = PORTB.6   
Symbol MAX_DT   = PORTB.7   

TRISA = %00000011
TRISB = %00000000
TRISC = %00011111

Input BUTON
Low BUTON
High SW1
High SW2
High SES
Low ALARM
Low L1
Low L2
Low L3
Low L4
Low C1
Low C2
Low C4
Low MAX_LD
Low MAX_CK
Low MAX_DT

DQ     = 0
X      = 0
SAYI   = 0
SAYI_1 = 0
SAY1   = 0
SAY2   = 0

Saniye_Say = 0
Dakika_Say = 0
Saat_Say   = 0

Cls
Clear

BASLA:
DelayMS 1000
Low SES : DelayMS 50 : High SES
       
       BirSaniye = 0
       Kesme_Say = 0             
       'INTCON = %10100000 'TMR0 için
       'T0CON  = %11000111 'TMR0 için
       T2CON = %01111111
       PIR1.1 = 0
       PIE1.1 = 1
       IPR1.1 = 1
       INTCON.6 = 1
       INTCON.7 = 1
             
       On Interrupt GoTo KESME_OLDU
             
'--------------------------------------------------------------------------------------------------------       
'address = 00....08 - digitler 
ADDRESS = $09 : DATAREG = $00 : GoSub MAXYAZ   
ADDRESS = $0A : DATAREG = $09 : GoSub MAXYAZ   
ADDRESS = $0B : DATAREG = $03 : GoSub MAXYAZ   
ADDRESS = $0C : DATAREG = $01 : GoSub MAXYAZ   
ADDRESS = $0F : DATAREG = $00 : GoSub MAXYAZ   
'--------------------------------------------------------------------------------------------------------         
       
START:
             
If BirSaniye = 1 Then
           
    ADDRESS = 1 : X = Dig Dakika_Say, 1 : GoSub AL : GoSub MAXYAZ
    ADDRESS = 2 : X = Dig Dakika_Say, 0 : GoSub AL : GoSub MAXYAZ
    ADDRESS = 3 : X = Dig Saniye_Say, 1 : GoSub AL : GoSub MAXYAZ
    ADDRESS = 4 : X = Dig Saniye_Say, 0 : GoSub AL : GoSub MAXYAZ
    Toggle L1

EndIf

BirSaniye = 0
GoTo START

''***************************************************************************************

Disable
KESME_OLDU:
         
         PIR1.1 = 0
         'INTCON.2 = 0 'tmr0 kesme bayrağı
         Kesme_Say = Kesme_Say + 1                         
         If Kesme_Say > 30 Then     
            Kesme_Say = 0       

             Saniye_Say = Saniye_Say + 1
             If Saniye_Say = 60 Then
                Saniye_Say = 0
                Dakika_Say = Dakika_Say + 1
                If Dakika_Say = 60 Then
                   Dakika_Say = 0
                   Saat_Say = Saat_Say + 1
                      If Saat_Say = 10 Then
                         Saat_Say = 0
                      EndIf
                 EndIf
              EndIf
         
         BirSaniye = 1
         GoTo START     
         EndIf 
         Resume
         Enable
         
''************************************************************************************************
AL:
DATAREG = LookUpL X,[126,48,109,121,51,91,95,112,127,123,99,78,128]
If ADDRESS = 2 Then DATAREG = DATAREG + 128 
Return

MAXYAZ:
SHOut MAX_DT,MAX_CK,msbfirst,[ADDRESS,DATAREG]
PulsOut MAX_LD,2       
Return
''************************************************************************************************

ete

#1
Bir sürü şey saymışsın ama en olmayacak timer (timer2) ile örneğini vermişsin.
Yapmayı planladığınişte tmr0 ve timer1 kullanabilirsin ama tmr2 yi aynı mantık ile kullanamazsın.
Zira timer2 kesmeyi ancak tmr2 değeri ile pr2 değeri bir birine eşit olunca oluşturur. Sen pr2 ye hiç değer vermediğine göre default değeri neyse o kullanılıyor olsa gerek. Tmr2 kesmesi pek kullanmadığım için fazla detay veremiyorum.

Bence yinede sen tmr0 yada tmr1 kesmesi kullanmalısın. Timer lar bu gibi işlerde bir önyükleme değeri ile çalışmalıdır. Rastgele bir zaman tutuyorsan ona lafım yok ama saniye palsi  (süresi) oluşturmaya çalışıyorsun. Bunun bir hesabı var nedir senin hesabın.?
Örnek vereyim,
20 Mhz de 8 bit timer ile en fazla 10 ms lik bir süre yaratabilirsin. 11-12-13 ms de olabilir ama hesaba uymazlar. 10 ms lik süreden 1000 ms (bir sn) yaratabilmen için en az 100 kesme sayman gerekirdi.
16 timer iler en fazla 100 ms lik süre yaratabiliyorsun. Böylece 10 kesme sonunda 1 sn lik süreyi yakalamış olursun.
Diyelimki tmr0 kesmesi kullanacaksın ve 100 kesme sayacaksın. İşte yapman gerekenler,
Intcon=%10100000
T0con=%11010111
On interrupt goto kesme
Tmr0.L=60:Tmr0.H=0
...
..
..
Disable
Kesme:
Kes=kes+1:
if kes=100 then
  Kes=0
  Sn=sn+1
...
Endif
Tmr0.L=60:Tmr0.h=0
Intcon.2=0
Resume
Enable
Dikkat edersen tmr0 registerine önyükleme değeri 60 verildi. Hem başlarken hemde her kesme oluştuğunda. Bu işlemcide tmr0 16 bit de kullanılabiliyor. Bu nedenle register kullanılırken yine 16 bit gibi kullanılıyor.

Tmr1 kullanımıda benzer şekildedir. Tek fark registerler farklı.
Intcon=%11000000
T1con=%10110101
Pır1.0=0
PIE1.0=1
IPR1.0=1
On onterrupt goto kesme
Tmr1L=$DC:TMR1H=$0B
..
...
Kesme:
Kes=kes+1
If kes=10 then
...
EndIF
Tmr1L=$DC:TMR1H=$0B
PIR1.0=0
Resume
Enable

Hepsi bu kadar
Ete

DigMan

hocam birazdan denicem yazdıklarınızı. Fakat gözüme birşey takıldı.
Verdiğiniz örnekte Tmr0 registerini 8 bit ayarlamış olmanıza rağmen TMRL ve TMRH değerlerini de yazmışsınız.bunu 8 bit için bile olsa yazmamı şart mı? sadece 16 bit için değil mi onlar?

Hesap olarak şunu yaptım;
TMR0'ı, 8 bit ile en yüksek bölme oranını ayarladım(256) ve 20MHz kristal ile 13ms kesme elde ettim. 0.2us x 256 x 256 = 13107us. kesme içinde bu kesmeleri 77 ye kadar saydırdım. 13 x 77 = 1001ms. Çok hassas bir zamanlayıcıya ihtiyacım yok.zaten en fazla 3 saat sonra sistem kendini sıfırlıyor ve baştan saymaya başlıyor.

ben sadece,
INTCON = %10100000
T0CON  = %11000111

bu ayarları yüklemiştim.bir başlangıç değeri vermedim. Sorun bundan mı diyorsunuz hocam?

ete

#3
8 bit olsada öyle veriliyor diye hatırlıyorum. Olmaz ise tek vermeyi denersin.
Neden çalışmadığını bilemem. Ancak verdiğin register ayarlarıda yanlış olabilir.
Ben T0CON=%11010111 vermişim sen, T0CON  = %11000111 vermişsin yada veriyorsun.
Bana kalırsa açıkladığım şekilde denemeye çalış sonuca bak çalışmıyorsa yine buraya kodları koy ki inceleyebilelim.

Ete

DigMan

#4
Hocam, sizin gönderdiklerinizi de denedim, her şeyi yaptım yok yine olmadı yine olmadı.kafayı yicem yarabbim.Hocam Allah aşkına nedir bu problem, nasıl bir şey bu? kaç günümü yedi delirticek beni.

dediğiniz gibi, tmr0 ile denedim, tmr1 ile denedim, 8 bit, 16 bit hepsini denedim, olmadı-olmadı-olmadı.başka kartta denedim ordada aynı sorunu veriyor.donanım olarak zaten sorun olmadığını biliyorum, daha önce 876A ile denemiştim çalışmıştı.

Zaten timer lar normal bir şekilde kurulup çalışıyor. 28 e gelince önce bir reset atıyor, baştan başlıyor sonraki 28 de kilitlenip kalıyor.nadiren de display 28 olarak kalıyor, led ve röle dengesizce çalışmaya devam ediyor sonra o da duruyor. bu arada ben değişkenlerin değerlerini başka bir displayle görmeye çalıştım.onlarda normal.cihaz sanki sonsuza kadar delay komutu işliyor gibi donup kalıyor.olmadı içinde başka bir yazılım olan ve çalışan farklı bir karta yükledim ordada çalışmadı.

hocam, devredeki herşeyi iptal ettim sadece led yakıp söndürdüm problem yine devam etti.lütfen bi el atın şu soruna.imkanınız varsa 18f252 ile bir timer kurup led yakıp söndürün bir kaç dakika, sonra da o programı bana verin deneyim.zaten 28. saniyede sorun başlıyor.
Hocam, lütfen bir yol gösterin..

programın en son ve sade hali...


Device = 18F252
XTAL = 20
ALL_DIGITAL = True

' ******************* DEĞİŞKENLER

Dim BirSaniye   As Bit
Dim SAYI        As Byte
Dim SAYI_1      As Byte
Dim X           As Byte
Dim Kesme_Say   As Byte
Dim Saniye_Say  As Byte
Dim Dakika_Say  As Byte
Dim Saat_Say    As Byte   

' ******************* ÇIKIŞLAR

Symbol SES    = PORTA.4     
Symbol L1       = PORTC.5   
Symbol L2       = PORTC.6   
Symbol L3       = PORTC.7   
Symbol L4       = PORTB.1           

TRISA = %00000011
TRISB = %00000000
TRISC = %00011111

Low L1
Low L2
Low L3
Low L4
Saniye_Say = 0
Dakika_Say = 0
Saat_Say   = 0
Clear

BASLA:
DelayMS 1000
Low SES : DelayMS 50 : High SES
       
       BirSaniye = 0
       Kesme_Say = 0                     
       INTCON = %11000000
       T1CON  = %10110101
       PIR1.0 = 0
       PIE1.0 = 1
       IPR1.0 = 1
       On Interrupt GoTo KESME_OLDU
       TMR1L = $DC : TMR1H = $0B
           
START:
             
If BirSaniye = 1 Then
    Toggle L1
    Toggle L4
EndIf

BirSaniye = 0
GoTo START

''***************************************************************************************

Disable
KESME_OLDU:
                 
         Kesme_Say = Kesme_Say + 1                                 
         
         If Kesme_Say > 10 Then     
            Kesme_Say = 0       

            Saniye_Say = Saniye_Say + 1
            If Saniye_Say = 60 Then
               Saniye_Say = 0
               Dakika_Say = Dakika_Say + 1
               If Dakika_Say = 60 Then
                  Dakika_Say = 0
                  Saat_Say = Saat_Say + 1
                  If Saat_Say = 10 Then
                     Saat_Say = 0
                  EndIf
               EndIf
            EndIf
                             
         BirSaniye = 1
         GoTo START     
         EndIf
         
         TMR1L = $DC : TMR1H = $0B
         PIR1.0 = 0
         Resume
         Enable






ete

Kesme satırları arasında Goto Start diye bir komut satırı var. Bu büyük bir hata. Kesme içinden programın bir başka etiketine goto yada gosub ile gidemezsin. Gidersen stack taşması yada benzer bir hata ile programın kitlenir.

O satırı oradan sil ve öyle dene bakalım.

Ete

DigMan


Hocam, evet dediğiniz o satırla beraber bir de birSaniye = 0 ifadesini if li ifadenin içine aldım sorun çözüldü. Kesmenin içindeki goto yu nasıl kullandım niye kullandım ben de bilmiyorum.sanırım 16f serisinde bu kadar çabuk hataya sebebiyet vermemesi beni yanılttı.Bu arada 8 bitlik tmr0 için başlangıç değerleri vermeye gerek olmadığını gördüm.sabahtan beri çalışıyor sorun olmadı.

Ete hocam, çok teşekkür ediyorum...

Powered by EzPortal