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

[ATmega32][C][2 przerwania od przepełnienia licznika T0 i T2

aniasta 31 Sty 2010 16:41 3397 6
  • #1 7622011
    aniasta
    Poziom 10  
    Witam serdecznie.
    Piszę program, w którym muszę zliczać przychodzące impulsy z licznika energetycznego do procka. Aby nie zliczać impulsów pochodzących od drgań styków wymyśliłam takie rozwiązanie.
    Jeśli na INT0 przyjedzie zbocze opadające, włącz licznik T0. Gdy licznik przepełni się- minie 32ms i w tym miejscu będzie poziom niski na pinie, to atmega uzna impuls jako dobry. Rozwiązanie to działa.
    Licznik T2 odlicza mi 1 sekundę(wysyłam na RS komputera co 5 sekund ilość zliczonych impulsów). T2 w trybie asynchronicznym, kwarc 32, 768Hz.
    Problem tkwi w tym, że jeśli włączę licznik T2 to impulsy nie są naliczane, nie wchodzi w przerwanie od T0 lub INT0. Nie wiem jak z tym problemem sobie poradzić. Proszę o pomoc. Jestem początkująca:)
    
    
    #define F_CPU 4000000UL 
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    
    #define UART_BAUD   9600         //prędkość transmisji
    #define UART_CONST   (F_CPU/(16ul*UART_BAUD)-1)
    
    unsigned char x=0;
    volatile unsigned char copiec=0;
    
    volatile unsigned char impuls=0;
    
    volatile unsigned char i=0, sekunda=0;
    
    void USART_Transmit( unsigned char data )
    {
       while ( !( UCSRA & (1<<UDRE)) );   /* Wait for empty transmit buffer */
       UDR = data;                  /* Put data into buffer, sends the data */
    }
    
    unsigned char USART_Receive( void )
    {
       while ( !(UCSRA & (1<<RXC)) );            /* Wait for data to be received */
       return UDR;                           /* Get and return received data from buffer */
    }
    
    void USART_Init( unsigned int ubrr )
    {
       UBRRH = (unsigned char)(ubrr>>8);         /* Set baud rate */
       UBRRL = (unsigned char)ubrr;   
       UCSRB = (1<<RXEN)|(1<<TXEN);      /* Enable Receiver and Transmitter */   
       UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);   /* Set frame format: 8data, 2stop bit */
    }
    
    
    SIGNAL(SIG_INTERRUPT0)
    {
    	TCCR0 = (0<<CS00)|  (0<<CS01) | (1<<CS02); //wlacz t0
    }
    
    
    ISR(TIMER0_OVF_vect){ //przerwanie co 16 ms
    
    	i++;
    	if (i==2){ //zeby bylo przerwanie co 32ms 
    		i=0;
    		if (bit_is_clear(PIND,2)){
    		PORTD ^=_BV(7); //dioda
    		impuls++;
    		TCCR0 =0; //wylacz T0
    		}
    		}
    }
    
    ISR (TIMER2_OVF_vect){ //co 1s 
    sekunda++;
    	if (sekunda==5 && copiec==1){
    	konwertuj_imp(impuls); //co 5 sekund transmisja na rs ilosc impulsow
    	napisz("  "); //2 spacje
    	sekunda=0;
    	PORTD ^=_BV(7); //dioda
    	}
    }
    
    int main(void){
    DDRD=0b10000000; //dioda PD.7 licznik PD.2
    PORTD=0b10000100;//
    
    //ustawienia TIMER0 ->co 16 ms
    TCCR0 = (0<<CS00)|  (0<<CS01) | (1<<CS02);  // preskaler fclk/256 
    TCNT0 = 0; //wartosc poczatkowa   16ms
    
    //ustawienia TIMER2 ->co 1 s
    ASSR |= _BV(AS2);   // TC2 z taktowania zegarem CPU na generator asynchroniczny
    TCCR2 = (1<<CS20)|  (0<<CS21) | (1<<CS22);  // preskaler fclk/128 
    TCNT2 = 0; //wartosc poczatkowa   32768/128/256=1hz, czyli co 1s
    
    sei();// globalne odblokowanie przerwań
    
    
    GIMSK=0b01000000; // Port INT0 is set (one)
    MCUCR = 0b00000010; // The rising edge of INT0 generates    
                     // an interrupt request. 
    
    USART_Init(UART_CONST);
    TIMSK = 1<<TOIE0;    // włącz przerwania z TC0
    
    	while (1){
    	x=USART_Receive();
    
    		if (x=='s'){
    		sekunda=0;
    		copiec=1;
    		napisz("\rIlosc impulsow aktualizowana co 5 sekund:\r");
    		TIMSK = 1<<TOIE2; //wlacz t2 czyli wysylaj co 5 s stan impulsow
    		}
             }
    }
    
    
  • #2 7622033
    _Robak_
    Poziom 33  
    Hmm a co jeśli będą te drgania również po 32ms, i akurat sie trafi na stan taki jak ma być? Może warto spróbować sprzętowo sie pozbyć drgań, filtrem RC np.
  • #3 7622058
    aniasta
    Poziom 10  
    Może i masz rację. Nie przypuszczałam, że coś takiego się trafi. Bardziej mnie jednak martwą te dwa przerwania, nachodzące na siebie...gdyż nie mogę zliczać impulsów w ogóle po włączeniu licznika T2.
    Wykrywa zbocze, ale T0 nie włącza się.
  • #4 7622172
    _Robak_
    Poziom 33  
    A więc sprawa jest prosta
    
    while (1){ 
       x=USART_Receive(); 
    
          if (x=='s'){ 
          sekunda=0; 
          copiec=1; 
          napisz("\rIlosc impulsow aktualizowana co 5 sekund:\r"); 
          TIMSK = 1<<TOIE2; //wlacz t2 czyli wysylaj co 5 s stan impulsow 
          } 
             }
    

    zmień na
    
    while (1){ 
       x=USART_Receive(); 
    
          if (x=='s'){ 
          sekunda=0; 
          copiec=1; 
          napisz("\rIlosc impulsow aktualizowana co 5 sekund:\r"); 
          TIMSK| = 1<<TOIE2; //wlacz t2 czyli wysylaj co 5 s stan impulsow 
          } 
             }
    
  • #5 7622194
    aniasta
    Poziom 10  
    Hmmm...A gdzie mam błąd, bo nie widzę, co na co mam zmienić?
  • Pomocny post
    #6 7622225
    _Robak_
    Poziom 33  
    Dokładnie w tej linijce
    
    TIMSK | = 1<<TOIE2; //wlacz t2 czyli wysylaj co 5 s stan impulsow
    

    Przez ustawienie TOIE2 kasowałaś TOIE0
  • #7 7622236
    aniasta
    Poziom 10  
    Wow!
    
    TIMSK = 1<<TOIE2 | 1<<TOIE0;
    

    Zapewne o to chodziło!
    Myślałam, że jak w mainie ustawię że przerwanie od przepełnienia T0 będzie aktywne, to zawsze będzie aktywne.
    Zapamiętam to na przyszłość.
    Dziękuję bardzo za pomoc:) Pozdrawiam.
REKLAMA