avatar_mierdogan

PIC Programlama Sorunu

Başlatan mierdogan, 20 Nisan 2012, 11:48:55

mierdogan

Herkese merhaba öncelikle ETE hocamızın yeni sitesi hayırlı olsun iyi varsınız.

Problemime gelince;

1- Elimde pic prog/deka pro-1 eğitim kartı var fakat IF-ELSE konularının işlendiği derslerden bir örnek çıkartıp uyguladığımda butonlara bastığım zaman programın çalışmadığını fakat pic bacaklarına(buton girişleri) gelen 5 voltun 0 a çekildiğni gördüm pic'i değiştirdim ama tuşlara bastıktan sonra herhangi bir hareket göremiyorum. butonsuz sadece karaşimşek denemesi yaptığımda ledler  sırasıyla yanıyor. kartın demo yazılımlarıda çalışıyor? yazılımda ne değiştirmeliyim ki programım çalışsın? MCU 16F877A

2- Bir forumda aşağıdaki kodu gördüm pull-upların iptali için eklesem bir etkisi olurmu? Gerçi bu pull-up benim anladığım butonların 5 voltta olmasıyla alakalımı bilmiyorum :). Bu kodu kaldırınce programın en üstündeki device satırlarına problem veriyor ekleyince sadece bu satıra problem veriyor...

Satırı Kaldırınca verdiği hata= Opcode expected instead of 'cpd_on
Satırı Ekleyince verdiği hata= Bad token"ı" //Line 14 Syntax Error

optıon_reg.7=0


3- Elimdeki eğitim kartı sizce nasıldır? Bir hayli donanım var üzerinde.

Saygılar

Örnek Program;
@Device CPD_ON
@DEVICE WDT_OFF
@DEVICE XT_OSC
@DEVICE PWRT_OFF
@DEVICE BOD_OFF
@DEVICE WRT_1FOURTH
@DEVICE LVP_OFF
@DEVICE DEBUG_OFF

TRISB=0
TRISA=%11111
PORTB=0
optıon_reg.7=0

A VAR BYTE
B VAR BYTE

BASLA:
IF PORTA.0=1 THEN SAYDIR1
IF PORTA.1=1 THEN SAYDIR2
IF PORTA.2=1 THEN SAYDIR3
GOTO BASLA

SAYDIR1:
PORTB=1
PAUSE 100
PORTB=2
PAUSE 100
PORTB=4
PAUSE 100
PORTB=8
PAUSE 100
PORTB=16
PAUSE 100
PORTB=32
PAUSE 100
PORTB=64
PAUSE 100
PORTB=128
PAUSE 100
PORTB=256
RETURN

SAYDIR2:
IF PORTA.3=1 THEN TOGGLE PORTB.0
PAUSE 100
IF PORTA.4=1 THEN TOGGLE PORTB.1
GOTO BASLA

SAYDIR3:
FOR A = 1 TO 5
HIGH PORTB.4
PAUSE 100
LOW PORTB.4
PAUSE 100
NEXT
RETURN
"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

ete

Bir işlemciye bağlı buton lar olduğunu varsayalım. Butona bastığımız zaman işlemcinin bunu algılamasını istiyoruz ne yapmalıyız?.

İşlemci pinlerine bağlı butonların basılıp basılmadığını ancak ve ancak o pinde bir konum değişikliği olursa anlayabilir.
Şöyle düşün,
Evin bir kapısı var. O kapının açılıp açılmadığını nasıl anlarsın. ? Normalde kapalı duran kapı açık kalmış ise açıldığını anlarsın. Veya kapının önüne bir sehpa koyarsın kapı açılınca otomatik sehpa da ittirilir ve sehpa yer değiştirir. Değiştirmiş ise sne kapının açıldığını anlarsın.  Bunun gibi bir şey. İşlemcide buton pinindeki değişikliği algılar. Peki pin nasıl durmalıki işlemci butona basıldığını anlasın. Bu iki değişik şekilde olur.Bunlar sırası ile;
- Buton pini LOW da beklerken butona basılınca pin'e HIGH gelirse otomatikman LOW dan HIGH a değişim olacağı için anlar.
- Buton pini HIGH da beklerken butona basılınca pin'e LOW gelirse otomatikman HIGH dan LOW a değişim olacağı için yine kolaylıkla anlar.
Peki bir pini LOW da bekletmek ne anlama geliyor. O pine Pulldown direnci ile LOW verildiğini gösteriyor demektir. Buda GND ile o pin arasına bir 10K lık bir direnç bağlanması anlamına gelir.  Neden direk GND ye bağlamıyoruz de dirençle yapıyoruz bu işi dersen. Yapabiliriz ama o pin GND ye bağlı iken bizde buton ile oraya +5V verir isek GND ile +5V bir bir ile kısa devre olur ve ortalık karışır bir şeyler anında yanıverir. Halbuki 10K lık direnç üzerinden GND ile +5V tun birleşmesi hiç bir problem yaratmaz. Bu ndenle Pulldown yani sıfıra Volta çekme işlemi yaparız.

