Birden Fazla Kesme Kullanımı

Başlatan pic_acemisi, 09 Şubat 2019, 00:20:48

pic_acemisi

Öncelikle Merhabalar,

Adımdan da anlaşılacağı gibi kendini geliştirmeye çalışan bir öğrenciyim. Pogramda verileri alma kısmını tamamladım ama ana çalışma kısmında mantığını kuramadım. Çözüm değil fikir, yol arıyorum.

18f4520 kullanıyorum ve lcd ile aşağıdaki değişkenleri 0-9999 arası değer girip eproma kaydediyorum ve okuyorum.
örneğin; girisdegeri1, girisdegeri2, girisdegeri3, cikisdegeri1, cikisdegeri2, cikisdegeri3 , giriszamani1, giriszamani2, giriszamani3 gibi.

PORTB.2 de fotoselim bulunmakta.
PORTB.3 'te motordan gelen puls bilgisi bulunmakta kare dalga şeklinde

bu pinler kesme pinleri olduğundan bunları seçtim.

Programın Çalışma Mantıığı Şu Şekilde :

Fotosel önü kapandığında girisdegeri1 kadar motordan puls sayacak eşitlenince bir pini high yapacak giriszamani1 'in değeri kadar ms cinsinden aktif olup sonrasında kapanacak. girisdeger2 ve 3 de bunun gibi ama bağımsız farklı değerlerde çalışabilmeli.

Fotoselin önü açılıdığında ise yukarısının aynısı cikis değişkenleri için çalışacak.

Şimdi bu mantığı nasıl kurmalıyım. Ana döngüde mi yoksa 1us lik  bir timer kurup sürekli onun içinde mi yapmalı ?  Her türlü fikre açığım... :)




ete

Açıklaman bana göre yetersiz.
Olaya tek açıdan bakıldığında bir fotosel girişin var ve bu kapandığında GIRIS_DEG_1 içeriği kadar motordan gelecek puls adedini sayacak ve değer ile puls değeri eşitlendiğinde  bir pini HIGH yapacak. HIGH olma süresi zaman-1 kadar olacak ve süre sonunda kapanacak.
Buraya kadar hiç sorun yok kolaylıkla yapılabilir. Eksik olan kısım girişdeğeri -3 gibi diğer farklı değerlerle de çalışabilmeli demişsin. Sürekli aynı puls sayıcısındanmı bahsediyoruz yoksa farklı girişler farklı değerlerlemi çalışacak burası pek açık değil.
Şöyle söylese idin daha kolay anlayabilirdim. Giriş değeri iki tuş yardımı ile değiştirilebilir olacak. BU durumda 3. cü bir tuş da koyulmalı set etmek için. Artır ve azalt seçer Seç tuşu ise onu set eder. Böylece sistem seçilen değere göre çalışır.
Bu tür sistemlerde sıklıkla kullandığım bir algoritma vardır. Şöyle düşünürüm.
Sabit bir zaman diliminde (mesela 100ms veya 250 ms veya 500 ms) çalışan bir timer-1 rutinim olsa.
Bu dilim içinde bir yandan puls sayarken bir yandan da zamana bağlı işlerin kontrolünü yapabilirim.
Senin olayında işin iki safhası var. Birinci safhada zamana bağlı hiç bir işlem olmadığı için yalnızca Puls sayarım. Puls eşitlenince ikinci safhaya geçerim.
İkinci safhada ise zaman bağlı işlerin kontrolünü yaparım. Standart bir zaman dilimi alırım ve bu dilim içinde rutin işleri (tuş kontrolü ve diğer benzeri işler) yaparım. dilim süresi bittiğinde dilimsayacını artırırım değer takip ettiğim zamanlardan birine eşitlenince ona ait kodu çalıştırırım. Burayı senin örnekle açıklamak daha uygun olacak sanırım.
Zaman fazında bir pini high yapacağım ve diyelimki 2 sn (2000 ms) süre ile HIGH da tutup sonra LOW yapacağım ve  sonra fazdan çıkacağım. Zaman dilimini 100ms de alabilirim (biraz işlemcinin çalışma frekansına da bağlı bu değer) 250 ms de alabilirim 500 ms de alabilirim. Diyelimki 100 ms aldım. KESME adedim 2000/100=20 olacaktır.
Timer-1 sayacını 100 ms için kurarım. PIR1.0 registeri Timer-1 sayacının kesme bayrağıdır. Global kesmeleri aktive etmeden yalnızca bu bayrağa bakarak işimi görebilirim.
Öncelikle Çıkışı HIGH yaparım ve aşağdaki satırlardan devam ederim
YENIDEN: PIR1.0:TMRL=xxxx:TMR1H=xxxx 'bayrak sıfırlandı ve TMR1 sayacına ön yükleme değeri verildi
WHILE PIR1.0=0
  Gosub Tusbak 'başka işlerek bakıyorm bu arada sürem 100 ms
