TMR0 kesmesinde sayımı if else ile yakalayamamak

Başlatan dyonizos, 11 Temmuz 2012, 04:38:07

dyonizos

selam arkadaslar,
aşağıdaki kodda TRM0 ile ms sayımı yaparken istediğim değerlerde ledleri yakıp söndürmek istiyorum ancak
IS-ELSE sorgusunu kesme içinde kullanmamak gerekir diye öğrenmiştim. Ancak IF-ELSE kesme dışına koyunca değerleri yakalayamıyorum sayım sırasında ve led yakıp söndürme olayı gerçekleşmiyor. Kesme içinde kullanmadan bu değerleri yakalamak mümkün değilmi?
Declare FLOAT_DISPLAY_TYPE = LARGE
		Device = 16F876
        Config HS_OSC,WDT_OFF,PWRTE_OFF,BODEN_OFF,LVP_OFF,DEBUG_OFF,CP_ALL
        XTAL = 20
		LCD_RSPIN = PORTA.0
		LCD_ENPIN = PORTA.1
		LCD_DTPIN = PORTC.4	
		LCD_INTERFACE = 4	' 4-bit Interface
		LCD_LINES = 4
		LCD_TYPE = 0
    
        ALL_DIGITAL = TRUE	' Set PORTA and PORTE to all digital


        
TRISA=%00000000
TRISB=%00000000
TRISC=%00000000
PORTA=0
PORTB=0
PORTC=0

Symbol led1     PORTC.0
Symbol led2     PORTC.2 
Dim sayac As Float
Dim int As DWord 

On_Hardware_Interrupt GoTo KESME 
OPTION_REG=%10000100  
INTCON=%10100000     'Kesmeler aktif,"-", ve TMR0 kesmesi aktif 
TMR0=101
Clear  'tüm değişkenler sıfırlandı

Cls

basla:
sayac=int/1000
Print At 1,1,DEC3 sayac
'Print At 2,1,Dec int
'DelayMS 1 

If int=220 Then High led1
If int=1660 Then Low led1
If int=550 Then High led2
If int=1800 Then Low led2


GoTo basla

KESME:
Context SAVE 
Inc int 	    
INTCON.2=0
TMR0=101
Context Restore 

End


Bu şekilde olursa istediğim değerlerde ledleri yakıp söndürebiliyorum ama kesme içinde IF-ELSE kullanmam gerekiyor.
Declare FLOAT_DISPLAY_TYPE = LARGE
		Device = 16F876
        Config HS_OSC,WDT_OFF,PWRTE_OFF,BODEN_OFF,LVP_OFF,DEBUG_OFF,CP_ALL
        XTAL = 20
		LCD_RSPIN = PORTA.0
		LCD_ENPIN = PORTA.1
		LCD_DTPIN = PORTC.4	
		LCD_INTERFACE = 4	' 4-bit Interface
		LCD_LINES = 4
		LCD_TYPE = 0
    
        ALL_DIGITAL = TRUE	' Set PORTA and PORTE to all digital


        
TRISA=%00000000
TRISB=%00000000
TRISC=%00000000
PORTA=0
PORTB=0
PORTC=0

Symbol led1     PORTC.0
Symbol led2     PORTC.2 
Dim sayac As Float
Dim int As DWord 

On_Hardware_Interrupt GoTo KESME 
OPTION_REG=%10000100  
INTCON=%10100000     'Kesmeler aktif,"-", ve TMR0 kesmesi aktif 
TMR0=101
Clear  'tüm değişkenler sıfırlandı

Cls

basla:
sayac=int/1000
Print At 1,1,DEC3 sayac
'Print At 2,1,Dec int
'DelayMS 1 

GoTo basla

KESME:
Context SAVE 
Inc int 

If int=220 Then High led1
If int=1660 Then Low led1
If int=550 Then High led2
If int=1800 Then Low led2
	    
INTCON.2=0
TMR0=101
Context Restore 

End

Tagli

Esitligin tutmamasi normal. Anlik bir olay sonucta, yakalasan sasardim. Senin de dedigin gibi, kesme icinde karsilastirma yapmak da hem yanlis hem de anlamsiz.

Cozum, disarida esitlik degil aralik kontrol etmek. Duruma gore sadece buyukluk veya kucukluk de kontrol edebilirsin.
Gökçe Tağlıoğlu

serhat1990

@Tagli Hocamın dediği gibi ,

Bu durumu büyüktür , küçüktür , büyük eşittir , küçük eşittir , gibi koşullarla görebilirsin. Kolay gelsin ...

Maxim

kesme içinde if-else kullansak ne sorun olabilir ?

dyonizos

eşitlik yakalamam lazım cünkü bu degerlerin aralıkları önemli. 1-2ms farklar sorun olabilir. O nedenle eşitlik olması gerekiyor.
Maxim hocam kesme içinde çok kalmadan çıkın denildiği için çıkmaya çalışıyorum. Yoksa orada işlem yapmak daha kolay valla :)

Tagli

