Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

EXTI9_5

Başlatan muhittin_kaplan, 15 Haziran 2014, 02:36:38

muhittin_kaplan

void EXTI9_5_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line6) != RESET)
  {

    intValue++;
	  /* Clear the EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line6);
  }
}

void EXTILine6_Config(void)
{

	GPIO_InitTypeDef   GPIO_InitStructure;
	  NVIC_InitTypeDef   NVIC_InitStructure;

	  /* Enable GPIOA clock */
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	  /* Enable SYSCFG clock */
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);


	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	  GPIO_Init(GPIOA, &GPIO_InitStructure);

	  /* Connect EXTI Line6 to PA6 pin */
	  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource6);

	  /* Configure EXTI Line6 */
	  EXTI_InitStructure.EXTI_Line = EXTI_Line6;
	  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	  EXTI_Init(&EXTI_InitStructure);

	  /* Enable and set EXTI Line9-5 Interrupt to the lowest priority */
	  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	  NVIC_Init(&NVIC_InitStructure);
	}


gibi bir int rutininde butona birkez basıldığında intValue değeri neden birden fazla artar ?

AsHeS

#1
Butonun verdiği arktan dolayı (debounce etkisi)
Butona basıldığında asıl olan şudur

muhittin_kaplan

İşlemci Hızlı Olunca Çok Çabuk İnt çıkıyor, Aradaki her bounce da inter. giriyor

mesaj birleştirme:: 15 Haziran 2014, 03:09:07

http://hackaday.com/2010/11/09/debounce-code-one-post-to-rule-them-all/

kimlenbu

Yanıt zaten verilmiş ama bu "debounce" etkisini en verimsiz yöntem olan gecikme fonksiyonları ile çözüyordum.

@muhittin_kaplan, verdiğiniz linkte insanın ufkunu açan güzel yöntemler var, teşekkür ederim :)

selimkoc

Buton uçlarına 100nf kondansatör koyarsanız büyük ölçüde düzelme sağlar.

muhittin_kaplan

bu işe bir çare bulmam gerek. 100n da yine kararsız..

mistek

Alıntı yapılan: muhittin_kaplan - 18 Haziran 2014, 23:55:27
bu işe bir çare bulmam gerek. 100n da yine kararsız..

Hocam birde böyle deneyin : http://postimg.cc/image/kr3akzs6r/
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Gökhan BEKEN

Benim yöntemim farklı.
#define PORT GPIOA
#define BIT 5
#define PORTA5OKU (!(((PORT->IDR)&(1<<BIT)) - (1<<BIT)))
#define OKUMASAYISI 100
if(PORTA5OKU){ //A5 butonuna basildi mi
{                  
   i=0; 
   while(PORTA5OKU){
         i++; 
         if(i>250)i=OKUMASAYISI+1; // not:bu if'e gerek yok normalde, ama adam çok uzun basarsa degisken sifirlanacagindan onlem amacli, bu kod  sayesinde hiç sifirlanmayacak 
    }  
    if(i>OKUMASAYISI)  ButonaBasilincaYapilacakIslemler();
} 


100 Kere kontrol ediyor 100'ünde de basılıysa butona basılmış kabul ediyor. Frekansa göre bu sayı artırılıp azaltılabilir.
Özel mesaj okumuyorum, lütfen göndermeyin.

muhittin_kaplan

Hocam Döngü içerinde değilim, doğrudan int e giriyor.

(Muhtemelen Montajımdan Kaynaklı PullUp da sıkıntı var, Birde Bu STMlerin Dahili PullUpları Düşük mü oluyordu ?)

Gökhan BEKEN

#9
Interrupt'ta da kullanılabilir. Tekrar interrupt'a girmemesi için interrupt bayrağını sıfırlamadan önce yapacaksınız bunları.
Hatta yukarıdaki kodlar yerine, kesmeye her girmesinde statick i değişkenini 1 artırsın, istenilen sayıya ulaşınca butondan elin çekildiğine kadar verirsiniz ve daha sonra tekrar girebilmesi için i'yi sıfırlarsınız.
Özel mesaj okumuyorum, lütfen göndermeyin.

Müh. müh.

Sorun yok. Meftunun yöntemini interrupt içersinde kullanabilirsin.

Ext int. in içersinde en başta, ext interrupt ı disable et. Yukarki yöntemle oku, sonra bıraklıdığınıda aynı yöntemle teyit et. İntten çıkarken, ext. interruptı yeniden aktif et.

Birde yazılım bitince, WDT yi aktif etmeyi unutma, Buton basılı kalırsa, kendini bir kere resetler. Sonralarında, butonda değişim olmayacağından, mcu interrupta da giremez. Müşteriler, bu cihaz takılıyor demez. Butonu bozulmuş derler.
Destiny of white is dirtied. Destiny of black is found guilty...

CLR

sadece kondansatörle bu iş olmaz, dolumu geciktirirsen bu defa deşarj'da uzun sürecektir, ters diyotla hızlı deşarj sağlarsan olur ama bunlar donanım yüküdür.

bu işi çözmenin çok yolu var, debounce genelde tuşun yapısınada bağlı ama en fazla 1ms sürebilir. dolayısıyla ilk okumadan 10ms sonra 2. okuma yapılırsa ve ilki ile aynı ise tuş doğru okunmuştur.

1) klasik yöndem bir delay'in başında ve sonunda o portu okumak ve karşılaştırmak ama bu defa delay kadar işlemci meşgul olacak,