Aynı şekilde pinin HIGH da beklemesi ise o pin ile +5V tun 10K direnç ile birleştirilmesi yolu ile sağlanır. Böylece pin HIGH da beklerken butona basışınca pine LOW (GND) verilerek pinde konum değişikliği yaratırız.

Şimdi bunalrı sana elindeki eğitim setinin fonksiyonalrını iyice tanıman içina anlattım.

Programda IF BUTON=0 gibibir ifade var ise butona basılınca pin LOW olacak demektir. O halde senin buton pinin HIGH da (pullup) beklemesi gerekir. Programda IF BUTIN=1 gibi bir terim var ise senin butonun LOW da beklemesi yani Pulldown olması gerekir. Bu özeklliklere bağlı olarak eğitim setinde mutlaka dip switch gibi elemanlarla buton pinlerine HIGh da bekle yada LOW da bekle gibi özellikler kazandırılıyordurç Programa göre onları aktif etmen gerekiyor.

İşlemcilerde genellikle PORTB de dahili Pullup dirençleri vardır ve Option registeri 7. biti ni 0 yaparak aktif edilir aynı biti 1 yaparak devre dışı bırakılırlar.
Senin programda şayet pulluplar aktif ise ve programın Pulldown gerektiriyorsa sistem çalışmayacaktır tabiiki.
Bu nedenle programı iyi ce anlaman ve ona göre işlem yapman gerekir.

Eğitim setini görmediğimiz için bir fikir yürütmek imkansız. En azından özelliklerini bilsek bir yorum yapabilirdik.
Aldığınbir şey için yorum bekleme daha iyi olur. Almışsın artık geriye dönüşünde yok. İyidir kötüdür geride kalmış zaten. Sen iyisimi onun özelliklerini çözmeye bak bence.

Ete


mierdogan

Bakalım doğrumu anladım...

Amacım sadece kartta yazdığım basit programı çalıştırabilmek CCS C de yapabiliyorum ama burda denediğimde yapamıyorum bu da insanın şevkini kırıyor tabi.. siz ve sizin gibi kaynaklar olmasa yerimizde sayarız... okuldaki ders programında bile pic ler olmasına rağmen sene sonuna geldiğimizde hiç bir şey bilmiyorduk Genelleme yapmıyorum ama proje ödevleri hep dışarılara yaptırılıyor. demek istediğim sanırım dökümantasyon veya kaynak eksiğimiz var(dı).

Kod'u aşağıdaki gibi değiştirdim, @device satırlarını kaldırdım programı yükledikten sonra ledler sırayla bir defa yanıp sönüyor fakat butonlarda hala tepki yok işlemci olarak 16F877A takılı programı yüklemek için Micro pro26 kullanıyorum, MicroPro fuse ayarları ise şu şekilde

WDT=Disabled
BODEN=Enabled
CPD=Disabled
DEBUG=Disabled
Code Protect=Disabled
PWRTE=Disabled
LVP=Disabled
WRT Enable=Enabled
Oscilator=XT

TRISB=0
TRISA=%11111
PORTB=0


A VAR BYTE
B VAR BYTE

BASLA:
IF PORTA.0=0 THEN SAYDIR1
IF PORTA.1=0 THEN SAYDIR2
IF PORTA.2=0 THEN SAYDIR3
GOTO BASLA

SAYDIR1:
PORTB=1
PAUSE 100
PORTB=2
PAUSE 100
PORTB=4
PAUSE 100
PORTB=8
PAUSE 100
PORTB=16
PAUSE 100
PORTB=32
PAUSE 100
PORTB=64
PAUSE 100
PORTB=128
PAUSE 100
PORTB=256
RETURN

SAYDIR2:
IF PORTA.3=0 THEN TOGGLE PORTB.0
PAUSE 100
IF PORTA.4=0 THEN TOGGLE PORTB.1
GOTO BASLA

SAYDIR3:
FOR A = 1 TO 5
HIGH PORTB.4
PAUSE 100
LOW PORTB.4
PAUSE 100
NEXT
RETURN
"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

ete

#3
Kodu önceden verse idin daha fazla yol alabilirdik.
16F877A işlemcisini inceledinmi hiç. Ne gibi özellikleri var acaba.?
İncelemdiğin belli çünki programda olması gerekenleri yazmamışsın.
CCS de de durum değişmez ama orada ALL DGITAL = TRUE gibi yada benzeri bir komut ile bütün pinleri digital yapabiliyorsun.
Basicde bunu işlemci registerlerini ayarlayarak yapman gerekiyor. Çünkiiiiiiiii
16F877A da iki önemli özellik var. Birincisi A portu Komparatör olarak çalışır önseçimli (default) olarak bu açılışta aktiftir.
Bunu kapatırsan geriden A portunun ADC çevirici olarak çalışabilme özelliği gelir. Bunda kapatırsan A portu pinlerini digital çalışma için hazır hale getirebilirsin. Senin programda buna ait hiç bir komut yok.
Komparatörleri kapatmak için CMCON=7 komutunu kullanman gerekiyor.
ADC (Analog) pinlerini kapatıp digital yapmak içinde ADCON1=7 komutunu kullanman gerekiyor.
Ancak bu iki komutu programın başına eklersen Senin buton pinlerin çalışır hale gelecektir.
16F877A da A portu pinleri 6 adet olmasına rağmen TRISA register 8 bitliktir. Bu nedenle TRISA=%111111 yerine TRISA=%00111111 şeklinde bir komut vermen daha doğru olacaktır.

