C ile AVR Programlama -39- Dış Kesme Yazmaçları

Dış kesme yazmaçlarını anlatmaya bu yazımızda devam ediyoruz. Şimdi yazmaçlara kaldığımız yerden devam edelim.

EIMSK – Dış Kesme Maske Yazmacı

Bit 1 – INT1 : Dış kesme talebi 1 etkin

INT1 biti ve SREG yazmacındaki I biti bir (1) olduğunda harici ayak kesmesi etkin hale gelir. Dış kesme denetleme yazmacındaki (EICRA) kesme algılama denetim bitleri (ISC11 ve ISC10) bu kesmenin yükselen veya düşen kenarda ya da ayak durumuna göre olup olmayacağını kararlaştırır. INT1 ayağı çıkış olarak tanımlansa da bu ayağa uygulanan gerilim kesmeyi yürütecektir.

Bit 0 – INT0 : Dış kesme talebi 0 etkin

INT0 biti ve SREG yazmacındaki I biti bir (1) olduğunda harici ayak kesmesi etkin hale gelir. Dış kesme denetleme yazmacındaki (EICRA) kesme algılama denetim bitleri (ISC01 ve ISC00) bu kesmenin yükselen veya düşen kenarda ya da ayak durumuna göre olup olmayacağını kararlaştırır. INT0 ayağı çıkış olarak tanımlansa da bu ayağa uygulanan gerilim kesmeyi yürütecektir.

EIFR – Dış Kesme Bayrak Yazmacı

Bit 1 – INTF1 : Dış Kesme Bayrağı 1

INT1 ayağındaki kenar veya mantık durumu değiştiğinde INT1 ayağı kesmeyi tetiklediğinde INTF1 biti bir (1) olur. Eğer SREG yazmacındaki I biti ve EIMSK yazmacındaki INT1 biti bir (1) yapılırsa işlemci kesme fonksiyonuna atlar. Bu bayrak kesme fonksiyonu yürütüldüğünde otomatik sıfırlanır. Ya da bu bayrağa bir (1) yazılarak sıfırlamak mümkündür. Bu bayrak INT1 kesmesi seviye kesmesi olarak ayarlandığında her zaman sıfır (0) konumundadır.

Bit 0 – INTF0 – Dış Kesme Bayrağı 0 

INT0 ayağındaki kenar veya mantık durumu değiştiğinde INT0 ayağı kesmeyi tetiklediğinde INTF0 biti bir (1) olur. Eğer SREG yazmacındaki I biti ve EIMSK yazmacındaki INT0 biti bir (1) yapılırsa işlemci kesme fonksiyonuna atlar. Bu bayrak kesme fonksiyonu yürütüldüğünde otomatik sıfırlanır. Ya da bu bayrağa bir (1) yazılarak sıfırlamak mümkündür. Bu bayrak INT0 kesmesi seviye kesmesi olarak ayarlandığında her zaman sıfır (0) konumundadır.

PCICR – Ayak Değişimi Kesmesi Denetleme Yazmacı

Bit 2 – PCIE2 : Ayak değişimi kesmesi Etkin 2

PCIE2 biti ve SREG yazmacındaki I biti bir (1) konumuna getirilirse ayak değişimi kesmesi 2 etkinleştirilir. PCINT[23:16] ayaklarındaki bir değişim bu kesmeyi yürütür. PCINT[23:16] ayakları tek tek PCMSK2 yazmacından etkinleştirilebilir.

Bit 1 – PCIE1 : Ayak değişimi kesmesi Etkin 1

PCIE1 biti ve SREG yazmacındaki I biti bir (1) konumuna getirilirse ayak değişimi kesmesi 1 etkinleştirilir. PCINT[14:8] ayaklarındaki bir değişim bu kesmeyi yürütür. PCINT[14:8] ayakları tek tek PCMSK1 yazmacından etkinleştirilebilir.

Bit 0 – PCIE0 : Ayak değişimi kesmesi Etkin 0

PCIE0 biti ve SREG yazmacındaki I biti bir (1) konumuna getirilirse ayak değişimi kesmesi 0 etkinleştirilir. PCINT[7:0] ayaklarındaki bir değişim bu kesmeyi yürütür. PCINT[7:0] ayakları tek tek PCMSK0 yazmacından etkinleştirilebilir.

 

PCIFR – Ayak Değişimi Kesmesi Bayrak Yazmacı

Bit 2 – PCIF2 : Ayak Değişimi Kesme Bayrağı 2 

PCINT [23:16] ayaklarından birinde mantıksal değişim olduğunda kesme talebi tetiklenir ve bu durumda PCIF2 biti bir (1) konumuna geçer.

Bit 1 – PCIF1 : Ayak Değişimi Kesme Bayrağı 1

PCINT [14:8] ayaklarından birinde mantıksal değişim olduğunda kesme talebi tetiklenir ve bu durumda PCIF1 biti bir (1) konumuna geçer.

