logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak obsłużyć przerwanie INT1 w ATTINY2313 tylko przy wciśnięciu przycisku?

psine.pl 10 Kwi 2008 22:06 2022 5
REKLAMA
  • #1 5016631
    psine.pl

    Specjalista Serwis Elektroniki
    Posty: 2347
    Pomógł: 133
    Ocena: 328
    Witam
    klopot mam z obsługą przerwania ... a mianowicie jestem początkującym programistą w języku C ...
    lecz ... potrzebuję by program wykrył wciśnięcie przycisku (podanie 1 logicznej , 0 logiczne robione jest poprzez rezystor podłączony do masy)

    i tu jest klopot ...
    program reaguje na przerwanie INT1 lecz 2 razy ! raz jak wcisnę przycisk a drugi raz jak go puszczę ...
    jak wyeliminować taką sytuację ...

    program w c :

    #include "stdio.h"
    #include "stdlib.h"
    #include <avr/io.h>   //adresy rejestrow
    #include <util\delay.h>  //biblioteka z opoznieniami
    #include <avr/interrupt.h>
    
    volatile int liczba_monet;
    volatile int zmienna,zmienna2,zmienna3;
    
    void inicjalizacja_licznika(void)
    {
    //TCCR1B = _BV(ICNC1)|_BV(ICES1)|_BV(CS11)|_BV(CS12); // testowałem i taką kombinację lecz także nie działa prawidłowo 
    GIMSK = _BV(INT1); //włącz obsługę przerwania INT1  
    MCUCR=_BV(ISC01)|~_BV(ISC00);
    sei();                // włącz obsługę przerwań
    }
    
    
    void odczytaj_piny(void)
    {
    if (bit_is_set(PINB,7)) liczba_monet = 1;
    if (bit_is_set(PINB,6)) liczba_monet = 2;
    if (bit_is_set(PINB,5)) liczba_monet = 3;
    if (bit_is_set(PINB,4)) liczba_monet = 4;
    if (bit_is_set(PINB,3)) liczba_monet = 5;
    if (bit_is_set(PINB,2)) liczba_monet = 6;
    if (bit_is_set(PINB,1)) liczba_monet = 7;
    if (bit_is_set(PINB,0)) liczba_monet = 8;
    }
    
    void krec_silnikiem(void)
    {
    cli();
    PORTD&=~_BV(6);
    _delay_ms(500);
    while((bit_is_set(PIND,0))){
    PORTD&=~_BV(6);
    }
    PORTD|=_BV(6);
    _delay_ms(500);
    zmienna=0;
    zmienna2=1;
    sei();
    }
    
    void czekaj_na_przycisk(void)
    {
    cli();
    while (bit_is_clear(PIND,1));
    krec_silnikiem();
    }
    
    SIGNAL (SIG_INTERRUPT1)
    {
    cli();
    zmienna3=0;
    if (zmienna>8) zmienna=0;
    _delay_ms(600);
    zmienna2=liczba_monet - zmienna;
    ++zmienna;
    PORTD^=_BV(4); //pod ten pin podłączony jest led , który "miga" mi zawsze 2 razy (czyli raz jak naciskam przycisk a 2 raz jak go puszczę) a powinien 1 raz gdy przycisk jest użyty ...
    if (zmienna2==0) czekaj_na_przycisk();
    _delay_ms(100);
    sei();
    }
    
    int main(void) {
    DDRB = 0x00;             // porb jako wejścia (ilosc_monet)   
    DDRD = 0b01010000;       // PIN D6 WYJSCIE
    DDRA = 0b00000100;       // PIN A.2 WEJSCIE
    PORTD|=_BV(4);
    PORTD|=_BV(6);
    PORTD&=~_BV(1);
    zmienna=0;
    zmienna2=0;
    zmienna3=1;
    odczytaj_piny();
    inicjalizacja_licznika();
    do
    {
    _delay_ms(100); // pętla pusta i tak wszystko jest w przerwaniu.
    }
    while(1);
    }
    


    jeżeli mogę prośić o pomoc w ustawieniu obsługi przerwania będę bardzo wdzięczny.

    jeszcze raz w skrócie :-)

    potrzebuję by procesor reagował TYLKO na zbocze opadające lub narastające ... (najlepiej na narastające)

    pozdrawiam
    Marek


    Proszę umieszczać listingi programów w znacznikach "Code". [c_p]
    Konto firmowe:
    PSINE.PL
    ul.Karczówkowska 8A, KIELCE, 25-019 | Strona WWW: https://www.psine.pl
  • REKLAMA
  • #2 5016805
    iwan3000
    Poziom 16  
    Posty: 209
    Pomógł: 9
    Ocena: 3
    Nie znam za bardzo C, ale sprawdź, czy ustawiłeś rodzaj przerwania int wg. tej tabelki:

    ISC11 ISC10 Description
    0 0 The low level of INT1 generates an interrupt request.
    0 1 Any logical change on INT1 generates an interrupt request.
    1 0 The falling edge of INT1 generates an interrupt request.
    1 1 The rising edge of INT1 generates an interrupt request.
  • REKLAMA
  • #3 5016855
    mieciomiecio
    Poziom 12  
    Posty: 34
    Pomógł: 1
    Nie będę się bardzo wgryzał w program ale na moje oko to masz błąd w tym miejscu:

    Używasz przerywania INT1
    GIMSK = _BV(INT1); //włącz obsługę przerwania INT1

    a twoje ustawienie rejestru kontrolnego MCUCR
    MCUCR=_BV(ISC01)|~_BV(ISC00);
    jest dla INT0

    zmień to na (INT1)
    MCUCR=_BV(ISC11)|~_BV(ISC10);
    i powinno działać.

    http://atmel.com/dyn/resources/prod_documents/doc2543.pdf
    strona 63

    PS: Daj znać czy pomogło
    PS2: Co budujesz??
  • REKLAMA
  • #4 5017110
    psine.pl

    Specjalista Serwis Elektroniki
    Posty: 2347
    Pomógł: 133
    Ocena: 328
    a ... buduję znajomemu zamiennik wrzutnika monet do automatu do gier ... oryginał poszedł z dymem ... (mechanicznie rozpoznaje monety, elektronicznie ma policzyć ile ich wpadło)

    pozdrawiam
    Marek

    p.s.
    sprawdzę rano czy działa po poprawce i dam znać ... bo już jestem w domu.
    Konto firmowe:
    PSINE.PL
    ul.Karczówkowska 8A, KIELCE, 25-019 | Strona WWW: https://www.psine.pl
  • REKLAMA
  • #5 5017196
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    A mnie się widzi coś innego:) Reaguje przypuszczam na zbocza (nie chce mi sie szukać w pdfie), jak naciskasz raz sie generują zbocza (pewnie jakiś debounce tam masz) i drugi raz jak puszczasz znow sie któreś zbocze łapie.
  • #6 5018898
    psine.pl

    Specjalista Serwis Elektroniki
    Posty: 2347
    Pomógł: 133
    Ocena: 328
    Witam raz jeszcze.
    W zasadzie to pomogły mi wskazówki kolegi Mieciomiecio a także Iwan3000 .
    nie rozwiązały one problemu, gdyż układ i tak reaguje na wciśnięcie i puszczenie przycisku.
    Stwierdziłem, że nie tędy droga ... lecz wiem już jak definiuje się te przerwania! Dzięki Wam koledzy.

    program poprawiłem korzystając z pośredniej zmiennej , którą uzyłem jako powiedzmy dodatkową flagę ...


    moze komuś się kiedyś przyda...
    dlatego umieszczam tu gotowy program.

    #include "stdio.h"
    #include "stdlib.h"
    #include <avr/io.h>   //adresy rejestrow
    #include <util\delay.h>  //biblioteka z opoznieniami
    #include <avr/interrupt.h>
    
    volatile int liczba_monet;
    volatile int zmienna,zmienna2,zmienna3;
    
    void inicjalizacja_licznika(void)
    {
    //TCCR1B = _BV(ICNC1)|_BV(ICES1)|_BV(CS11)|_BV(CS12); 
    GIMSK = _BV(INT1); //włącz obsługę przerwania 1  
    MCUCR=~_BV(ISC11)|~_BV(ISC10);
      sei();                // włącz obsługę przerwań
    }
    
    void krec_silnikiem(void)
    {
    cli();
    PORTD|=_BV(5);
    PORTD&=~_BV(6);
    _delay_ms(500);
    while((bit_is_set(PIND,0))){
    PORTD&=~_BV(6);
    }
    PORTD|=_BV(6);
    _delay_ms(500);
    zmienna=0;
    zmienna2=1;
    zmienna3=0;
    sei();
    }
    
    
    void czekaj_na_przycisk(void)
    {
    PORTD&=~_BV(5);
    while (bit_is_clear(PIND,1));
    krec_silnikiem();
    }
    
    
    void odczytaj_piny(void)
    {
    int zmienna4;
    zmienna4=PINB;
    
    switch(zmienna4)
    {
       case 128:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=1;
          break;
    	case 64:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=2;
          break;
    	case 32:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=3;
          break;
    	case 16:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=4;
          break;
    	case 8:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=5;
          break;
    	case 4:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=6;
          break;
    	case 2:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=7;
          break;
    	case 1:  // jeżeli warunek == wartość1 to wykonuje instrukcje1
          liczba_monet=8;
          break;
       default:  // jeżeli nie jest spełniony żaden warunek to wykonaj instrukcja3
          czekaj_na_przycisk();
          break;
    }
    }
    
    
    SIGNAL (SIG_INTERRUPT1)
    {
    cli();
    _delay_ms(30);
    zmienna3=1;
    _delay_ms(100);
    
    }
    
    int main(void) {
    DDRB = 0b00000000;             // porb jako wejścia (ilosc_monet)   
    DDRD = 0b01110000;       // PIN D6 WYJSCIE (1 TO WYJSCIE 0 TO WEJSCIE)
    DDRA = 0b00000100;       // PIN A.2 WEJSCIE
    PORTD|=_BV(4);
    PORTD|=_BV(6);
    PORTD|=_BV(5);
    PORTD&=~_BV(1);
    zmienna=0;
    zmienna2=0;
    zmienna3=1;
    liczba_monet=3;
    inicjalizacja_licznika();
    //PORTD = 0x0d;                // podciąganie bitów 3 i 4 PortD (przyciski)
    do
    {
    odczytaj_piny();
    if (zmienna3==1) {
    zmienna3=0;
    ++zmienna;
    if (zmienna>8) zmienna=0;
    _delay_ms(300);
    PORTD^=_BV(4);
    zmienna2=liczba_monet - zmienna;
    if (zmienna2==0) czekaj_na_przycisk();
    _delay_ms(100);
    sei();
    }
    sei();
    }
    while(1);
    }
    


    Pozdrawiam
    Marek
    Konto firmowe:
    PSINE.PL
    ul.Karczówkowska 8A, KIELCE, 25-019 | Strona WWW: https://www.psine.pl
REKLAMA