İki türlü alt program vardır. Sık sık aynı satırları çalıştırmak için o satırları her seferinde yazmak yerine bir kere bir alt program şeklinde yazıp programı oraya yönlendirmek akıllıca bir iştir.
Yönlendirme iki şekilde olabilir.
- Birincisi GOTO ile gidip dönüşü mutlaka yine GOTO ile yapmak gerekir.
- Ikıncisi GOSUB ile gidip dönüşü mutlaka RETURN ile yapmak gerekir.

İkisi arasındaki temel fark şudur. Birinci sistemde Goto ile gittiğin yerden mutlaka Goto ile dönecğin için o satırları yalnızca bir yerde kullanabilirsin. Çünki dönüş satırını mesela GOTO BASLA gibi bir komutla yapacağın için program daima BASLA satırına dönecektir.
İkinci sistemde ise program nereden yollanmış ise dönüşü yine oraya olacaktır. Bu işlemde RETURN komutunun görülmesi ile otomatik olarak gerçekleşir.  Bu nedenle daha kullanışlı bir komuttur.

Programına bakarsan GOTO ile gittiğin yerden RETURN ile dönmeye çalışmışsın bu büyük bir hatadır. Program Gosub ile yönlendirilmediği için Return komutunu görünce nereye döneceğini şaşırır ve muhtemelen rastgele bir yere atlar.
Bu nedenle programın yönlendirme satırlarını şöyle yazman gerekiyor.
IF PORTA.0=0 THEN SAYDIR1
IF PORTA.1=0 THEN  SAYDIR2
IF PORTA.2=0 THEN  SAYDIR3
yerine
IF PORTA.0=0 THEN GOSUB SAYDIR1
IF PORTA.1=0 THEN GOSUB SAYDIR2
IF PORTA.2=0 THEN GOSUB SAYDIR3


Önceden de dediğim gibi programın başına;
CMCON=7
ADCON1=7
komutlarınıda eklediğin zaman programın çalışır hale gelecektir.

tabiiki PortA.0 - PortA.1 ve PortA.2 pinlerinde Pullup dirençleri olması gerekir. Butona basıldığı zamanda o pinlere LOW tatbik edilmesi gerekiyor. Eğitim setini bu şekilde ayarlaman gerekiyor.

Şimdi baktımda SAYDIR2 alt programının altında RETURN yer almıyor. Yerine GOTO BASLA satırı mevcut. Bu durumda oraya GOTO BASLA yerine RETURN yazman gerekecek.

Biraz düşünürsen bu programı GOSUB yerine GOTO lar ilede çalıştırabileceğinianlarsın. Bu durumda Buton kontrol kısmını hiç değiştirmeden ,
- SAYDIR1 alt programının altındaki RETURN yerine GOTO BASLA
- SAYDIR3 alt programının ALtındaki RETURN yerine GOTO BASLA
yazman gerekir. SAYDIR2 altında zaten GOTO BASLA yazılı olduğu için orda bir değişiklik gerekmeyecektir.

Ete


mierdogan

Teşekkür ederim hocam program çalıştı..

Alınan ders:  demekki bir işe başlarken bir kenarda işlemci bilgilerini bulundurmak ve iyice tatbik etmek gerekiyor :) çok eksiğim var anlaşıldı... Bu işi bir zincir gibi ele almak lazım tabi o zincir en zayıf halkası kadar güçlü oluyor benim zayıf olduğum yerlerde ortada... gerçi yeni başlayan için makul sonuçta yol gösteren yok sizlere ulaşamasak belki çok uzun zaman alacak problemleri çözmek.

Teşekkür ederim hocam... umarım bende bir gün sizin gibi nice ete'  lerin yetişmesine yardımcı olurum bir sonraki aşamada yazmak istediğim kodun çalışması şöyle tabi eldeki bilgilerle yapılır mı lütfen beni yönlendirin...

A portuna bağlı 3 adet buton olacak.
B portuna bağlı 3 adet led olacak

1. butona basınca 1. led 1 saniye aralıklarla yanıp sönecek diğerleri 0 konumunda kalacak
2. butona basınca 2. led 2 saniye aralıklarla yanıp sönecek diğerleri 0 konumunda kalacak
3. butona basınca 3. led 3 saniye aralıklarla yanıp sönecek diğerleri 0 konumunda kalacak

