Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => ARM => Cortex ARM => Konuyu başlatan: muhittin_kaplan - 15 Haziran 2014, 02:36:38

Başlık: EXTI9_5
Gönderen: muhittin_kaplan - 15 Haziran 2014, 02:36:38
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 ?
Başlık: Ynt: EXTI9_5
Gönderen: AsHeS - 15 Haziran 2014, 02:48:54
Butonun verdiği arktan dolayı (debounce etkisi)
Butona basıldığında asıl olan şudur
(http://www.engscope.com/wp-content/uploads/2009/02/debounce.png)
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 15 Haziran 2014, 03:08:22
İş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/ (http://hackaday.com/2010/11/09/debounce-code-one-post-to-rule-them-all/)
Başlık: Ynt: EXTI9_5
Gönderen: kimlenbu - 15 Haziran 2014, 11:55:44
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 :)
Başlık: Ynt: EXTI9_5
Gönderen: selimkoc - 15 Haziran 2014, 12:37:38
Buton uçlarına 100nf kondansatör koyarsanız büyük ölçüde düzelme sağlar.
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 18 Haziran 2014, 23:55:27
bu işe bir çare bulmam gerek. 100n da yine kararsız..
Başlık: Ynt: EXTI9_5
Gönderen: mistek - 19 Haziran 2014, 00:00:16
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/ (http://postimg.cc/image/kr3akzs6r/)
Başlık: Ynt: EXTI9_5
Gönderen: Gökhan BEKEN - 19 Haziran 2014, 00:54:38
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.
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 19 Haziran 2014, 01:01:40
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 ?)
Başlık: Ynt: EXTI9_5
Gönderen: Gökhan BEKEN - 19 Haziran 2014, 01:06:23
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.
Başlık: Ynt: EXTI9_5
Gönderen: Müh. müh. - 19 Haziran 2014, 01:09:21
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.
Başlık: Ynt: EXTI9_5
Gönderen: CLR - 19 Haziran 2014, 01:11:44
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,
Başlık: Ynt: EXTI9_5
Gönderen: Müh. müh. - 19 Haziran 2014, 01:25:09
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.
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 19 Haziran 2014, 01:27:55
sytemtic şu an hazır aslında kontrol edebilirim doğru..
Başlık: Ynt: EXTI9_5
Gönderen: Müh. müh. - 19 Haziran 2014, 01:37:01
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.
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 19 Haziran 2014, 01:40:00
ST şöyle yapmış.


(http://s27.postimg.cc/tzc18zs8f/button.jpg) (http://postimg.cc/image/tzc18zs8f/)
Başlık: Ynt: EXTI9_5
Gönderen: CLR - 19 Haziran 2014, 02:28:20
@muhittin_kaplan

şemada kondansatörün yanında not fitted yazıyor yani pcb üzerine dizilmiyor demektir, öyleyse o tuştanda gereksiz spike'lar işlemciye gelecektir, ST örnek kodlarında da interruptlı veya interruptsız delay kullanılıyordur.

Gerçi herkesin tekniği farklıdır, benim prensiplerime göre en az code ile büyük iş yaptırmaya çalışırım. 2 kez okuduğumda doğru tuş okuyacaksam neden fazla okuyayım ki, nokta atışı yaparım.   
Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 19 Haziran 2014, 19:49:56
hocam,

systemtick in altına (yaklaşım 10ms)

if (!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)) {
if (Button1Now==TRUE) {
Button1Pass++;
if (Button1Pass==TRUE) {
intValue++;
Button1Pass=FALSE;
Button1Now=FALSE;
}

}
}

yaptım
Başlık: Ynt: EXTI9_5
Gönderen: AsHeS - 19 Haziran 2014, 20:08:01
Alıntı yapılan: muhittin_kaplan - 19 Haziran 2014, 19:49:56
hocam,

systemtick in altına (yaklaşım 10ms)

if (!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)) {
if (Button1Now==TRUE) {
Button1Pass++;
if (Button1Pass==TRUE) {
intValue++;
Button1Pass=FALSE;
Button1Now=FALSE;
}

}
}

yaptım

Button1Now ne zaman TRUE oluyor ?
Başlık: Ynt: EXTI9_5
Gönderen: CLR - 19 Haziran 2014, 21:53:02
@muhittin_kaplan