Wend
KESME=KESME-1:IF KESME>0 then YENIDEN 'her bir dilim 100 ms nin geçtiğini gösteriyor
'program bu noktaya geldiğinde 2000 ms geçmiş olacaktır.
CIKIS=0 şeklinde çıkışı LOW yapıp fazı sonlandırırım.

İşin detayında puls değeri seçimi kalıyorki bunuda işe başlamadan önce yapmak ve işlem başlangıcını SEC tuşuna başlatarak yapmak en akıllıcası olur diye düşünüyorum.

Umarım ne demek istediğimi anlamışsındır.
Ben olsam Puls girişin INT0 (PORTB.0) pininden yapar ve bunuda Global kesmeye bağlayarak puls sayımını kesme içinde yapardım. Puls eşitliğini ise ana program bölümünde yapardım. Böylece puls kaçırma ihtimalin sıfıra iner.

Ete

pic_acemisi

#2
Hocam cevabınız için teşekkür ederim .

giriş değerleri isimli değişkenler butonlar ile farklı değerleri girilebiliyor. Puls kaynağım tek aynı motordan geliyor pulsler.
İşlemci 18f4520 oldugunda sayici porbt2 de yani kesme bacağında bağlı. Global kesme ile pulsleri saymayı düşünüyorum. Ama pinlerin acik kalma surelerini nasil yapacagimiz bilemedim yani birden fazla cikis olmasi durumunda birbirlerini beklememeleri gerekiyor. O zaman puls sayma isini kesme icerisinde yapip ana dongude esitlik sorgulayip. Timer in icinde mi cikis surelerini kontrol etmeliyim ? Birde timer0 mi timer 1 i mi kullanmaliyim

ete

Bu iş için en uygunu Timer1 sayacı. Tam da tarif ettiğin gibi,
puls saymayı kesme içinde, yapabilirsin.
Sistemini iki faza ayırmıştım. Birinci fazda zamanla işin yok sanırım. Bu nedenle orada yalnızca kesme içinde saydığın puls eşitliğini kontrıol edersin. Eşitlik sağlandıktan sonra bu sefer zaman eşitliğinee bakman gerekecek onuda ikinci fazda Timeer1 sayacını dediğim şekilde kullanarak yapacaksın.
İşin detayını fazla bilmediğim için bu şekilde söylüyorum ama sürekli olarak puls sayacak isen aynı zamanda eşitlik kontrolu ve zaman kontrolüde yapacak isen bütün iş tek fazda yapılabilir.
Timer1 sayacını 250 ms lik dilimler halinde çalıştırır ve her 250 ms lik dilim içinde puls eşitliğini kontrol eder, ve aynı zamanda tuşları kontrol edersin. Zaman eşitliği için sayılacak zaman var ise onu aktif eden bir bit değişkeni kullanmak akıllıca olur. Örneğin SAYAC isimli bir değişkenin olsa, Bunun sıfır biti birinci sayılacak zamanını aktive etse, 1 nolu biti ikinci zamanı aktive etse  bu şekilde 8 farklı zamanı aynı timer1 dilimi içinde kontrol edersin. Dilim süresi tamamen kontrol edeceğin zamana bağlı ister 100 ms lik ister 250 ms lik ister 500 ms lik dilimler kullanırsın.
Dilim sonunda ise IF SAYAC.0=1 THEN ZAMAN1=ZAMAN1+1 şeklinde işlem yaptırabilirsin. Böylece kim aktif ise onun zamanı sayar. Burada dikkat edeceğin şey süre hesabında kaç zaman dilimi kullanılacağıdır. Örneğin 2000 ms sayacak isen ve dilim süren 250 ms ise 8 tane dilim sayman gerekir. 100 ms lik dilimle çalışıyor isen 20 tane dilim sayman gerekir. Böylece tek bir dilim sayacından bütün zamanlayıcıların çalışır. Hemde hepsi aynı anda syamış olur üstelik arada diğer işlerinide yapmış olursun.
Süresi bitenide dilim sonundaki artırma eksiltme işlemleri sırasında kontrol edersin olur biter.

Ete

pic_acemisi

Hocam, timer1 üzerinden uygulamaya çalışıyorum. Konu dışı ama şöyle bir durum oldu 18f4520 kullanıyordum piyasada ondan daha ucuz ama daha fonksiyonlu 18f45k22' ye geçmeye karar verdim.



TRISA=0
TRISB=%00011110
TRISC=0
TRISD=0
TRISE=0
PORTA=0
PORTC=%00110000
PORTD=%00001000
PORTE=0
ADCON0.0=0
ADCON1=%00001111
CMCON=7
RCON.7=1   
INTCON= %10101000
INTCON2=%00100101
INTCON3=%11011000
T0CON=%10001000
TMR0H=236
TMR0L=120


18f4520 bu sigorta ayarları ile çalışyordu. 45k22 de doğal olarak çalışmadı. Datasheet'e bakınca çok fazla adc kanalı olduğunu gördüm bunlarıda dijital yapmak için bunların yanına birde aşağıdakilerini ekledim. Fakat gene çalışmadı. Neyi eksik yapıyorum acaba ?