Pause ile yapabilirim ama bunu yapmak istemiyorum... sayaçlarla yapmak istiyorum incelemem gereken konular nedir?

Saygılar


"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

ete

Yapmak istediğini pause ler ile yapmaya kalkarsan hüsrana uğrarsın. Sebebi gayet açık.
Birinci led işini yaparken diğerleri onun işinin bitmesini bekleyecektir. Aynı şekilde 2. lied işini yaparken diğerleride onu beklemek zorundadır. Bu ise istediğin amaçtan epeyce uzaklaşmanı sağlar. Çözüm kesme kullanmakta elbet.
Bunun için en kısa bekleme süresini esas alıp o kadarlık sürede bir kesme oluşturmakta. Süre kesme için uzun ise onu en azından ikiye veya 4 e bölerek işi yapmak gerekir.
Örnek vereyim. Her 500us de bir kesme oluşturduğunu varsayarsak;
Led1 için her iki kesmede bir led konum değiştirmelidir.
Led2 için her 4 kesmede bir led konum değiştirmelidir.
Led3 için her 6 kesmede bir led konum değiştirmelidir.
Kesme kısmında bunu yapmak çok kolay.
Kesme oluştuğunda IF LED1 aktif ise (yani ona ait butona basılmış ise)
SAY1=SAY1+1
IF SAY1=2 then
SAY1=0:Led1=1-LED1
ENDIF
Şeklinde iş kolaylıkla halledilebilir.

Ete

veli dayı

Led1=1-LED1   Hocam bu komut toggle led1=0 gibi bir şeymi.şayet öyle değilse ne işe yarıyor.bu kmutu ilk defa gördüm de kusura kalmayın.

ete

Led1=1-LED1
Açıklaması kendi üzerinde olan bir komut bu. Toggle Led1 komutunun yaptığı işi yapar.
Başlangıçta Led1=0 dır. Eşitlikte yerine koyarsak,
Led1=1-0=1 böylece led1=1 olur.
İkinci defa aynı komut çalışırsa;
Led1=1-1=0 olur. Yani led1 değeri her seferinde konum değiştirir.

Ete

veli dayı

teşekkür ederim.sayenizde yeni bir komut daha öğrendim.elinize sağlık

mierdogan

#9
Hocam birşeyler parçaladım ama eksik olduğu aşikar :)

-Mesela SAY1 dediğimiz sayacı nasıl 250 ms' e nasıl kuruyoruz?
-B portundaki çıkışları nasıl tanımlıyoruz gibi sorular dönüyor aklımda...
-Ben eski programa dahil etmeye çalıştım ama sanırım olmadı
-Kart üzerinde sadece Led3 salak saçma yanıyor dzüenli değil...

Kod aşağıdaki gibidir


'****************************************************************
'*  Name    : LEDDING.BAS                                       *
'*  Author  : M.Erdogan                                         *
'*  Notice  : Copyright (c) 2012 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 20.04.2012                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
CMCON=7
ADCON1=7
TRISB=0
TRISA=%00111111
PORTB=0

SAY1    VAR WORD
Led1    var PORTB.0
Led2    var PORTB.1
Led3    var PORTB.2

SAY1=250
   
IF PORTA.0=0 THEN GOSUB KESME
IF PORTA.1=0 THEN GOSUB KESMEE
IF PORTA.2=0 THEN GOSUB KESMEEE

KESME:
SAY1=SAY1+1
IF SAY1=4 then
    SAY1=0:Led1=1-LED1
ENDIF
return

KESMEE:
SAY1=SAY1+1
IF SAY1=8 THEN
    SAY1=0:Led2=1-Led2
endif
return

KESMEEE:
SAY1=SAy1+1
IF SAY1=12 THEN
    SAY1=0:Led3=1-Led3
ENDIF
RETURN



Saygılar....
"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

ete

İşlemci içinde yer alan ve geri planda çalışan zamanlayıcıların ayarlanması son derece basittir.
TMR0 zamanlayıcısı 8 bitliktir. Bu şu demek zamanlayıcı sıfırdan başlar işlemcinin her clk palsinde oda bir sayar ve sonuçta 255 değerine gelir. Saymaya devam eder ve 255 den tekrar sıfıra otomatik döner ve saymasına devam eder. 255 den sıfıra dönerken kesme oluşturur. TMR0 kesmesini aktif edersen bu kesmeyi yakalayabilirsin. BU zamanlayıcının blücüleri vardır.
Bölme oranını 1/1 alırsan işlemcinin clk palsi ile birebir sayar. Bölme oranını 1/2 alırsan her iki clk palsinde zamanlayıcı bir sayar.
Bölme oranları 1/256 ya kadar uzanabilir.
TMR1 zamanlayıcısı 16 bitliktir. 65535'e kadar sayar ve sonra yeniden sıfıra döner. Bu esnada oda bir kesme oluşturabilir.
TMR1 kesmesini aktif edersen o kesmeyide yakalayabilirsin. TMR1 in de bölücüleri vardır. Maksimum 1/8 olarak kullanabilirsin.

