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

[Atmega8][C] Generowanie Przebiegu z użyciem Timrów

killerwo 02 Sty 2009 17:54 1316 4
REKLAMA
  • #1 5938246
    killerwo
    Poziom 10  
    Witam.

    Niestety mam problem dotyczący wygenerowanie przebiegu prostokątnego ALE przy użyciu tylko Timerów bez PWMa. Musze Wygenerować sygnał o okresie 270ms i wypełnieniu 90%( czyli po 243ms wartość na wyjściu musi być 0 przez resztę czasu) Później po naduszeniu przycisku okres ma sie zwiększyć do 810ms.Problem juz mam na samym początku z kodem:

    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    
    #define F_CPU 8000000L
    
    SIGNAL(SIG_OVERFLOW1)
    { 
    
       
            PORTB &= ~_BV(1); // na jak długo bedzie ustawione 0?
    		TCNT0 = 0; 
    
    }
    int main(void)
    {
    
    DDRB = 0xff; 
    DDRC = 0x00;
    PORTC = 0xFF;
    
    while(1) 
    
    
    { 
    
       PORTB |= _BV(1)
       TCNT1L = 53643; // start licznika
       TCCR1A = 0x00; // wartość końcowa licznika 
       TCCR1B =(1 << CS12) | (1 << CS10); //prescaler 1024
       TIMSK = _BV(TOIE1); //zgoda na przerwanie?
       
       sei(); 
     
     if bit_is_set(PORTC,1)
    
    
    
    }
    
    }


    skoro juz mam wyliczone ze 90% gdzie ma być 5V to 1893 cykle az do przeładowania przechodzimy tam i ustawiamy na wyjściu 0 i tu pojawia sie problem co dalej , czy w przerwaniu mamy zdeklarować po jakim czasie ma być znowu stan wysoki?to by musiały być 2 rodzaje przerwań ze po jednym czasie ma przejsc na niski a drugi raz na wysoki, idzie to jakoś uwzględnić w kodzie? a pozniej przy pomocy przycisku zmienić okres? Proszę o wskazówkę jestem zielony w C i w uC;/
  • REKLAMA
  • #2 5941054
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 5941630
    BoskiDialer
    Poziom 34  
    Najłatwiej bez PWM było by ustawić któryś timer, aby przepełniał się (lub pojawiało się przerwanie compare match) co 1ms (/64, 125 cykli), całą resztę zrealizować programowo. Potem tylko odpowiednio krótki kod, na 4 zmiennych powinno dać się zmieścić (jak długi ma być stan wysoki, jak długi stan niski, ile pozostało do końca aktualnego stanu i jaki aktualnie jest stan) - w przerwaniu aktualizować wyprowadzenie, w programie głównym odpowiednio aktualizować stan.
  • REKLAMA
  • #4 5941919
    killerwo
    Poziom 10  
    Witam.

    Jak by ktoś miał trochę dobrej woli i napisał kod do tego działania bo mimo że wasze podpowiedzi dużo dają to nie umiem ich zrealizować a z gotowym kodem łatwiej było by zrozumieć...zrozumiem jak uznacie ze to gotowiec i nie będziecie chcieli jednak to jest przykład jedynie treningowy.Pozdrawiam
  • #5 5942036
    BoskiDialer
    Poziom 34  
    Tak, uznamy to za gotowca, jedyne co Cię ratuje, to że mam trochę wolnego czasu, chociaż nie zwykłem pisać gotowce:
    #include <avr/io.h>
    #include <stdint.h>
    
    volatile uint16_t state_hi_time = 243;
    volatile uint16_t state_lo_time = 27;
    volatile uint16_t state_curr_timeout = 243;
    volatile uint8_t state_curr = 0;
    
    ISR(TIMER0_OVF_vect)
    {
    	// t0 jest zbyt prosty, trzeba załadować TCNT0 ręcznie
    	TCNT0 = (unsigned char)-125;
    	
    	uint16_t cto = state_curr_timeout;
    	cto--;
    	if(cto == 0)
    	{
    		// zmiana stanu
    		if(state_curr)
    		{
    			state_curr = 0;
    			cto = state_lo_time;
    
    			// TODO: ustawienie stanu niskiego na pinie
    		} else
    		{
    			state_curr = 1;
    			cto = state_hi_time;
    			
    			// TODO: ustawienie stanu wysokiego na pinie
    		}
    	}
    	state_curr_timeout = cto;
    }
    
    int main(void)
    {
    	// TODO: konfiguracja wyjścia, pinu wejściowego od przycisku
    
    	// t0: /64, 125ck
    	TCCR0 = _BV(CS01)+_BV(CS00);
    	TCNT0 = (unsigned char)-125;
    	// zezwolenie na przerwanie TOV0 (pozostałe przerwania od timerów wyłączone)
    	TIMSK = _BV(TOIE0);
    	
    	sei();
    	
    	while(1)
    	{
    		// TODO: jeśli przycisk naciśnięty
    		if(0)
    		{
    			uint8_t _sreg = SREG;
    			cli();
    
    			state_hi_time = 729;
    			state_lo_time = 81;
    			
    			SREG = _sreg;
    		}
    	}
    	return 0;
    }
    kod napisany od ręki, nawet nie sprawdzany czy się kompiluje.
REKLAMA