Bit 0 – PCIF0 : Ayak Değişimi Kesme Bayrağı 0

PCINT [7:0] ayaklarından birinde mantıksal değişim olduğunda kesme talebi tetiklenir ve bu durumda PCIF0 biti bir (1) konumuna geçer.

PCMSK2 – Ayak Değişimi Maske Yazmacı 2 

Bit 0, 1 , 2, 4, 5, 6, 7 – PCINT 16, PCINT17, PCINT18, PCINT19, PCINT20, PCINT21, PCINT22, PCINT23 : Ayak değişimi Etkinleştirme Biti

Bu yazmaç hangi ayaklardan kesme gerçekleştireceğini belirler. Bu bitlerden biri ya da birkaçı ve PCICR yazmacındaki PCIE2 biti bir (1)  yapılırsa uygun ayaktaki değişmeye göre kesme gerçekleşir. PCMSK2 yazmacındaki bitler sıfır (0) yapılırsa o kesme devre dışı bırakılır.

PCMSK1 – Ayak Değişimi Maske Yazmacı 1 

Bit 0, 1, 2, 3, 4, 5, 6 – PCINT8, PCINT9, PCINT10, PCINT11, PCINT12, PCINT13, PCINT14 : Ayak Değişimi Etkinleştirme Biti

Bu yazmaç hangi ayaklardan kesme gerçekleştireceğini belirler. Bu bitlerden biri ya da birkaçı ve PCICR yazmacındaki PCIE1 biti bir (1)  yapılırsa uygun ayaktaki değişmeye göre kesme gerçekleşir. PCMSK1 yazmacındaki bitler sıfır (0) yapılırsa o kesme devre dışı bırakılır.

PCMSK0 – Ayak Değişimi Maske Yazmacı 0 

Bit 7:0 – PCINTn : Ayak Değişimi Etkinleştirme Biti [ n = 7:0 ]

Bu yazmaç hangi ayaklardan kesme gerçekleştireceğini belirler. Bu bitlerden biri ya da birkaçı ve PCICR yazmacındaki PCIE0 biti bir (1)  yapılırsa uygun ayaktaki değişmeye göre kesme gerçekleşir. PCMSK0 yazmacındaki bitler sıfır (0) yapılırsa o kesme devre dışı bırakılır.

 

Bütün dış kesme yazmaçlarını bitirdiğimize göre şimdi dış kesmelerin kullanıldığı bir örneği açıklayarak konumuzu bitirelim. Bu devrede dışarıdan bağlı bir düğme ve bir porta bağlı olan toplam 8 adet led bulunur. Düğmeye bastıkça bu ledler sıra ile yanacaktır. Programın en önemli özelliği ise bağlı olan düğmenin dış kesme ile kullanılmasıdır. Devremizin şeması aşağıdaki gibidir.

Resim : http://www.avr-tutorials.com/sites/default/files/INT0_0.png

Şimdi kodu vererek bu kodu satır satır anlatalım.

Bu program kodlardan anlaşıldığı üzere normal çalışma döngüsünde devreye bağlı olan sekiz ledi sağdan sola sırayla 500 mili saniye aralıklarla yakacaktır. 0x80 değeri 0b10000000 değerine denk geldiği için 8. led yandığı zaman port tekrar 1 değerine çekilip ilk ledin yanması sağlanacaktır. Böylelikle bu kayan ışık programı sürekli olarak çalışacaktır. Bu sürekli çalışan programı kesmek için INT0 kesmesi kullanılmıştır. Bu kesmeyi yürütmek için PD2 ayağı giriş olarak tanımlanmış, buna bir düğme bağlanmış ve dahili pull-up özelliği etkinleştirilmiştir. Böylelikle düğmeye basıldığında kesme yürütülecektir. Dış kesmeler için kullanılan iki komut ve kesme fonksiyonu vardır. Geri kalan komutlar temel giriş ve çıkış özelliğinde olduğu için derslerin en başında anlatılmıştır.

ISR(INT0_vect)  Bu kesme fonksiyonu INT0 kesmesi yürütüldüğünde işletilecek kodları içinde bulundurur.

GICR = 1<<INT0;  GICR yazmacının INT0 biti bir (1) yapılarak INT0 kesmesi etkinleştirilir.

EICRA = 1<<ISC01 | 1<<ISC00; Kesmenin ne zaman yürütüleceği EICRA yazmacının bitleri ile kararlaştırılır.

Bir sonraki derste yeni bir konuya geçeceğiz. Görüşmek üzere.

Kaynaklar:

AVR C Programming of External Interrupt, http://www.avr-tutorials.com/interrupts/avr-external-interrupt-c-programming, Erişim Tarihi : 02.09.2018

ATmega328P – Microchip Technology , http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf, Erişim Tarihi: 25.08.2018

Kapak Resmi : http://industrialtraining.info/wp-content/uploads/2017/02/avr-micrcontroller-training-in-patiala.jpg

UYARI!!

Gökhan Dökmetaş

