Pic kontrolör kullanarak, pcb üzerindeki; 6 adet tact buton ve 4 digit seven segment display ile, bir menü programı yapmam gerekiyor.
Programda çeşitli değişkenlerin içeriğini (10 adet int tipinde değişken var.), butonlarla displayden görerek, değiştirmem-ayarlamam gerekiyor.
4 digit displeyi, timeri ayarlayarak, timer kesmesi aracılığıyla, tarama şeklinde digit-digit sürekli sürmeyi planlıyorum.
Butonları 2 şekilde okuyabilirim;
1-) main() içindeki while() döngüsü içerisinde, normal port girişleri olarak algılayıp-okumak. (kesmesiz olarak butonları okuma.)
2-) CN Giriş Pin Interrupt-Kesmesi ile; Giriş pinlerini bir kesme ile, main() dışında bir kesme fonksiyonunu içinde okuyup işlemleri, kesme içinde yapmak. (kesme içinde butonları işlemek.)
Buton girişlerini okumak için, hangisini kullanmalıyım. Bu türden bir işte hangi yöntemi kullanmak gerekir. Kısaca butonlar kesme ilemi, yoksa normal olarak mı okunup-değerlendirilse iyi oluyor.
https://www.sifirzero.com/2023/03/seven-segment-display-tarama-yontemi.html (https://www.sifirzero.com/2023/03/seven-segment-display-tarama-yontemi.html)
Güzel uygulama yapmışsınız. Bu türden bir çalışma yapmak için, bundan kısa ve öz olanı da pek mümkün olmaz herhalde.
Herşey tıkır tıkır yerinde okunaklı ve sade olmuş.
Yalnız ben display sürmeyi sormamıştım.! Pcb mi kısaca özetleyerek,
Butonları nasıl okumalıyım, buton kodlarını nereye yazmalıyım diye sormuştum.!
Butonlar kesmeli ve kesmesiz okunup değerlendirilebiliyor. Hangisini yapmak gerekir demek istemiştim.
Bouncing (zıplama?) problemi olduğu için normalde butonları kesmeye bağlamak iyi bir fikir değil. Bence bu konudaki en doğru yöntem bir timer kesmesi içinde butonları hızlıca okuyup sonra da butonun değerine karar vermek için bu okumalar içinde oy birliğine bakmak.
Okuma ne kadar sık olmalı emin değilim, epeydir buton uygulaması yapmadım ama ben olsam 1 ms periyodla başlardım. Bu süre uzatılabilir ama daha kısası işlemci için yorucu olacaktır. Her buton için uint8_t bir değişken oluşturup, her yeni okumayı bu değişkenin bir ucuna ekleyip sonra da 1 bit kaydırma yapardım. Değişken 0 ise buton 0, 0xff ise buton 1 demektir. Diğer değerleri bouncing durumunu göstereceği için göz ardı ederdim.
Ufak çaplı başlangıç denemesi yaparken; Buton okumalarının başına 1-2 msn. gecikme vererek, bubouncing problemini aşmayı başarabildim. Butona çıkışına kondansatör bağlamakda iş görebiliyor.
Siz buton giriş kesmesini öenrmiyorsunuz. timer kesmesi içinde butonları sürekli okurken butona tek tıklamalı veya sürekli basılı tutmayı halletmek zor oluyormu? Tek tıklamalı buton okumak,
görebildiğim kadarıyla, kesme girişleri ile iyi oluyor gibi duruyor. Buton basılı kalsada problem olmuyor. Yalnız butona uzun süre sürekli basıldığınıda anlamak gerekebiliyor budurumda hangi yöntem avantajlı olur.?
Belki işine yarayabilir esp32 de çalışan bir kod. Normalde hem timer kesmesi, hem de input kesmesi ile kullanılabilecek şekilde yazdığım bir kod, yalnız esp32 kaynaklı bir problemden dolayı input kesmesi sürekli hatalı sonuç sebep oluyor, zaten daha önceleri başkalarınında mcu kaynaklı bu problemi duyduğum için üzerinde durmayıp yalnız timer ile çalışacak şekilde kullandım.
Özünde state machine bulunan bir kod bloğu ve iki buton gibi mcu a bağlanan rotary encoder handle ediyor.
int deb_cnt,deb_stt;
/* state 0->1->2->3 ise arttirilir*/
/* state 3->2->1->0 ise arttirilir*/
static uint8_t rtr_pos[4] = {1, 3, 0, 2};
//uint8_t rtr_neg[4] = { 3, 0, 2, 1 };
static uint8_t rtr_neg[4] = {2, 0, 3, 1};
int32_t inp_taps[inp_max];
int32_t inp_stt[inp_max];
uint16_t rtr_stt;
int32_t rtr_val;
uint32_t us10_cnt;
static void inputCallback(void* arg){
if(deb_stt > 0 && deb_cnt++ < 10 )return;
deb_stt = 0;
deb_cnt = 0;
uint32_t gpio_num;
for (int i = 0; i < inp_max; i++)
{
gpio_num = inp_nums[i];
/* result touch vals processing*/
switch (inp_stt[i])
{
/* unpressed state*/
case 0:
if (!gpio_get_level(gpio_num))
{
inp_stt[i] = 1;
inp_taps[i]++;
deb_stt++;
xEventGroupSetBits(InputEvents, gpio_num);
}
break;
/* pressed state*/
case 1:
/* shut down sayaci resetlenir*/
t_base_sdown = time_cnt;
if (gpio_get_level(gpio_num))
{
inp_stt[i] = 0;
deb_stt++;
xEventGroupSetBits(InputEvents, gpio_num);
}
break;
}
}
/* rotary encoder yon takibi yapilir*/
rtr_stt = ((inp_stt[inp_rtr_prev] & 1) << 1) | (inp_stt[inp_rtr_next] & 1);
if (rtr_stt_old != rtr_stt)
{
if (rtr_pos[rtr_stt_old] == rtr_stt)
{
rtr_val++;
}
else if (rtr_neg[rtr_stt_old] == rtr_stt)
{
rtr_val--;
}
else{
rtr_val=0;
}
rtr_stt_old = rtr_stt;
}
}
static void deb_tick_task(void *arg)
{
_enter_critical_fnc();
us10_cnt++;
inputCallback(0);
_exit_critical_fnc();
}
Button okumada bouncing problemini aşmayı donanımsal olarak halletmelisin.
Butonlar Pozitif mi negatifmi kontaklı olacak ona göre tasarlayabilirsin.
Hatta 2x3 mux okuyabilirsinki bir çok sistemde (Daha fazla buton durumunda) kullanılan bir yöntem.
Nasıl olsa 4 diğit Display çıktısı çıkışı veriyorsun. Oradaki çıkışlardan geridönüş okuyarak hangi butonun basıldığını 2 pin üzerinden okuyabilirsin. Ayrıca zaman kaybına da gerek kalmaz.
İyi bir algoritmayla işlemciyi de yormadan halletmiş olursun.
(https://i.ibb.co/qsMgMRZ/contenteetimes-images-design-embedded-2015-07-kaganmuxfig1.webp) (https://ibb.co/qsMgMRZ)
(https://i.ibb.co/ftLHHd9/contenteetimes-images-design-embedded-2015-07-kaganmuxfig3.jpg) (https://ibb.co/ftLHHd9)
(https://i.ibb.co/P1VyR08/contenteetimes-images-design-embedded-2015-07-kaganmuxfig2.jpg) (https://ibb.co/P1VyR08)
Bu 3 ünü birleştir melez bir keyboard ve display ortak giriş çıkış kullan.
Salim Hocam,
Devrem kurulu belirli bir aşamaya getirdim, sadece birkaç noktası kaldı. Devrenizden notlarımı aldım. Nasipse ileride kullanırız. Güzel bir devre.
Genele şöyle bir sorum var;
Pic mikrokontrolörde, Change Notification (CN) Pinlerin Kesmesi içerisindeyken (kesmeden henüz çıkılmadan önce),
başka bir Timer Interrupt Kesmesi oluşup, program Timer Interrupt kesmenin fonksiyonuna gidip-dallanıp,
buradaki işlemler yapılıp bitirildikten sonra, Tekrar niye henüz tamamlanmayan CN Pinlerin Kesmesi içerisine dönmez.
Bu mümkün değil mi? Mümkünse.! Neyi atlıyor olabilirim? Timer Interruptu, Cn Interruptun içinde oluştuğunda,
Cn Interruptu yarıda bırakıp kaldığı yere geri dönmüyor. Bu saçma bir durum değilmi? İşleyiş nasıl oluyor burada?
Hangi PIC modelinden bahsediyoruz? Güncel modelleri takip etmedim ama eski PIC16'larda kesme öncelikleri yoktu. Bu da bir kesmenin işlenmesi bitmeden bir diğerine başlanamayacağı anlamına geliyor. Zaten kesme vektörü de sadece 1 tane idi, yazılımsal dallanma gerekiyordu. Sonradan gelen kesme kaybolmaz, ancak birincinin işlenmesi bittikten sonra işlenir.
Eski PIC18'lerde ise 2 adet kesme önceliği ve 2 adet kesme vektörü vardı, tabi eğer bu özellik etkinleştirilirse. Bunlarda yüksek öncelikli bir kesmenin düşük öncelikli bir kesmeyi kesmesi mümkün.
Bu arada CN kesmesinin zaten hızlıca bitirilip çıkılması gerekir. Program akışı kesme içinde kesme beklemeye göre tasarlandıysa tasarımda bir hata var demektir.
Sadece timer kesmesi ile halledilir özel bir duruma gerek yok. Timer de sadece görev zamanları belirlenir ana döngüde kontrolleri yapılır.
Alıntı yapılan: picmanya - 18 Haziran 2024, 17:32:52Salim Hocam,
Devrem kurulu belirli bir aşamaya getirdim, sadece birkaç noktası kaldı. Devrenizden notlarımı aldım. Nasipse ileride kullanırız. Güzel bir devre.
Genele şöyle bir sorum var;
Pic mikrokontrolörde, Change Notification (CN) Pinlerin Kesmesi içerisindeyken (kesmeden henüz çıkılmadan önce),
başka bir Timer Interrupt Kesmesi oluşup, program Timer Interrupt kesmenin fonksiyonuna gidip-dallanıp,
buradaki işlemler yapılıp bitirildikten sonra, Tekrar niye henüz tamamlanmayan CN Pinlerin Kesmesi içerisine dönmez.
Bu mümkün değil mi? Mümkünse.! Neyi atlıyor olabilirim? Timer Interruptu, Cn Interruptun içinde oluştuğunda,
Cn Interruptu yarıda bırakıp kaldığı yere geri dönmüyor. Bu saçma bir durum değilmi? İşleyiş nasıl oluyor burada?
Umarım kesme rutininde uzun programlar yazmıyorsunuzdur.
Yeni bir kesme zamanı geldiğinde tekrar kesme rutinine düşeceğinden asla çıkamaz.
O yüzden kesmelerde bazı değerler set edilir çıkılır. Uzun uzun kod yazılmaz. En fazla birkaç formül icra edilir.
Mesela clock tan Saniye yada milisaniye ye indigemek gibi. Milisaniye ataması yapılır çıkılır.
Diğer işlemlerin tamamı ana döngü ve altındaki rutinlerde yapılır.
Tagli,
30F ler de durum belirttiğiniz gibi değil. Farklı çalışıyor olmalılar. En yüksek öncelikli kesme içinde en düşük öncelikli kesmede oluşsa ona dallanılıyor.
Belki ayarlamaları vardır, ama defaultunda durum böyle görünüyor. Kesme öncelik sırası, iki kesme aynı anda tetiklendiğinde, öncelik sırası ilk hangisinin fonksiyonuna gidilecek kısmında olabilir belki.
Alıntı yapılan: Okan AKÇA - 19 Haziran 2024, 12:29:16Sadece timer kesmesi ile halledilir özel bir duruma gerek yok. Timer de sadece görev zamanları belirlenir ana döngüde kontrolleri yapılır.
Zaten bir timer kesmesi 4 dijit seven segment dipleyleri sürüyor. CN kesmesini komple bırakıp, ayrı bir timer kesmesi ile butonları oku ve kontrollerini gerçekleştirmi demek istediniz.
GeneleButona uzun basıldığını, nerede nasıl algılayıp ne yapmam gerekir, işlemler sırasını açıkça anlatacak birisi varmı?
Mevcuttaki haliyle; butonların basıldığının algılanmasının ve tüm kontrollerinin, yalnızca CN kesmesi içinde olduğunuda bilinmesi gerekir.
Şu anda tüm buton işlemleri, yalnızca CN kesmesi içinde bulunuyor. Butona uzun basıldığını nasıl-nerede algılamalıyım? Tane tane anlatılabilirse,
anlatılanları aynen uygulayabilirim. Koda gerek yok, metodu bilmem yeterli olur.
Alıntı yapılan: picmanya - 19 Haziran 2024, 12:57:0230F ler de durum belirttiğiniz gibi değil. Farklı çalışıyor olmalılar. En yüksek öncelikli kesme içinde en düşük öncelikli kesmede oluşsa ona dallanılıyor.
Bunun olması mümkün değil. Üzerinden yıllar geçtiği için bilgilerim çok taze olmasa da daha önce dsPIC30F2010 ile çalışmıştım. Farklı kesme öncelikleri ve her bir kesme için ayrı vektör olduğunu hatırlıyorum. Zaten tek çekirdekli hiçbir mimaride düşük öncelikli bir kesme yüksek öncelikli bir kesmeyi kesemez. Önce yüksek öncelikli kesmenin işlenmesinin tamamlanması gerekir.
Alıntı yapılan: picmanya - 19 Haziran 2024, 12:57:02Kesme öncelik sırası, iki kesme aynı anda tetiklendiğinde, öncelik sırası ilk hangisinin fonksiyonuna gidilecek kısmında olabilir belki.
Bu mümkün ancak dsPIC30F'lerde bu özelliğin olup olmadığını veya nasıl çalıştığını hatırlamıyorum. ARM Cortex M'lerde "priority grouping" diye bir kavram var. Uygun şekilde ayarlandığında kesme önceliklerinin, kesmelerin birbirini kesmesinde bir etkisi olmayıp sadece bir sonra işlenecek olan kesmenin hangisi olacağını belirlemede etkili olmasını sağlamak mümkün.
Tesadüf bende dsPIC30F2010 ile çalıştığımdan sadece gördüğümü yazdım.
Derleyicim C XC16, düşük öncelikli kesme, büyük öncelikli kesmeyi kesebilir olarak görünüyor.
Belki ayarlamalardan bu isteğe göre düzenleniyor olabilir. Interrupt nesting diye bir ayar falan vardı.
Ayarların fazlasıda varsa, ben bu türden ayarlamalara hiç müdahale etmeden kullandım.
Priority 1-7 arası kesme öncelik sıralamaları var.
Kesmeler hakkindeki bilgiler, genelde eski 8 bit işlemcilerden beri aynı telaffuz ediliyor gibi duruyor.
Çeşitli Varyasyonlar var:
Aynı priortiy kesme derecesine sahip iki kesme, aynı anda tetiklenirse ne olur? (Burda kesin birşey oluyor olmalı. Ama ne olur. Priortiden hariç bunlarında kendi içinde bir hiyararşisi olabilir.)
Yüksek öncelikli kesme içindeyken, düşük öncelikli kesme olursa ne olur? (Benim gördüğüm düşük öncelikli kesmede işleme alınıyor. Yine kendi hiyerarşisi devreye giriyorda olabilir.)
Yüksek öncelikli kesme içindeyken, düşük öncelikli kesme oluşursa dikkate alınmaması için hangi ayara müdahale etmek gerekir?
Tezgahım kurulu, öneri varsa deneyebilirim.
Sayısal bir karışıklık veya yanlış anlaşılma olabilir mi? ARM'da örneğin öncelik numarası küçüldükçe öncelik artar. Önceliği 0 olan kesme en yüksek önceliklidir. Belki PIC'te de öyledir, dokümana bir bakmak gerek.
Aynı öncelikli kesmelerin aynı anda gelmesi durumunda genelde vektör numarasına göre içlerinden biri daha yüksek öncelikli kabul edilir.
30F lerde 1 en düşük 7 en yüksek öncelikli kesme priority level-numarasıdır bunu iyi biliyorum.
Kesme içinde kesmede kesinlikle çalışıyor, burda kesmelerin önceliğinin hiç bir önemide yok.
INTCON1, NSTDIS = 1 ayarını hiç kullanmadım, ama bu register ayarıyla, bu çalışma tarzı değiştirilebiliyor olarak görünüyor.
Yani sizin dediğiniz gibide çalıştırmak mümkün gibi. 8 bit 16F-18F lerden bir farkı olsun yani.
Bence bir kesme içinde başka kesmeninde çalışması istenilen yerler olabilir, bu bana daha uygun geldi.
Her iki kesmeyide idare edecek ikisinde işini bir ondan bir bundan deyip görecek. Birnevi paralel çalışma yapacak yani.
_____________________________________________________________________________________________________________________________
Bu vektör numarasının belirttiğinizin dışında başka yerlerde de işe yaradığı oluyor mu?
Birde tüm kesmelerin Alternatif interrupt vektörü diye bir şey yazıyor bu ne amaçlı oluyor biliyormusunuz?
Buton kontrol devremi tek buton için istediğim gibi tamamladım. Diğer butonlarada bir fonksiyon yardımıyla kopyalarım artık.
Birşeyi ilk kez yapmak çok zahmetli olabiliyor. Değerli yardımlarından dolayı herkese teşekkür ederim.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:3430F lerde 1 en düşük 7 en yüksek öncelikli kesme priority level-numarasıdır bunu iyi biliyorum.
Evet, öyle imiş. Az önce ben de referans manual (https://ww1.microchip.com/downloads/en/DeviceDoc/70053D.pdf)'den baktım.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34Kesme içinde kesmede kesinlikle çalışıyor,
Bu mümkün, NSTDIS = 1 yapılmadığı sürece varsayılan ayar da zaten bu. Ancak bunun olmasının tek yolu var: Düşük öncelikli bir kesme çalışırken yüksek öncelikli bir kesme gelecek. Tersi mümkün değil. Benzer şekilde, aynı önceliğe sahip iki kesme de birbirini kesemez.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34burda kesmelerin önceliğinin hiç bir önemide yok.
Bu kesinlikle mümkün değil. NSTDIS = 1 yapılırsa tüm kesmeler aynı önceliğe sahip olur. Ancak bu durumda bile birbirlerini kesemezler.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34Bence bir kesme içinde başka kesmeninde çalışması istenilen yerler olabilir, bu bana daha uygun geldi.
Aynı fikirdeyim. Kesme öncelikleri bunun için var zaten.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34Her iki kesmeyide idare edecek ikisinde işini bir ondan bir bundan deyip görecek. Birnevi paralel çalışma yapacak yani.
Tek çekirdekli bir işlemcide bu şekilde bir işleyiş mümkün değil. dsPIC30F için durum bu en azından. İstisnai mimariler olabilir. Padauk'un öyle garip bir işlemcisi vardı aklımda yanlış kalmadıysa, sanki 2 thread var gibi donanımsal olarak bir ondan bir bundan kod çalıştırıyordu.
@picmanya bence senin yazılımında gözünden kaçan bir durum var. Veya belki de derleyicide bir bug vardır. Durumu analiz etmenin en pratik yolu şüpheli kesmelerin giriş-çıkışlarında birer pini 1-0 yapmak. Sonra da bunları bir lojik analizör ile gözlemle. Benim sıklıkla kullandığım bir debug yöntemidir ve çok faydasını gördüm. Ben CN kesmesinin bouncing sebebiyle beklediğinden daha fazla sayıda geldiğinden şüpheleniyorum. Ya da belki kesme önceliklerini atamayla ilgili bir problem vardır.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34Bu vektör numarasının belirttiğinizin dışında başka yerlerde de işe yaradığı oluyor mu?
Bildiğim kadarıyla hayır. Sadece aynı önceliğe sahip kesmeler arasında karar verilmesinde kullanılıyor.
Alıntı yapılan: picmanya - 19 Haziran 2024, 20:52:34Birde tüm kesmelerin Alternatif interrupt vektörü diye bir şey yazıyor bu ne amaçlı oluyor biliyormusunuz?
Çalışma sırasında kesme fonksiyonunun değiştirilmesine olanak veriyor. Gerçi bir değişkenle de dallanma yapılabilirdi belki. İşlemcide aynı anda yüklü olan ancak aynı anda çalışmayacak iki uygulama varsa işe yarayabilir. Akla ilk gelen örnek bootloader'lar sanırım.
Anladım. Bilgilendirmeler için sağolun.
Ben devremi herhangibir lojik analizöre bağlamadım. Gözümle gördüğümü söyledim.
Buton bouncing kısmınıda;
Butona basıldığında, otomatik olarak, CN kesmenin içine gidildiğinde,
en başta ilk olarak 1,5 msn. gecikme döngüsü vererek sonra butonları okuyarak aştım. 1 msn. de yeterli oluyor. garanti olsun dedim.
hatta bu zamanıda menüden ayarlama imkanı sağladım. çalışma zamanında istenirse kullanıcı-operatör tarafından değiştirilebilecek.
CN kesmede çoklu tetikleme olduğunu sanmam, displeyden ve ledlerden devreyi gözlemleyebiliyorum.
Display rakamlarının her tıklamada yalnızca tek tek artırabiliyordum. Çoklu artma hiç olmadı. Taki ben son anda butona uzun basılma yordamını ekleyene kadar.
_____________________________________________________________________________________________
Okan AKÇA ya teşekkür ederim. Mesajını ilk seferinde iyi anlamamışım.
Devremi dediğiniz gibi düzenleyip yapmış oldum. Butona uzun basılma olayını algılama kısmı ana döngü while() içinde timer ile oldu.