PMD2=%00001111
ANSELB=%00000000
ANSELC=%00000000
ANSELD=%00000000
ANSELA=%00000000
ANSELE=%00000000


Bu arada sigorta ayarlarım aşağıda. Kristalim 20mhz.

   
    __CONFIG    _CONFIG1H, _FOSC_HSHP_1H & _PLLCFG_OFF_1H & _PRICLKEN_ON_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
__CONFIG    _CONFIG2L, _PWRTEN_ON_2L & _BOREN_OFF_2L & _BORV_285_2L
__CONFIG    _CONFIG2H, _WDTEN_OFF_2H & _WDTPS_32_2H       
__CONFIG    _CONFIG3H, _CCP2MX_PORTC1_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTC0_3H & _P2BMX_PORTC0_3H & _MCLRE_INTMCLR_3H
        __CONFIG    _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
__CONFIG    _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L       
__CONFIG    _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
__CONFIG    _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L
__CONFIG    _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
__CONFIG    _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L
__CONFIG    _CONFIG7H, _EBTRB_OFF_7H


ete

Genel anlamda tüm pinleri digital yapmak için öncelikle ANSEL registerlerini sıfırlaman ve Komparatör işlevinide iptal etmen gerekir.
18F45K22 de komparatör iptal;
CM1CON0=0
CM2CON0=0
komutları ile sağlanıyor. Ayrıca bu işlemcide örnek sigorta ayarı aşağıdaki şekilde olabilir.
'işlemci 18F45K22
#CONFIG
  __CONFIG _CONFIG1H, _HS_OSC & _PLLCFG_OFF_1H & _PRICLKEN_OFF_1H & _FCMEN_OFF_1H & _IESO_OFF_1H       
  __CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_OFF_2L & _BORV_285_2L
  __CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDTPS_64_2H                                                                                     
;  __CONFIG _CONFIG3H, _CCP2MX_PORTB3_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_INTMCLR_3H
  __CONFIG _CONFIG3H, _PBADEN_OFF_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_INTMCLR_3H
  __CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
  __CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L   
  __CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_ON_5H
  __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_ON_6L
  __CONFIG _CONFIG6H, _WRTC_ON_6H & _WRTB_ON_6H & _WRTD_OFF_6H ; epromun yazma koruması WRTD dir OFF olmalı
  __CONFIG _CONFIG7L, _EBTR0_ON_7L & _EBTR1_ON_7L
  __CONFIG _CONFIG7H, _EBTRB_ON_7H
#ENDCONFIG


Ete

pic_acemisi

Önerdiğiniz sigorta ayarları ile mcs derleme esnasında

Error[113] c\pbp\18f45k22.inc 33: Symbol not previously defined (_HS_OSC)  hatası veriyor.

Size paylaştığım sigorta ayarları c\pbp içerisinde bulunan 18f45k22.inc dosyasında idi. Yani programın başında ekli değiller. Paylaştıklarımı da MPASM'nin içinde p18f45k22 dosyasından almış idim.

Comparator ile ilgili olanları ekledim ama 18f4520 de çalışan program bu entegre ile çalışmıyor. Program da portb 1,2 ve portb.4 değişiklik kesmelerini kullanıyorum ama bu işlemcide çalışmıyorlar. PortD de lcd bulunmakta o normal bir şekilde çalışıyor. İlginç bir durum oldu

ete

Yeni nesillerde pek kristal kullanmıyorum artık. 4-8-16-32 Mhz dahili OSC seçeneklerinden birini kullanıyorum. Bu nedenle sigorta ayarlarında HS osc diye bir şey yokmuş şimdi MPASM içindeki INC dosyasına baktım orada şöyle kullanılmış,
_FOSC_HSHP_1H        EQU  H'F2'    ; HS oscillator (high power > 16 MHz)
yani _HS_OSC yi silip yerine _FOSC_HSHP_1H   yazman derleme hatasını kaldıracaktır.

PortB değişiklik kesmesinin çalışması için Bu işlemcide Ayrıca IOCB registerinde ilgili giriş pinlerine denk gelen bitleri HIGH yapman gerekir.
Yani diyelimki PORTB.4 ve PORTB.5 pininden kesme oluşturacaksın. IOCB.4=1 ve IOCB.5=1 komutlarınıda eklemen gerekiyor.
INT0 (PORTB.0) kesmesi INTCON registeri 4. nolu bit ile aktif ediliyor burda sorun olmaması gerek. INT2 yani PORTB.1 kesmesi ise INTCON3 registeri 4 nolu biti ile set ediliyor.
Geriyede başka sorun kalmıyor olması gerekir.
Aslında biraz data sheet inceleme alışkanlığı edinsen herşey orada yazıyor bende oradan bakıp uyguluyorum sende yapabilirsin.

Ete

Powered by EzPortal