Bilgi Teknolojileri Uzmanı

You may also like...

12 Responses

  1. İlker Aykut dedi ki:

    Hocam merhaba INT0 kesmesi ve timer0 kesmesi arasındaki geçişler mnasıl olur?Mesela INT0 dayken timer0 a geçsin timer0 Isr yi tamamladıktan sonra INT0 ISR sine geri dönsün gibi?

  2. İlker Aykut dedi ki:

    Hocam şöyle bir sorum var.

    void kisa_fonksiyon(void);
    void uzun_fonksiyon(void);
    volatile boolean kisa=true;

    ISR(INT1_vect){

    uint16_t zaman=0;
    while(PIND & (1<0 && zaman=30)
    {
    kisa=false;
    }

    }

    int main(void)
    {

    DDRD |=(1<<PIND6);
    PORTD &=~(1<<PIND6);
    DDRD |=(1<<PIND7);
    PORTD &=~(1<<PIND7);
    DDRD &=~(1<<PIND3);

    EICRA |=(1<<ISC10);
    EICRA |=(1<<ISC11);

    while(1)
    {
    EIMSK |=(1<<INT1);
    sei();
    if(kisa)
    kisa_fonksiyon();
    else
    uzun_fonksiyon();

    }

    }
    void kisa_fonksiyon()
    {
    PORTD &=~(1<<PIND7);

    for(int j=1;j<3;j++)
    {
    for(int i=0;i<4;i++)
    {
    PORTD ^=(1<<PIND6);
    _delay_ms(j*1000);
    }
    }
    }
    void uzun_fonksiyon()
    {
    PORTD &=~(1<<PIND6);

    for(int j=1;j<3;j++)
    {
    for(int i=0;i<8;i++)
    {
    PORTD ^=(1<<PIND7);
    _delay_ms(j*1000);
    }
    }

    }

    Burada interrupta girdikten sonra kisa degerini değiştiriyor ama örneğin kısa fonksiyonundaysa o fonksiyonu bitirdikten sonra uzun fonksiyona gidiyor.Ben o anda o fonksiyonun bitmesini istiyorum ne yapabilirim acaba?

    • İlker Aykut dedi ki:

      while(PIND & (1<0 && zaman=30)
      {
      kisa=false;
      }

      bu kısım yanlış olmuş hocam şöyle olacak

      while(PIND & (1<<PD3)) //Buton pull down
      {
      zaman++;
      _delay_ms(100);

      }

    • return komutu ile istediğiniz zaman istediğiniz fonksiyondan çıkabilirsiniz. C dilinde böyle bir deyim mevcut. Bunu şart ifadesine bağladıktan sonra gayet sağlıklı çalışır.

  3. Eldar dedi ki:

    Dersler çok faydalı teşekkür ederim.GICR = 1<<INT0; GICR yazmacının INT0 biti bir (1) yapılarak INT0 kesmesi etkinleştirilir.-Şurada galiba GİCR yerine EIMSK olmalı

  4. Eldar dedi ki:

    Döngüde çalışması için küçük deyişiklikler yapdım.Belki faydalı olur:

    #include
    #include

    #define F_CPU 16000000UL
    #include
    #define DataPort PORTC // PORTC dataport olarak tanımlanıyor.
    #define DataDDR DDRC // Port adlarına böyle isim verebiliriz.
    #define ms 100 //delay fonksiyonları için
    //INT1 için kesme fonksiyonu. Kesme yürütüldüğünde işletilecek kodlar.
    ISR(INT1_vect)
    {
    unsigned char i, temp;

    _delay_ms(ms); // Düğme arkını engellemek için bekleme fonksiyonu.

    temp = DataPort; // DataPort’un değerini ver.

    /* Bu döngü dataporttaki ledleri beş kere yakar.*/
    for(i = 0; i<5; i++)
    {
    DataPort = 0x00;
    _delay_ms(ms); // ms kadar bekle
    DataPort = 0xFF;
    _delay_ms(ms); // ms kadar bekle
    }

    DataPort = temp; //Dataporta eski değerini ver. (0)
    }

    int main(void)
    {
    DDRD = 1<<PD3; // ,INT1 kesmesi için kullanılan PD2 ayağı giriş
    PORTD = 1<<PD3; // Dahili pull-up dirençlerini etkinleştir.
    DataDDR = 0xFF; // Dataportu çıkış yap
    EIMSK = 1<<INT1; // INT1 kesmesini etkinleştir
    EICRA = 0<<ISC01 | 1<<ISC00; // her hangi bir deyişiklikde INT1 kesmesi yürüyecek
    sei(); //Genel kesmeleri etkinleştir.

    while(1)
    {
    for ( int a=0 ; a<6;a++)
    {
    DataPort |= _BV(a);
    _delay_ms(ms);
    }
    for ( int b=0 ; b<6;b++)
    {
    DataPort &= ~(_BV(b));
    _delay_ms(ms);
    }
    }
    }

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.