Aşağıya basit bir örneğini yazdım, sayıları işlemek sana düşer, Bir tane yerine çok tuş okuyacağını varsayıyorum(mesela 8bitlik bit port/8 tuş olsun), önce bir struct oluşturacağım, bu struct içinde geçerli bir tuş yakalarsan flag 1 olacak(basılan tuş bulundu artık bu tuşla işlem yapabilirsin anlamında), ardışık 2 okumada aynı değeri(tuşu yakalarsam) tuş basılmış kabul edeceğim, 2 okuma için araya delay yerleştireceğim ama yazılıma yük getirmeyecek sonra tuş değerini struct içinde bir registere yazacağım.


struct{
   u8     Flag;             //
   vu8   Delay;           // buton okumada delay için kullanacağım, interrupt içinde kullanacağım için volatile
   u8   KeyCode;       // tuş koduda buraya
}ButonRegs;

#define BUTON_DELAY   25                      //25ms
#define KEY_PORT   (vu8) GPIOA->IDR    // portun 0-7bitlerini okuyacağız

main(){
// systick interupt 1ms'de bir interrupt ayarı
// port ayarları
ButonRegs.Delay=BUTON_DELAY;   

    while(1){                 // main loop
         CheckKeys();
         KeyProcess()


     }


}

//25ms'de bir keyleri check edeceğiz, bu fonksiyon sadece 25ms'de bir çalışacaktır
void CheckKeys(void){

   static u8 KeyTemps[2];      // karşılaştırmalar için
   static u8 cnt;                      // tuş okuma sırasını tutan counter         

   if(ButonRegs.Delay == 0){ // 25ms olduysa tuşlar okunur
            KeyTemps[Cnt++]=KEY_PORT;
            if(Cnt==2){               //2 olduysa tuşlar karşılaştırılır
                     if(KeyTemps[0] == KeyTemps[1]){
                               ButonRegs.KeyCode = KeyTemps[0];    // tuş kodları 0x1,0x2...0x80 şeklinde gelecektir hatta istersen aynı anda 2 tuşa basılmalarıda okuyabilirsin
                               ButonRegs.Flag=1;  // tuş update oldu anlamında
                     }
               Cnt=0;  //clear
            }

          ButonRegs.Delay = BUTON_DELAY;         // sonraki işlem için tekrar 25ms yükledim
   }
}

// bir tuş yakalandı ise işlemleri burada yapılır
void KeyProcess(void){
        if(ButonRegs.Flag){


           ButonRegs.Flag =0;
        }

}

systick_interrupt{

if(ButonRegs.Delay) ButonRegs.Delay--;  // varsa bir azalt

}

Başlık: Ynt: EXTI9_5
Gönderen: muhittin_kaplan - 19 Haziran 2014, 22:21:00
hocam 20ms de bir gelip bakıyorum,
şu haliyle çalışıyor.

if (!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)) {
if (Button1Now==TRUE) {
intValue++;
Button1Now=FALSE;
}
}

else {
Button1Now=TRUE;
}
Başlık: Ynt: EXTI9_5
Gönderen: CLR - 19 Haziran 2014, 22:24:50
çözdüysen iyi, 20ms'de bir baktıktan sonra tuş bırakılana kadarda tuş verileri gecektir, eski tuş ile yeni tuşu karşılaştırabilirsin aynı ise dikkate almazsın veya uzun süreli basım için dikkate alabilirsin
Başlık: Ynt: EXTI9_5
Gönderen: Müh. müh. - 19 Haziran 2014, 22:31:33
Birkaç çeşit buton fonksiyonlama şekli var.

-Mesela basarsın, işlem yapılmaz. Butondan elimizi çekince işlem yapılır.

-Basarsın +1 işlem yapılır. Eğer buton belirli bir süre basılı kalmış işe, yapılan 1 işlemi hızlıca yapmaya başlarsın(sayı arttırma, azaltma fonksiyonlarında sıklıkça kullanılır)

birkaç buton algılatma fonksiyonu daha olması gerekli. Yerine göre seçim yapmamız gerekli.

Eğer ilk yöntem, projeniz için uygunsa, birde butondan elinizi çekme testi yapmanız lazım.