Salvo
Kayıtlı Üye
GECİKME VE DÖNGÜLER
Döngü nedir?
Döngüler program içersinde bir dizi işlemin belli sayıda yapılması yada bir şartın gerçekleşmesine kadar belli bir işin yapılması veya zaman gecikmesi gibi amaçlar için kullanılan alt yordamlardır.
Örneğin visual basic de 1 den 10 a kadar olan sayıların toplanması işlemi şöyle yapılır;
--------------------
toplam=0
for sayi=1 to 10
toplam=toplam+1
next
--------------------
Sonuçta Toplam=10 olacaktır. 4 satırla işi hallettik.
Ama assembler a gelince iş değişiyor, çünkü orda for next kullanma gibi bir lüksümüz yok.
Assembler ile bu işlemleri yapmak için etiketlerden ve yönlendirme komutu olan GOTO komutundan çok faydalanıyoruz. Hemen küçük bir örnek verelim;
------------------------------
dongubasi
goto dongubasi
------------------------------
2 satırlık bu program, pic için assembler da yapabileceğimiz en küçük döngüdür ve bir kısır döngüdür.
hemen ledler ile ilgili bir örnek verelim;
aşağıdaki kodlar ile portB nin birinci pin'ine (Sıfırıncı bit) bağlı olan led yakılıp söndürülür.
---------------------------
dongubasi
bsf portb,0
bcf portb,0
goto dongubasi
------------------------------
bakın şimdi konuyu biraz dağıtıp burada bir parantez açalım.
(Eğer bu programı denerseniz, devreyi çalıştırdığınızda göreceksiniz ki programınız sizin dediğinizi yapmayacak, yani diyeceksiniz ki "bu program" çalışmıyor.
halbuki bu kodlar doğru. Burada ince bir nokta var.
Soru: Evimizdeki ampuller devamlı yanıyor mudur, yani anahtarı açtığınızdan itibaren kapanıncaya kadar devamlı yanar mı?
hemen cevap verelim. evet yanar, ama bu doğru cevap değil. Bu lambalar, devamlı yanmaz, ara sıra canı sönmek ister ve söner, normal şartlar altında bu sönme olayı 10 msn de bir olur.
Parantezin içine bir parantez daha açalım ( konuları oldukça basitten başlayarak karmaşığa doğru götürmek istiyorum ve bu anlatım şeklini seçmemdeki amaç da konunun anlaşılırlığını ve doyuruculuğunu sağlamak. O yüzden sizin için çok basit olan bir yer karşınıza gelirse o bölümü geçebilirsiniz.). Birinci parantezden devam edelim. Lambalarımız sn de 100 defa iyice sönmesine rağmen biz bunu farketmeyiz. neden? çünkü 10 msn gibi bir zamanı gözlerimiz algılamaz ve devamlı yanıyor görürüz, çünkü lamba sönmesine rağmen yanık kalma süresi daha fazla olduğundan devamlı yanıyor görürüz.
-----------------------------
dongubasi
bsf portb,0
bcf portb,0
goto dongubasi
------------------------------
PIC de eğer osilatör olarak 4 MHZ osilatör kullanıyorsak yukarıdaki programda, led yanar 1 µsn yanık kalır sonra söner ve 3 µsn sönük kalır. Bu programda biz bir şey gözlemleyemeyiz. Sönük kalma süresi yanık kalma süresinden daha fazla olduğu için led devamlı sönük görünecektir. Yukarıdaki döngü özgür, bağımsız ve koşulsuz bir döngü ve belli bir sayısı yok. Yani gene bu program PIC resetleninceye kadar yada gücü kesilinceye kadar yada bozuluncaya kadar devam edecektir. Yani kısacası bir koşul ve bir sayı yok.
şimdi 10 defa çalışacak bir alt bölüm yapalım. Bunun için mantığı anlatalım (çünkü assembler da döngü için bir komut yok.).
1) Belli sayıda bir döngü yapılırken önce döngü sayısı bir değişkene aktarılır.
2) Döngü başı için bir etiket tanımlanır.
3) Ardından bu sayı bir komutla her defasında bir azaltılır.
DECFSZ komutu bu işi yapar. F register içindeki sayıyı bir azaltıp F registerin içine koyar, ve F içindeki sayı sıfıra indiğinde yönlendirme yaparak kendinden sonraki komutu işletmeden, pic'i kendinden sonraki 2 inci komuta gönderir.
4) eğer sıfıra ulaşıldıysa zaten döngüden çıkar. ama eğer sıfıra ulaşılmadıysa döngü başı etiketine yönlendirme yapılması gerekir ki döngü devam etsin.
Bunu da GOTO komutu yapıyor.
5) Döngü dışına çıkışta ne yapacaksa yada program devam edecekse bir sonraki satırda da o verilir.
Şimdi bunları toparlayalım.
-----------------------------
movlw d'10'
movwf SAYAC
DONGUBASI
decfsz SAYAC,f
goto DONGUBASI
goto BAS
-----------------------------
SAYAC değişkenine 10 atanırsa döngü 10 defa işlenir 100 atanırsa 100 defa işlenir.
PIC içinde döngülerin en çok kullanıldığı yerler gecikme sağlamak, buton kontrolü gibi işlemlerdir. Gözle görülebilir bir gecikme sağlayacaksak bu durumda döngü için kullanılan sayı artırılmalıdır. ve bu durumda bir adet döngü bizim ihtiyacımızı karşılamaz. Ama program gereği bir miktar mesela 100 µsn gibi bir gecikme sağlamak istiyorsak bu durumda bir döngü işimizi görür. Gözle görülür bir döngüden kasıt mesela ledi flaşör gibi yakıp söndürme işlemi yapacaksak iç içe döngüler kurmalıyız. ama göze göre ayar olduğu için de bunu kendimiz değişkenlere vereceğimiz sayılarla deneyerek yada hesaplayarak ayarlarız. İç içe döngülerde de mantık aynı olacaktır.
Program birinci döngüden başlar ve hemen ikinci döngüye girer, ikinci döngü bittiğinde birinci döngünün ilk dönüşü tamamlanmış olur.
İÇ İÇE 2 Lİ DÖNGÜ:
Visual basic de bir örnek:
--------------------------------
for i=1 to 10
for j=1 to 10
komutlar
next
next
--------------------------------
Bu döngü sonucunda komutlar 10+10=20 defa değil 10*10=100 defa işlenmiş olur.
Aynı işlemi pic ile yaparsak,
-----------------------------
TUMDONGU
movlw d'255'
movwf SAYAC1
DONGUBASI1
movlw d'255'
movwf SAYAC2
DONGUBASI2
decfsz SAYAC2,f
goto DONGUBASI2
decfsz SAYAC1,f
goto DONGUBASI1
RETURN
-----------------------------
Burada return komutu; eğer bu döngü bir gecikme alt yordamı olarak çağrılacaksa PIC'i çağrıldığı yere geri göndermek içindir. Eğer bir yerden çağrılma yapılmayacak ve program işlenip devam edecekse return komutuna gerek yoktur.
İÇ İÇE 3 Lü DÖNGÜ:
-----------------------------
GECIKME
MOVLW D'255'
MOVWF SAYAC1
DONGU1
MOVLW D'255'
MOVWF SAYAC2
DONGU2
MOVLW D'255'
MOVWF SAYAC3
DONGU3
DECFSZ SAYAC3,F
GOTO DONGU3
DECFSZ SAYAC2,F
GOTO DONGU2
DECFSZ SAYAC1,F
GOTO DONGU1
RETURN
END
-----------------------------
Bu son alt program iç içe 3'lü döngüde elde edilebilecek en fazla zamanı elde eder. Şüphesiz ki burada elde edilecek zaman gecikmesi 255X255X255 µsn diye aklımıza gelebilir, ama değildir. Sadece yukardan aşağıya komutların bir defa işlendiğini göz önüne alırsak 13 adet komut vardır. ve bu aralık iç içe defalarca işlenmektedir. Buradaki 3'lü döngüde sayac değişkenlerine 255 verip belli aralıklarla ledlerin sönüp yanmasını beklemeyin. Çünkü döngüden çıkmak için PIC'in yaklaşık 50.000.000 kusur tane işleyecek komutu var. Bu da yaklaşık 50 sn gibi bir zamana denk düşer.
__________________
Döngü nedir?
Döngüler program içersinde bir dizi işlemin belli sayıda yapılması yada bir şartın gerçekleşmesine kadar belli bir işin yapılması veya zaman gecikmesi gibi amaçlar için kullanılan alt yordamlardır.
Örneğin visual basic de 1 den 10 a kadar olan sayıların toplanması işlemi şöyle yapılır;
--------------------
toplam=0
for sayi=1 to 10
toplam=toplam+1
next
--------------------
Sonuçta Toplam=10 olacaktır. 4 satırla işi hallettik.
Ama assembler a gelince iş değişiyor, çünkü orda for next kullanma gibi bir lüksümüz yok.
Assembler ile bu işlemleri yapmak için etiketlerden ve yönlendirme komutu olan GOTO komutundan çok faydalanıyoruz. Hemen küçük bir örnek verelim;
------------------------------
dongubasi
goto dongubasi
------------------------------
2 satırlık bu program, pic için assembler da yapabileceğimiz en küçük döngüdür ve bir kısır döngüdür.
hemen ledler ile ilgili bir örnek verelim;
aşağıdaki kodlar ile portB nin birinci pin'ine (Sıfırıncı bit) bağlı olan led yakılıp söndürülür.
---------------------------
dongubasi
bsf portb,0
bcf portb,0
goto dongubasi
------------------------------
bakın şimdi konuyu biraz dağıtıp burada bir parantez açalım.
(Eğer bu programı denerseniz, devreyi çalıştırdığınızda göreceksiniz ki programınız sizin dediğinizi yapmayacak, yani diyeceksiniz ki "bu program" çalışmıyor.
halbuki bu kodlar doğru. Burada ince bir nokta var.
Soru: Evimizdeki ampuller devamlı yanıyor mudur, yani anahtarı açtığınızdan itibaren kapanıncaya kadar devamlı yanar mı?
hemen cevap verelim. evet yanar, ama bu doğru cevap değil. Bu lambalar, devamlı yanmaz, ara sıra canı sönmek ister ve söner, normal şartlar altında bu sönme olayı 10 msn de bir olur.
Parantezin içine bir parantez daha açalım ( konuları oldukça basitten başlayarak karmaşığa doğru götürmek istiyorum ve bu anlatım şeklini seçmemdeki amaç da konunun anlaşılırlığını ve doyuruculuğunu sağlamak. O yüzden sizin için çok basit olan bir yer karşınıza gelirse o bölümü geçebilirsiniz.). Birinci parantezden devam edelim. Lambalarımız sn de 100 defa iyice sönmesine rağmen biz bunu farketmeyiz. neden? çünkü 10 msn gibi bir zamanı gözlerimiz algılamaz ve devamlı yanıyor görürüz, çünkü lamba sönmesine rağmen yanık kalma süresi daha fazla olduğundan devamlı yanıyor görürüz.
-----------------------------
dongubasi
bsf portb,0
bcf portb,0
goto dongubasi
------------------------------
PIC de eğer osilatör olarak 4 MHZ osilatör kullanıyorsak yukarıdaki programda, led yanar 1 µsn yanık kalır sonra söner ve 3 µsn sönük kalır. Bu programda biz bir şey gözlemleyemeyiz. Sönük kalma süresi yanık kalma süresinden daha fazla olduğu için led devamlı sönük görünecektir. Yukarıdaki döngü özgür, bağımsız ve koşulsuz bir döngü ve belli bir sayısı yok. Yani gene bu program PIC resetleninceye kadar yada gücü kesilinceye kadar yada bozuluncaya kadar devam edecektir. Yani kısacası bir koşul ve bir sayı yok.
şimdi 10 defa çalışacak bir alt bölüm yapalım. Bunun için mantığı anlatalım (çünkü assembler da döngü için bir komut yok.).
1) Belli sayıda bir döngü yapılırken önce döngü sayısı bir değişkene aktarılır.
2) Döngü başı için bir etiket tanımlanır.
3) Ardından bu sayı bir komutla her defasında bir azaltılır.
DECFSZ komutu bu işi yapar. F register içindeki sayıyı bir azaltıp F registerin içine koyar, ve F içindeki sayı sıfıra indiğinde yönlendirme yaparak kendinden sonraki komutu işletmeden, pic'i kendinden sonraki 2 inci komuta gönderir.
4) eğer sıfıra ulaşıldıysa zaten döngüden çıkar. ama eğer sıfıra ulaşılmadıysa döngü başı etiketine yönlendirme yapılması gerekir ki döngü devam etsin.
Bunu da GOTO komutu yapıyor.
5) Döngü dışına çıkışta ne yapacaksa yada program devam edecekse bir sonraki satırda da o verilir.
Şimdi bunları toparlayalım.
-----------------------------
movlw d'10'
movwf SAYAC
DONGUBASI
decfsz SAYAC,f
goto DONGUBASI
goto BAS
-----------------------------
SAYAC değişkenine 10 atanırsa döngü 10 defa işlenir 100 atanırsa 100 defa işlenir.
PIC içinde döngülerin en çok kullanıldığı yerler gecikme sağlamak, buton kontrolü gibi işlemlerdir. Gözle görülebilir bir gecikme sağlayacaksak bu durumda döngü için kullanılan sayı artırılmalıdır. ve bu durumda bir adet döngü bizim ihtiyacımızı karşılamaz. Ama program gereği bir miktar mesela 100 µsn gibi bir gecikme sağlamak istiyorsak bu durumda bir döngü işimizi görür. Gözle görülür bir döngüden kasıt mesela ledi flaşör gibi yakıp söndürme işlemi yapacaksak iç içe döngüler kurmalıyız. ama göze göre ayar olduğu için de bunu kendimiz değişkenlere vereceğimiz sayılarla deneyerek yada hesaplayarak ayarlarız. İç içe döngülerde de mantık aynı olacaktır.
Program birinci döngüden başlar ve hemen ikinci döngüye girer, ikinci döngü bittiğinde birinci döngünün ilk dönüşü tamamlanmış olur.
İÇ İÇE 2 Lİ DÖNGÜ:
Visual basic de bir örnek:
--------------------------------
for i=1 to 10
for j=1 to 10
komutlar
next
next
--------------------------------
Bu döngü sonucunda komutlar 10+10=20 defa değil 10*10=100 defa işlenmiş olur.
Aynı işlemi pic ile yaparsak,
-----------------------------
TUMDONGU
movlw d'255'
movwf SAYAC1
DONGUBASI1
movlw d'255'
movwf SAYAC2
DONGUBASI2
decfsz SAYAC2,f
goto DONGUBASI2
decfsz SAYAC1,f
goto DONGUBASI1
RETURN
-----------------------------
Burada return komutu; eğer bu döngü bir gecikme alt yordamı olarak çağrılacaksa PIC'i çağrıldığı yere geri göndermek içindir. Eğer bir yerden çağrılma yapılmayacak ve program işlenip devam edecekse return komutuna gerek yoktur.
İÇ İÇE 3 Lü DÖNGÜ:
-----------------------------
GECIKME
MOVLW D'255'
MOVWF SAYAC1
DONGU1
MOVLW D'255'
MOVWF SAYAC2
DONGU2
MOVLW D'255'
MOVWF SAYAC3
DONGU3
DECFSZ SAYAC3,F
GOTO DONGU3
DECFSZ SAYAC2,F
GOTO DONGU2
DECFSZ SAYAC1,F
GOTO DONGU1
RETURN
END
-----------------------------
Bu son alt program iç içe 3'lü döngüde elde edilebilecek en fazla zamanı elde eder. Şüphesiz ki burada elde edilecek zaman gecikmesi 255X255X255 µsn diye aklımıza gelebilir, ama değildir. Sadece yukardan aşağıya komutların bir defa işlendiğini göz önüne alırsak 13 adet komut vardır. ve bu aralık iç içe defalarca işlenmektedir. Buradaki 3'lü döngüde sayac değişkenlerine 255 verip belli aralıklarla ledlerin sönüp yanmasını beklemeyin. Çünkü döngüden çıkmak için PIC'in yaklaşık 50.000.000 kusur tane işleyecek komutu var. Bu da yaklaşık 50 sn gibi bir zamana denk düşer.
__________________