Bu kadar bilgiden sonra gelelim senin 250 ms lik kesme oluşturma süresi hesabına.
250 ms 250.000 us eder. TMR0 açısından düşünürsek bu çok yüksek bir değer. Buna bölme tatbik edersek;
- 2 ye bölersek 125.000 hala büyük bir değer
- 4 e bölersek 62.500 değeri elde edilirki 8 bit için hala yüksek bir değer
- 8 e bölersek  31.250 değerini elde edeirz hala yüksek bir değer.
- 256 ya bölersek bile hala yüksek bir değer olan  976,5 değerini elde ederiz.
Peki ne yapmalıyız.  en güzeli 16 ya bölerek 15626 sayısını elde ederiz. Bu bize yaklaşık her 15625 us de (yaklaşık 15,6ms) bir kesme oluşturma imkanı sağlar. 250/15,6 =16 olduğuna göre oluşan kesmeleri sayarız ve her 16 sayaçta bir 250 ms lik gecikme elde etmiş oluruz.
Ama 8 bitlik zamanlayıcı yerine 16 bitlik TMR1 zamanlayıcısını kullanırsak işimiz biraz daha kolay olur. Zira 250000/4=62500 dür. O halde ben TMR1 sayacını her seferinde 62500 saydırırsam ve sayılanı 4 e bölersem tam oalrak 250.000 us lik bir gecikme sağlamış olurum. Yapılacak iş, TMR1 sayacını sııfrdan değilde ön yükleme değeri olarak 65536-62500= 3036 değeri ile saydırmaya başlatatıp bölme oranınıda 1/4 olarak ayarladımmı her 250 ms de bir kesme oluşturabilirim.
İşte gereken komutlar;
INTCON=%11000000 Burada 7 nolu bit genel kesmeleri aktif eder. Bit 6 ise yardımcı kesmelerin yolunu açar. (TMR1 bunlardan birisidir)

T1CON=%00100001  Bu registerin 5-4 nolu bitleri bölme oranını ayarlar. 00=1/1, 01=1/2 , 10=1/4 , 11=1/8 bölme oranını verir.

PIE1 registerinin sıfır nolu biti TMR1 taşma kesmesini aktif eder.  O halde komut PIE1.0=1 şeklinde olacaktır.
TMR1 sayacımız  3036 dan başlayarak sayacağı için TMR1 sayacına bu değeri yüklememiz gerekiyor.
Maalesef TMR1 sayacı 16 bitlik olmasına rağmen direk ulaşılabilir değildir. Ancak TMR1L (yani Low byte) ve TMR1H (yani High Byte) registerleri yardımı ile bu iş yapılabilmektedir. Şimdi öncelikle 3036 sayısını Lowbyte ve Highbyte bileşenlerine ayırmamız gerekecek. TMR1H=3036/256  ,  TMR1L=3036-(TMR1H*256) şeklinde bunu yapabiliriz.
Sonuçta TMR1H=11 ve TMR1L=220 şeklinde bu değerleri TMR1 registerlerine verebiliriz.
Buraya kadar olan komutlar kesmeyi aktive eder. Ancak kesme oluşunca program hangi etikete gidecek ise onuda ;
ON INTERRUPT GOTO KESME    şeklinde belirleriz.

Şimdi KESME etiketinde ne yapılacak onları açıklayalım.
Önce kesme etiketine gelindeiğinde yeniden kesme oluşmasını önlemek için
DISABLE   şeklinde bir komutla başlamalıyız. Ardından etiket adını yazabiliriz.  Buda
KESME:    şeklinde yapılır.
Şimdi kesme oluştuğu zaman neler yapacağız onları yazmamız gerekiyor.
Bunu yapmadan önce programımızı biraz düzenlememiz lazım. Ne yapacağız, ilgili led butonlarına basıldığı zaman ledleri aktive etmek gerekiyor. Bunlar için birer bit değişkeni kullanacağız. Yapmamız gereken yalnızca ledleri aktive etmek yada etmemek. olmalı geri kalan iş zaten kesme kısmına otomatik icra edilecektir.
Önce her led için birer aktivasyon değişkeni tanımlayalım.
AKTIF1 VAR BIT 'bu Led1 in aktivasyon değişkeni
AKTIF2 VAR BIT 'bu Led2 nin aktivasyon değişkeni
AKTIF3 VAR BIT 'buda Led3 ün aktivasyon değişkeni.