2) @meftun'nun yöntemi ki yine verimsiz bir yöntem, çok fazla okuma yapılıp karşılaştırmalar yapılıyor, çok işlem kaybı var.

3) Soft timer yerine hard timer  interrupt ile delay ile
mesela butuna basılınca exti9_5 int içinde tuşların olduğu port okunur ve delay için timer int startı verilebilir, ilgili timer interrupt içinde tekrar tuşların olduğu port okunur, 1. ve 2. okunan değer aynı ise ilgili tuşa basılmıştır.

4) benzer bir yöntem ile systemtick ile yapılabilir, hatta tüm ms'lik delaylar tek systick ile yapılabilir, 1ms'de bir systick interrupt oluştur,  butuna basılınca exti9_5 int içinde tuşların olduğu port okunur  ve buton delay registerine istediğin değeri ver, systemtick int içinde veya main içinde hertürlü tuş için delay registeri her ms'de bir azaltırsın. 0 olunca portu oku ve karşılaştır.

5)İstersen tuş okuma için 9_5 intrerruptı kurmayıp sürekli 30ms'de bir okutabilirsin system tick int ile . ardışık iki değer aynı ise o tuş basılmıştır.

daha bir çok yol var,
Knowledge and Experience are Power

Müh. müh.

CLR

Aslında bir çoğumuz, işlem gücünü bazen hiç düşünmeden program yazıyoruz.. 5. örneğin mükemmel.

Şu ana kadar gelen öneriler baz alınarak, en temizinin şu olacağını düşünmekteyim.



Herhangi bir timer, herhangi bir zamana kurulur. Örneğin, 1msn.

Timer içersinde hızlıca, butonlar kotrol edilip, ledler, göstergeler, bitler set edilip, temizlenebilir.

timer ın sonunuda basit if komutları ile, örneğin butona 10 zaman boyunca basılmışmı diye bakılabilir. Aynı C# timer mantığında yazılım yazdığımızı düşünelim.
Destiny of white is dirtied. Destiny of black is found guilty...

muhittin_kaplan

sytemtic şu an hazır aslında kontrol edebilirim doğru..

Müh. müh.

#14
Yalnız yukarıda yazdığım şey yanlış anlaşılmasın.

timer içersinde şu mantıkta ilerleyeceğiz. (sadec buton için olan kodları yazıyorum.

if(buton basılmışmı = evet) a++;
if(buton basılmışmı = hayır) a= 0;

.
.
.
.
.

timer ın son kısmında,

if ( a == 10)
{

  // butona basılmış, işlemini yap
 
  a = 0;
}


Yani yukarıdan anlayacağımız üzere, butona basılıp basılmadığını 10 kere döngü içersinde test etmiyoruz. Mcu timer a giriyor, basılı ise a değişkeni artıyor, sonunda a belirli bir değere ulaşmışsa, buton işlemleri uygulanıyor ki, mümkünse, o işlemlerin birkaç kod satırı olması daha makbul. Buton okunup, hemen timer dan çıkılıyor. Eğer buton basıldığında, çok işlem gücü gerekiyorsa, a değişkeninin istenilen değere ulaşıp ulaşmadığını main içersinde test edip, gerekli işlemleri orada yapıp, mcu nun timer interruptını meşgul etmemeliyiz.
Destiny of white is dirtied. Destiny of black is found guilty...