Alıntı yapılan: Maxim - 11 Temmuz 2012, 09:07:19
kesme içinde if-else kullansak ne sorun olabilir ?
Aslında yanlış ifade etmişim. Yanlış olan kesme içinde karşılaştırma yapmak değil. Gerektiğinde yapılır tabi, neden yapılmasın.. Ama burada kesme içinde o karşılaştırmanın yapılması, timer'ın kullanım amacına ters. Yoksa dyonizos'un da belirttiği gibi kesme içinde çok zaman alan işler yapılmadığı sürece sorun yok. Birkaç karşılaştırma çok zaman almaz.
Gökçe Tağlıoğlu

LukeSkywalker

Hocam yaptığınız iş kesmenin kullanımına aykırı. Kesmeyi istediğiniz süreye göre oluşturup her kesme oluştuğunda dışarıdaki bir değişkeni arttırarak o değeri kontrol edip ledleri yakıp söndürün.

CLR

Alıntı yapılan: dyonizos - 11 Temmuz 2012, 09:10:27
eşitlik yakalamam lazım cünkü bu degerlerin aralıkları önemli. 1-2ms farklar sorun olabilir. O nedenle eşitlik olması gerekiyor.
Maxim hocam kesme içinde çok kalmadan çıkın denildiği için çıkmaya çalışıyorum. Yoksa orada işlem yapmak daha kolay valla :)


Tmr'ı hazırlarken tam istediğin zaman için programlayabilirsin. Tmr'ın sayan registerine başlangıç değerini ver interrupt geldiğinde senin istediğin zaman olacaktır interrupt içinde tekrar sayan registere aynı değerleri verirsen hiç şaşmaz her defasında aynı zamanda interrupt oluşur. Bu durumda if kullanmanada gerek kalmaz.

Örnek vereyim anlaşılması kolay olsundiye xtal 4mhz olsun. Bu durumda timerlar 1mhzde sayar(ilgili timerın prescalerı 1/1 ise) Amacımız 200us de bir interrupt oluşturmak olsun.TMR0 için örnek vereyim
TMR0=0xff-200;
TMR0ON=1;

int içinde
TMR0=0xff-200;  // tekrar yükle
flags.tmr0=1;    // int geldiğini alayacağımız flag
Knowledge and Experience are Power

dyonizos

Yaklasik 13-15 arasi degisken zaman degerleri var. Zaman ilerlerken (sayac sayarken) her bir degere geldiginde sirasi ile o degerde yapmasi gereken islemleri yapmasi gerekiyor. Tmr a tek bir deger verebildigimizi varsayarsak sizin dediginiz yontemle tum degiskenlerde islem yapmasini saglayabilirmiyiz?

CLR

Evet yapabilirsin yeterki hepsinin zaman aralığını baştan belirle, sonra bu belirlediğin zamanları bir diziye yerleştir, sırasıyla timera ilk değer olarak yüklersen hepsinde tam zamanında işlemleri yaparsın, biri gelince sonraki değeri vereceksin
Knowledge and Experience are Power

camby

@uicroarm,

Dediğin şekilde aynı anda 1 tane zaman takibi yapabilirsin. Birini yapıyorsun sonra diğerini yapıyorsun işlemler sıralı oluyor.

----

Şu şekilde olabilir :

Soru :

Diyelim 4 farklı çıkışta 4 farklı led var. Bunlar 1ms , 7ms , 17ms , 29ms 'lik periyotlarda yanması gerekiyor. Ve bu işin timer ile yapılıp 1.0000000ms hassasiyet ile yapılması gerekiyor.