Programda ilgili butonlara basılınca bunları aktive edecek bir sistem geliştirmeliyiz.
Butona bir kere basılınca led aktif olacak bırakıp yeniden basınca led aktivasyonu kaldırılmış olacaktır. Bunu toggle komutu ile yapabiliriz. Örnek olarak ;
IF PORTA.0=0 THEN TOGGLE AKTIF1 şeklinde bir komut bu işi rahatlıkla yapacaktır.
IF PORTA.1=0 THEN TOGGLE AKTIF2
IF PORTA.2=0 THEN TOGGLE AKTIF3 şeklinde bu işi bitirmiş oluruz.
WHILE PORTA.0=0 OR PORTA.1=0 OR PORTA.2=0:WEND   'bu komut ilede tuşlar bırakılıncaya kadar programı orada bekletiriz.
Şimdi bunları programımıza tatbik edelim ve kesme kısmınıda orada halledelim.

'-----------------------------------------------------------------
@ DEVICE PIC16F877                                                   
@ DEVICE PIC16F877, WDT_OFF             
@ DEVICE PIC16F877, PWRT_OFF           
@ DEVICE PIC16F877, PROTECT_OFF       
@ DEVICE PIC16F877, XT_OSC             
'-----------------------------------------------------------------
DEFINE OSC 4  'kristalimiz 4 Mhz

CMCON=7
ADCON1=7
TRISB=0
TRISA=%00111111
PORTB=0

SAY1   VAR  WORD
SAY1   VAR  BYTE
SAY2   VAR  BYTE
SAY3   VAR  BYTE
AKTIF1 VAR BIT
AKTIF2 VAR BIT
AKTIF3 VAR BIT
SYMBOL LED1=PORTB.0
SYMBOL LED2=PORTB.1
SYMBOL LED3=PORTB.2
SYMBOL TUS1=PORTA.0
SYMBOL TUS2=PORTA1
SYMBOL TUS3=PORTA.2

CLEAR
PAUSE 200  'programın açılış gecikmesi bu gereklidir.

INTCON=%11000000
T1CON=%00100001
PIE1.0=1
TMR1H=11 ve TMR1L=220

ON INTERRUPT GOTO KESME

BASLA:

IF  TUS1=0 THEN 
   TOGGLE AKTIF1
   LED1=AKTIF1
ENDIF

IF  TUS2=0 THEN
   TOGGLE AKTIF2
   LED2=AKTIF2
ENDIF


IF  TUS3=0 THEN
   TOGGLE AKTIF3
   LED3=AKTIF3
ENDIF

WHILE TUS1=0 OR  TUS2=0 OR TUS3=0:WEND
GOTO BASLA

DISABLE
KESME:
IF AKTIF1=1 THEN
    SAY1=SAY1+1
    IF SAY1=2 THEN
        SAY1=0
        TOGGLE  LED1
    ENDIF
ENDIF

IF AKTIF2=1 THEN   
  SAY2=SAY2+1
    IF SAY2=4 THEN
        SAY2=0
        TOGGLE  LED2
    ENDIF
ENDIF

IF AKTIF3=1 THEN   
  SAY3=SAY3+1
    IF SAY3=6 THEN
        SAY3=0
        TOGGLE  LED3
    ENDIF
ENDIF
PIR1.0=0  ' buda TMR1 kesme bayrağıdır. Çıkmadan önce sıfırlanması gerekiyor.
TMR1H=11:TMR1L=220  'tekrar Timer1'e ön yükleme değerini veriyoruz
    PIR1.0=0 'kesme bayrağını sıfırlıyoruz
    Resume  'geldiğimiz yere geri dönüyoruz
    enable  'kesmeleri yeniden aktive ediyoruz.


Hepsi bu kadar . Bem denemedim . Sen bir dene bakalım. Epeyce detaylı yazdım.
Aslında bu konulara derslerde yer vermiştim. Dersleri takip edersen her şeyi oradan öğrenebilirsin.
Sonucu buraya yazarsın umarım.

Ete

mierdogan

derledim fakat bir iki problem çıktı ki klavye basmadığı için yapılabilecek hatalar bunlar...

Bende deneyemedim çünkü laptop' un fişinin ucu(metal bacak) yani prize giren yer her nasılsa dibinden kopmuş durumda... Ucunu kesip yeni fiş takmalıyım... yarına kadar beklemem gerekecek yada bu bilgisayara proteus yükleyip gözlemleyeceğim fakat gerçek bir sonuç olmayacak...

ayrıca bu konu bana göre biraz karmaşık(bi önceki yazdığım kodla karşılaştırırsak :) ) daha doğrusu bilmediğim şeyler var biraz incelemek istiyorum
Yarına tekrar yazarım hocam

Saygılar
"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

mierdogan

Merhaba,

programı denedim çalışıyor fakat küçük minik bir eksik var sanırım. yada bana ben öyle görmek istedim.

Örneğin:
1. butona basınca 1. led yanıp sönmeye başlıyor buraya kadar tamam fakat 2. butona basınca 2. led de yanıp sönmeye başlıyor ve 1. led sönük kalmıyor.. bunu nasıl aşarım acaba toggle komutlarının üzerine portb=0 komutu yazdım ama olmadı? portb yi sıfırlarsam problemin istediğime kısa yoldan ulaşırım diye düşündüm.

