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

[C] Przerwania wys 7seg

cineksuw 27 Gru 2008 19:43 2368 14
REKLAMA
  • #1 5909759
    cineksuw
    Poziom 10  
    Witam. Staram się zrobić obsługę 2 wyswietlaczy 7 segmentowych. Tylko nie mam pojęcia jak to wykonać. Rozdzieliłem już na jednosci i dziesiątki i teraz zostało mi ustalić przerwanie i nie mam pojęcia jak się za to zabrać. Mógłby ktoś pokazać mi jakiś prosty przykład jak zrobić takie przerwanie?
  • REKLAMA
  • Pomocny post
    #2 5909793
    dawid512
    Poziom 32  
  • #3 5910024
    cineksuw
    Poziom 10  
    ok spoko ale tam jest pokazane jak wykonac przerwanie gdy wciskamy przycisk a mi potrzeba aby przerwanie włączało się co jakiś czas
  • Pomocny post
    #4 5910432
    dawid512
    Poziom 32  
    Zobacz tutaj:

    przed mainem dajesz:
    ISR(TIMER0_COMP_vect)
    {
    ...jakies instrukcje w przerwaniu
    }


    W mainie konfigurujesz timer w tryb CTC np. tak:
    
    OCR0 = 150;						
    TCCR0 = _BV(WGM01) | _BV(CS02); 
    TIMSK |= _BV(OCIE0);			


    Wpisanie do OCR0 odpowiedniej wartości spowoduje wywołanie przerwania co jakiś czas (patrz datasheet). Na koniec uruchom przerwania i gotowe.

    Pozdrawiam Dawid.
  • REKLAMA
  • #5 5912227
    cineksuw
    Poziom 10  
    Ok wielkie dzięki za pomoc lecz nie trybi kodzik :( Oto błędy :
    Cytat:
    > "make.exe" all
    avr-gcc -g -Wall -O2 -mmcu=atmega8 -c -o lekcja1.o lekcja1.c
    In file included from lekcja1.c:7:
    c:/winavr-20080610/lib/gcc/../../avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete. Use <avr/interrupt.h>."
    lekcja1.c:16: warning: 'TIMER0_COMP_vect' appears to be a misspelled signal handler
    lekcja1.c: In function 'main':
    lekcja1.c:73: error: 'OCR0' undeclared (first use in this function)
    lekcja1.c:73: error: (Each undeclared identifier is reported only once
    lekcja1.c:73: error: for each function it appears in.)
    lekcja1.c:74: error: 'WGM01' undeclared (first use in this function)
    lekcja1.c:75: error: 'OCIE0' undeclared (first use in this function)
    make.exe: *** [lekcja1.o] Error 1

    > Process Exit Code: 2
    > Time Taken: 00:01

    A to moj kod:
    // Wyswietlacz ze wspolna katodąa
    
    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h> 
    #include <avr/interrupt.h>        
    #include <avr/signal.h>      
    
    volatile int c = 0; // cyfry
    volatile int d = 0; // dziesiatki
    volatile int j = 0; // jednosci
    volatile int liczba = 0;// liczba do wyswielenia
    
    // Przerwanie
    //
    ISR(TIMER0_COMP_vect)
    {
    // Definiowanie znakow
    //
        int cyf[9];
       
            cyf[0] = 0x3F; 
            cyf[1] = 0x06;
            cyf[2] = 0x5B;
            cyf[3] = 0x4F;
            cyf[4] = 0x66;
            cyf[5] = 0x6D;
            cyf[6] = 0x7D;
            cyf[7] = 0x07;
            cyf[8] = 0x7F;
            cyf[9] = 0x6F;
    //
    // Koniec definiowania znakow
    //
    // Rodzielanie na jednostki i dziesiatki 
    //
    	if(liczba > 9){
    	
    		j = liczba%10;
    		liczba = liczba/10;
    	
    		d = liczba%10;
    	
    	}else{
    	
    		j = liczba%10;
    		liczba = liczba/10;
    	
    		d = 0;
    
    	}  
    //
    // Koniec rozdzielania  
    //
    // Wyswietlanie 
    //
    PORTC = 0x27;
    PORTD = cyf[d];
    
    PORTC = 0x17;
    PORTD = cyf[j];
    // 
    // Koniec wyswietlania
    }
    //
    // Koniec przerwania
    
    int main(void)
    {
    
    // Konfiguracja timera w tryb CTC
    //
    	OCR0 = 150;                  
    	TCCR0 = _BV(WGM01) | _BV(CS02);
    	TIMSK |= _BV(OCIE0);  
    // 
    // Koniec kongifuracji 
    
    	
    
    // Ustawianie i/o 
    //	
    	DDRD = 0xFF; 
    	DDRC = 0x30; 
    //
    // Koniec ustawiania i/o 
     
           sei();
    
    while(1)
    {
    // Poprawianie bledow
    //
    	if(liczba < 0) liczba = 0;
    	if(liczba > 99) liczba = 99;
    //
    // Koniec poprawiania bledow
    //
    // Funkcje przycisków
    //
    	if(!(PORTC & 0x01)){
    		++liczba;
    		_delay_ms(10);
    		while(!(PINC & 0x01)){}
    		_delay_ms(10);
        }
    	if(!(PORTC & 0x02)){
    		--liczba;
    		_delay_ms(10);
    		while(!(PINC & 0x02)){}
    		_delay_ms(10);
        }
    //
    // Koniec ustawiania przyciskow
    }
    }
    
  • Pomocny post
    #6 5912362
    dawid512
    Poziom 32  
    Robisz własnego make'a? W avrstudio kompiluje sie bez problemu.
  • REKLAMA
  • #7 5912405
    cineksuw
    Poziom 10  
    Mam WinAVR i piszę w Programmers Notepad. Tak sam musiałem robić makefile tzn skopiowałem gdzies z google i pozmieniałem nazwe projektu i procesor . Możesz podesłać mi działające?? :)
  • Pomocny post
    #8 5912515
    BoskiDialer
    Poziom 34  
    To co dawid512 napisał jest najprawdopodobniej na atmega32. Musisz poczytać dokumentację i zmienić ten kod, gdyż timer0 na atmega8 ma trochę mniejsze możliwości.

    [dodano] Można też skorzystać z timer2, jego obsługa będzie łatwiejsza.
  • REKLAMA
  • Pomocny post
    #9 5912946
    dawid512
    Poziom 32  
    Masz racje BoskiDialer mój kod jest na m32, nie zwróciłem uwagi na to że m8 ma inny timer0. Tak czy siak wystarczy tylko lekko zmodyfikować ustawienia żeby korzystać z timera2.
  • #10 5913175
    cineksuw
    Poziom 10  
    Ok z przerwaniami poradziłem sobie dzięki dawidowi:) Teraz kolejny problem. Zapala mi się tylko jeden segment. Zamienie miejscami case 1 z case 0 to pali sie drugi segment. Wie ktoś co może być przyczyną?
    /* 
    PC0 - PC2 Przyciski
    PC4 - PC5 Anody
    PORTD - Katody
    */
    #define F_CPU 1000000L 
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    
    volatile int c = 0; // cyfry
    volatile int d = 9; // dziesiatki
    volatile int j = 7; // jednosci
    volatile int liczba = 29;// liczba do wyswielenia
    volatile int seg = 0;
    
    // Przerwanie
    //
    ISR(TIMER2_COMP_vect)
    {
    seg &= 2;
    // Definiowanie znakow
    //
        int cyf[10];
       
            cyf[0] = 0x3F;
            cyf[1] = 0x06;
            cyf[2] = 0x5B;
            cyf[3] = 0x4F;
            cyf[4] = 0x66;
            cyf[5] = 0x6D;
            cyf[6] = 0x7D;
            cyf[7] = 0x07;
            cyf[8] = 0x7F;
            cyf[9] = 0x6F;
    //
    // Koniec definiowania znakow
    //
    // Rodzielanie na jednostki i dziesiatki
    //
    /*  if(liczba > 9){
       
          j = liczba%10;
          liczba = liczba/10;
       
          d = liczba%10;
       
       }else{
       
          j = liczba%10;
          liczba = liczba/10;
       
          d = 0;
    
       } */
    //
    // Koniec rozdzielania 
    //
    // Wyswietlanie
    //
    DDRD = 0x00;
    
    switch(seg){
    
    	case 0:
    		PORTC = 0x2F;
    		PORTD = cyf[j];
    	break;
    	
    	case 1:
    		PORTC = 0x1F;
    		PORTD = cyf[d];
    	break;
    }
    seg++;
    }
    //
    // Koniec wyswietlania
    
    //
    // Koniec przerwania
    
    int main(void)
    {
    
    // Konfiguracja timera w tryb CTC
    //
       OCR2 = 150;                 
       TCCR2 = _BV(WGM21) | _BV(CS02);
       TIMSK |= _BV(OCIE2); 
    //
    // Koniec kongifuracji
    
    // Ustawianie i/o
    //   
       DDRD = 0xFF;
       DDRC = 0x30;
       PORTC = 0x0F;
    //
    // Koniec ustawiania i/o
     
           sei(); 
    
    while(1)
    {
    // Poprawianie bledow
    //
       if(liczba < 0) liczba = 0;
       if(liczba > 99) liczba = 99;
    //
    // Koniec poprawiania bledow
    //
    // Funkcje przycisków
    //
       if(!(PORTC & 0x01)){
          ++liczba;
          _delay_ms(10);
          while(!(PINC & 0x01)){}
          _delay_ms(10);
        }
       if(!(PORTC & 0x02)){
          --liczba;
          _delay_ms(10);
          while(!(PINC & 0x02)){}
          _delay_ms(10);
        }
    
    //
    // Koniec ustawiania przyciskow
    }
    }
  • Pomocny post
    #11 5913208
    dawid512
    Poziom 32  
    Przy każdym wywołaniu przerwania musisz wygasić wyświetlacze czyli to DDRD = 0x00; zastąpiłbym PORTC = 0xFF;
  • #12 5913247
    cineksuw
    Poziom 10  
    Nic to nie dało :(
  • Pomocny post
    #13 5913320
    BoskiDialer
    Poziom 34  
    "seg &= 2;" nie zostawia najniższego bitu, tylko drugi z kolei. Zamień 2 na 1. Ponieważ seg zwiększasz maksymalnie o 1, jego wartość będzie zawsze równa 0.

    Wpisanie 0 do DDRD spowoduje tylko wygaszenie wszystkiego.

    Co do kodu - definiowanie znaków wyrzuć z przerwania, daj do stałej tablicy. Tracisz na tym wiele cennych cykli.
  • #14 5913410
    cineksuw
    Poziom 10  
    Pomogła zmiana miejsca seg++; na koniec przerwania chociaż w sumie nawet jak byśmy zaczęli od 1 a nie od zera to kolejna pętla była by 0. Ale ważne że działa i dzięki za zainteresowanie:)

    Dodano po 49 [minuty]:

    Jeszcze takie małe pytanko na koniec. Program ten ciągnie średnio 60% możliwości procka (tak wyswietla proteus) jak zmniejszyć te obciążenie ? W sumie to prosty programik.
  • Pomocny post
    #15 5913763
    BoskiDialer
    Poziom 34  
    Nie wiem czym jest owe "ciągnięcie możliwości procka".

    Jeśli chodzi o moc obliczeniową, to procesor albo idzie na 100% dostępnej mocy obliczeniowej, albo śpi - nie ma tu systemu operacyjnego, który zarządzał by czasem procesora, funkcje _delay są oparte o pętle(zajęcie procesora na określoną liczbę cykli), nie o usypianie procesora na określony czas, zresztą nawet nop wymaga mocy obliczeniowej/cykli procesora. Nie widzę sensu modyfikowania programu tylko dla jakiegoś tam wskaźnika w programie, co innego jeśli chodziło by o rzeczywiste zmniejszenie zużycia prądu przez procesor.
REKLAMA