Çözüm : Birim zaman burada 1ms , 1ms'de bir kesme olacak şekilde bir kesme oluşturulacak şekilde Timerlar'dan birini kurulacak. Bu iş için timer0 değil de , taşma değeri belirlenebilen  TMR2 gibi ( daha doğrusu donanımsal PWM'e hizmet etmek için hazırlanmış ) bir timer kullanılmalı. Ön bölücü , son bölücü , taşma değeri ayarlanıp birim zaman ayarlandıktan sonra ( bu örnekte 1 ms ) her kesmeye gidişte bir sayaç değeri arrıtırılacak ve bu sayaç değeri her arttırmadan sonra :

1 , 7 - 17 - 29 değerlerinin katları ile karşılaştırılacak . Değeri tutan var ise işlem yapılacak. Birim zaman EBOB , timer resetleme zamanı EKOK.


Takip edilmesi gereken değişken sayısı "N"'lerle ifade edildiğinde daha iyi algoritmalar da çıkabilir

PLC'lerde bu iş nasıl yapılıyor ?

------

@uicroarm, sen de bunu kastetmiş ama ben anlamamış olabilirim.

CLR

Alıntı yapılan: camby - 11 Temmuz 2012, 18:27:41
@uicroarm,

Dediğin şekilde aynı anda 1 tane zaman takibi yapabilirsin. Birini yapıyorsun sonra diğerini yapıyorsun işlemler sıralı oluyor.

----

Şu şekilde olabilir :

Soru :

Diyelim 4 farklı çıkışta 4 farklı led var. Bunlar 1ms , 7ms , 17ms , 29ms 'lik periyotlarda yanması gerekiyor. Ve bu işin timer ile yapılıp 1.0000000ms hassasiyet ile yapılması gerekiyor.

Çözüm : Birim zaman burada 1ms , 1ms'de bir kesme olacak şekilde bir kesme oluşturulacak şekilde Timerlar'dan birini kurulacak. Bu iş için timer0 değil de , taşma değeri belirlenebilen  TMR2 gibi ( daha doğrusu donanımsal PWM'e hizmet etmek için hazırlanmış ) bir timer kullanılmalı. Ön bölücü , son bölücü , taşma değeri ayarlanıp birim zaman ayarlandıktan sonra ( bu örnekte 1 ms ) her kesmeye gidişte bir sayaç değeri arrıtırılacak ve bu sayaç değeri her arttırmadan sonra :

1 , 7 - 17 - 29 değerlerinin katları ile karşılaştırılacak . Değeri tutan var ise işlem yapılacak. Birim zaman EBOB , timer resetleme zamanı EKOK.


Takip edilmesi gereken değişken sayısı "N"'lerle ifade edildiğinde daha iyi algoritmalar da çıkabilir

PLC'lerde bu iş nasıl yapılıyor ?

------

@uicroarm, sen de bunu kastetmiş ama ben anlamamış olabilirim.


Elbette sırasıyla yapacaksın, 7ms dediğim zaman birimi 1ms'den sonra gelmiyor mu? Okekini alır sayıcı koyar sayarsın veya benim bahzettiğim yönlemle, ben sayıcı yöntemini kullanmam çünkü karşılaştırmalar çok zaman kaybı olur. Karşılaştırma yapmayalım diye pointer vs kullanıyoruz. işlemler hızlansın diye yani
Knowledge and Experience are Power

dyonizos

Alıntı yapılan: uicroarm - 11 Temmuz 2012, 13:49:16
Tmr'ı hazırlarken tam istediğin zaman için programlayabilirsin. Tmr'ın sayan registerine başlangıç değerini ver interrupt geldiğinde senin istediğin zaman olacaktır interrupt içinde tekrar sayan registere aynı değerleri verirsen hiç şaşmaz her defasında aynı zamanda interrupt oluşur. Bu durumda if kullanmanada gerek kalmaz.

Örnek vereyim anlaşılması kolay olsundiye xtal 4mhz olsun. Bu durumda timerlar 1mhzde sayar(ilgili timerın prescalerı 1/1 ise) Amacımız 200us de bir interrupt oluşturmak olsun.TMR0 için örnek vereyim
TMR0=0xff-200;
TMR0ON=1;

int içinde
TMR0=0xff-200;  // tekrar yükle
flags.tmr0=1;    // int geldiğini alayacağımız flag


Bu sistemde kesme oluştuğunda o kesmenin hangi işleme bağlı olduğunu anlamak ve gereken led leri yakıp söndürmek için yine kesme içine if-else karşılaştırması koymamız gerekmiycekmi?
yani 200ms de LED1 yanacak. 202 ci ms de sönecek. 208 de LED2 yanıp 212 de LED2 sönecek.
ayrıca 200 de kesme oluşturdum ve LED1 i yaktım diyelim ( bunuda hangi ledin yanması gerektiğini anlamak için if-else ile bulmak gerekir diye düşünüyorum. yada case ile) bu durumda 202 ms sonunda LED1 in sönmesi için timer degerini 202 değilde 2 vermek gerekecek yanılıyormuyum? ve yine kesme içinde sönmesi gereken LED in hangisi olduğunu bulabilmek için bir yol izlemem gerekir.

camby

Alıntı yapılan: uicroarm - 11 Temmuz 2012, 18:41:04
Elbette sırasıyla yapacaksın, 7ms dediğim zaman birimi 1ms'den sonra gelmiyor mu? Okekini alır sayıcı koyar sayarsın veya benim bahzettiğim yönlemle, ben sayıcı yöntemini kullanmam çünkü karşılaştırmalar çok zaman kaybı olur. Karşılaştırma yapmayalım diye pointer vs kullanıyoruz. işlemler hızlansın diye yani

- 1 Adet kontrol işlemi 8bitte dallanmasıyla beraber 4 cycle.

- Pointer'ın açıklayabilir misin ? Pointer ile yapılan işlemlerde arka planda yapılan nedir ?

CLR

Alıntı yapılan: camby - 11 Temmuz 2012, 22:45:53
- 1 Adet kontrol işlemi 8bitte dallanmasıyla beraber 4 cycle.

- Pointer'ın açıklayabilir misin ? Pointer ile yapılan işlemlerde arka planda yapılan nedir ?

Pointer, arka arkaya yapacağın adımları hızlandıran bir işlemdir. Sonraki yapacağın işi pointer'a gösterirsin işlem zamanı geldiğinde doğrudan o işi yaparsın bu defa daha sonraki işlemi pointer'a gösterirsin. Eğer bahsettiğin gibi karşılaştırma kullanırsan her defasında tüm karşılaştırmaları yapman gerekir bu nedenle, 2den fazla if-else veya veya switch case durumları fazla ise pointerla yapmak en hızlısıdır, Sanırım bu senin için açıklayıcı olmuştur.

Knowledge and Experience are Power