Saygılar

"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

mierdogan

ETE Hocam kodu aşağıdaki gibi yaptım ama bence yanlış oldu çünkü uygulamada low durumuna gelen led tamamen sönmüyor çok az miktarda parlaklık ile yanıp sönmeye devam ediyor.

Kod üzerinde aktif olan led'i bir diğer butona basınca pasif hale nasıl getirebiliriz? yani sadece tek led yanıp sönecek?

Beni düşüncem subrutin olarak ele alsak olacak gibi ne dersiniz?

Saygılar

'****************************************************************
'*  Name    : UNTITLED.BAS                                      *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2012 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 24.04.2012                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
'-----------------------------------------------------------------
@ DEVICE PIC16F877A                                                   
@ DEVICE PIC16F877A, WDT_OFF             
@ DEVICE PIC16F877A, PWRT_OFF           
@ DEVICE PIC16F877A, PROTECT_OFF       
@ DEVICE PIC16F877A, XT_OSC             
'-----------------------------------------------------------------
DEFINE OSC 4  'kristalimiz 4 Mhz

CMCON=7
ADCON1=7
TRISB=0
TRISA=%00111111
PORTB=0

SAY1   VAR  WORD
'SAY1   VAR  BYTE
SAY2   VAR  BYTE
SAY3   VAR  BYTE
SAY4    VAR BYTE
AKTIF1 VAR BIT
AKTIF2 VAR BIT
AKTIF3 VAR BIT
AKTIF4 VAR BIT
SYMBOL LED1=PORTB.0
SYMBOL LED2=PORTB.1
SYMBOL LED3=PORTB.2
SYMBOL LED4=PORTB.3
SYMBOL TUS1=PORTA.0
SYMBOL TUS2=PORTA.1
SYMBOL TUS3=PORTA.2
SYMBOL TUS4=PORTA.3

CLEAR
PAUSE 200  'programın açılış gecikmesi bu gereklidir.

INTCON=%11000000
T1CON=%00100001
PIE1.0=1
TMR1H=11 and TMR1L=220

ON INTERRUPT GOTO KESME

BASLA:

IF  TUS1=0 THEN
       TOGGLE AKTIF1
   LED1=AKTIF1
ENDIF

IF  TUS2=0 THEN
      TOGGLE AKTIF2
   LED2=AKTIF2
ENDIF


IF  TUS3=0 THEN
       TOGGLE AKTIF3
    LED3=AKTIF3
ENDIF

IF  TUS4=0 THEN
    TOGGLE AKTIF4
    LED3=AKTIF3
ENDIF

WHILE TUS1=0 OR  TUS2=0 OR TUS3=0 OR TUS4=0:WEND
GOTO BASLA

DISABLE
KESME:
IF AKTIF1=1 THEN
    LOW PORTB.1 AND PORTB.2 AND PORTB.3
      SAY1=SAY1+1
        IF SAY1=2 THEN
            SAY1=0
        TOGGLE  LED1
    ENDIF
ENDIF

IF AKTIF2=1 THEN   
    LOW PORTB.0 AND PORTB.2 AND PORTB.3
      SAY2=SAY2+1
        IF SAY2=4 THEN
            SAY2=0
        TOGGLE  LED2
    ENDIF
ENDIF

IF AKTIF3=1 THEN
    LOW PORTB.0 AND PORTB.1 AND PORTB.3   
      SAY3=SAY3+1
        IF SAY3=6 THEN
            SAY3=0
        TOGGLE  LED3
    ENDIF
ENDIF

IF AKTIF4=1 THEN
    LOW PORTB.0 AND PORTB.1 AND PORTB.2   
      SAY4=SAY4+1
        IF SAY4=8 THEN
            SAY4=0
        TOGGLE  LED4
    ENDIF   
ENDIF
PIR1.0=0  ' buda TMR1 kesme bayrağıdır. Çıkmadan önce sıfırlanması gerekiyor.
TMR1H=11:TMR1L=220  'tekrar Timer1'e ön yükleme değerini veriyoruz
    PIR1.0=0 'kesme bayrağını sıfırlıyoruz
    Resume  'geldiğimiz yere geri dönüyoruz
    enable  'kesmeleri yeniden aktive ediyoruz.

"Doğal bir esin arzulu bir isteğe dönüştüğünde, insan hedefine dev adımlarla ulaşır..."

ete

#14
Ledlerin tamamen sönmemesi program veya devredeki hatadan kaynaklanıyor.
Ben aşağıdaki programı Simulasyonda denedim. Sorunsuz çalışıyor.

Devrede yapman gereken kontrollar şunlar.
1. OSC bacaklarına 4 Mhz kristal bağlımıdır.
2. Kirstal bacakları ile GND arasında 22pf kondansatör bağlımıdır.
3. MCLR pinine 4K7 lik bir direnç ile PULLUP yapılmışmıdır?
5. Besleme bacaklarınada tam olarak 5V okunuyormudur.

Bunları yaptıktan sonra aşağıdaki programı denemeni isterim. Zira senin programında TMR1 sayacını her 500 ms de kesme yaratacak şekilde ayarlamamışsın. Timer'a verdiğin değerler doğru ancak bölme oranını 1/4 yapmışsınki bu kesme süresini kısaltmaktadır.  Aşağıdaki programda kesme süresi tam 500 ms olup 1 nolu led her 1 sn de bir , 2 nolu led her 2 sn de bir , 3 nolu led her 3 sn de bir ve 4 nolu led ise her 4 sn de bir yanıp sönmektedir. Süreleri kısaltmak istersen T1CON registeri 4 ve 5. bitlerinde yer alan değerleri değiştirmen gerekir. 00 yaparsan her 64ms de bir kesme oluşur, 01 yaparsan her 125 ms de bir kesme oluşur, 10 yaparsan her 250 ms de bir kesme oluşur 11 yaparsan her 500 ms debir kesme oluşur.
Bu arada karışıklık olmasın diye tuş isimlerini, ve ona bağlı değişken isimlerini değiştirdim.
Ete

'-----------------------------------------------------------------
@ DEVICE PIC16F877A                                                   
@ DEVICE PIC16F877A, WDT_OFF             
@ DEVICE PIC16F877A, PWRT_OFF           
@ DEVICE PIC16F877A, PROTECT_OFF       
@ DEVICE PIC16F877A, XT_OSC             
'-----------------------------------------------------------------
DEFINE OSC 4  'kristalimiz 4 Mhz

CMCON=7
ADCON1=7
TRISB=0
TRISA=%00111111
PORTB=0

SAY0  VAR byte 56
SAY1  VAR BYTE 57
SAY2  VAR BYTE 58
SAY3  VAR BYTE 59
ARA   VAR byte 60
symbol AKTIF0=ARA.0
SYMBOL AKTIF1=ARA.1
SYMBOL AKTIF2=ARA.2
SYMBOL AKTIF3=ARA.3

SYMBOL LED0=PORTB.0
SYMBOL LED1=PORTB.1
SYMBOL LED2=PORTB.2
SYMBOL LED3=PORTB.3
SYMBOL TUS0=PORTA.0
SYMBOL TUS1=PORTA.1
SYMBOL TUS2=PORTA.2
SYMBOL TUS3=PORTA.3

CLEAR
PAUSE 200  'programın açılış gecikmesi bu gereklidir.

INTCON=%11000000
T1CON=%00110001   '54 bitler, 00=1/1  , 01=1/2  , 10=1/4   11=1/8
PIE1.0=1
TMR1H=11 and TMR1L=220

ON INTERRUPT GOTO KESME

BASLA: 
        IF  TUS0=0 THEN
           TOGGLE AKTIF0           
           IF AKTIF0=1 THEN ARA=1:PORTB=0
           LED0=AKTIF0               
           WHILE tus0=0:wend           
        ENDIF
       
        IF  TUS1=0 THEN
           TOGGLE AKTIF1           
           IF AKTIF1=1 THEN ARA=2:PORTB=0
           LED1=AKTIF1
           while tus1=0:wend
        ENDIF
       
        IF  TUS2=0 THEN
            TOGGLE AKTIF2           
            IF AKTIF2=1 then ARA=4:PORTB=0
            LED2=AKTIF2
            WHILE tus2=0:wend
        ENDIF
       
        IF  TUS3=0 THEN
            TOGGLE AKTIF3
            IF AKTIF3=1 then ARA=8:PORTB=0
            LED3=AKTIF3
            WHILE TUS3=0:wend
        ENDIF
       
        GOTO BASLA

DISABLE
KESME:
IF AKTIF0=1 THEN
      SAY0=SAY0+1
        IF SAY0=2 THEN
            SAY0=0
        TOGGLE LED0
    ENDIF
ENDIF

IF AKTIF1=1 THEN   
      SAY1=SAY1+1
        IF SAY1=4 THEN
            SAY1=0
        TOGGLE  LED1
    ENDIF
ENDIF

IF AKTIF2=1 THEN
      SAY2=SAY2+1
        IF SAY2=6 THEN
            SAY2=0
        TOGGLE LED2
    ENDIF
ENDIF

IF AKTIF3=1 THEN
      SAY3=SAY3+1
        IF SAY3=8 THEN
            SAY3=0
        TOGGLE LED3
    ENDIF   
ENDIF
PIR1.0=0  ' buda TMR1 kesme bayrağıdır. Çıkmadan önce sıfırlanması gerekiyor.
TMR1H=11:TMR1L=220  'tekrar Timer1'e ön yükleme değerini veriyoruz her 500 ms de birkesme
Resume  'geldiğimiz yere geri dönüyoruz
enable  'kesmeleri yeniden aktive ediyoruz.
END

Powered by EzPortal