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++][ATmega8535] PWM -> inny_pin

rafalkosc 24 Mar 2011 16:58 939 2
REKLAMA
  • #1 9317206
    rafalkosc
    Poziom 13  
    Cześć!

    Przez nieuwagę upaliłem piny, na które wyprowadzone sa domyślnie timery, a potrzebuję PWMu. Wpadłem więc na pomysł, by użyć przerwań TIMERx_COMP. Niby przerwania są obsługiwane (jak dam głupotę w stylu {zapal_pin; czekaj; zgaś_pin; czekaj;}, to widać działanie), ale nie udało mi sie uzyskać PWMu, które mogłoby sterować ledem.
    Może miałby ktoś pomysł? Siedzę parę godzin i nic.

    
    #define F_CPU 12000000UL
    
    #include "halogen.h"
    #include "przekaznik.h"
    #include "klawiatura.h"
    #include "tools.h"
    #include "main.h"
    #include "debug.h"
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    klawiatura kbd;
    
    halogen lampa1(OCR2, 0, 255);
    halogen lampa4(OCR1A, 0, 1023);
    halogen lampa3(OCR1B, 0, 1023);
    halogen lampa2(OCR0, 0, 255);
    
    przekaznik sw1(PORTC, PC4);
    
    ISR(TIMER2_COMP_vect){
        PORTC ^= _BV(PC7);
        TIFR &= ~_BV(OCF2);
    
    
    }
    
    
    void inicjuj(){
        int i;
    
        DDRA = 0x00;
        DDRB = _BV(DDB3) | _BV(DDB2);
        DDRC = 0xFF;
        DDRD = _BV(DDD4) | _BV(DDD5) | _BV(DDD7);
    
        PORTA = 0xFF;
    
    
    
         for(i = 0; i < 3; i++){ //blysniecie na start
            PORTB = 0x0C;
            PORTD = 0xD0;
            czekaj_ms(100);
    
            PORTB = 0x00;
            PORTD = 0x00;
            czekaj_ms(100);
        } //for i
    
    
        TCCR0 =	  _BV(WGM00)	//fast PWM@CK
    		| _BV(WGM01)
    		| _BV(COM00)
    		| _BV(COM01)
    		| _BV(CS00)
    		| _BV(CS01)
            | _BV(CS02);
    
        OCR1A = 100;
        TCCR1A =	  _BV(WGM10)
    		| _BV(WGM11)
    		| _BV(COM1B0)
    		| _BV(COM1B1)
    		| _BV(COM1A0)
    		| _BV(COM1A1);
    
        OCR1B = 100;
        TCCR1B =      _BV(WGM12)
    		//| _BV(WGM13)
    		| _BV(CS10);
    		//| _BV(CS11);
    		//| _BV(CS12);
    
    
        TCCR2 =	  _BV(WGM20)	//fast PWM@CK
    		//| _BV(WGM01)
    		| _BV(COM20)
    		| _BV(COM21)
    		| _BV(CS20);
    //		| _BV(CS21);
    //        | _BV(CS22);
    
    
        TIMSK = _BV(OCIE2);
      //  SREG |= _BV(7);
        sei();
    
    
    } //inicjuj
    
    
    int main(){
        int on_off = 0;
        bool strob = 0;
    
        inicjuj();
    
        while(1){
    
    	if(kbd.klawisz(0)){
            czekaj_ms(200);
            if(kbd.klawisz(0)){
                while(kbd.klawisz(0)){
                    lampa1.pulsuj();
                } //while
    	    } //if
    	    else lampa1.przelacz();
    	}
    
        if(kbd.klawisz(1)){
            czekaj_ms(200);
            if(kbd.klawisz(1)){
                while(kbd.klawisz(1)){
                    lampa2.pulsuj();
                } //while
    	    } //if
    	    else lampa2.przelacz();
    	}
    
        if(kbd.klawisz(2)){
            czekaj_ms(200);
            if(kbd.klawisz(1)){
                while(kbd.klawisz(2)){
                    lampa3.pulsuj();
                } //while
    	    } //if
    	    else lampa4.przelacz();
        }
    
        if(kbd.klawisz(3)){
           czekaj_ms(200);
            if(kbd.klawisz(1)){
                while(kbd.klawisz(3)){
                    lampa4.pulsuj();
                } //while
    	    } //if
    	    else lampa4.przelacz();
        }
    
        if(strob){
            sw1.przelacz();
            lampa1.przelacz();
            lampa2.przelacz();
            lampa3.przelacz();
            lampa4.przelacz();
            czekaj_ms(10000);
        }
    
        if(kbd.klawisz(4)){
           if(strob) strob = false; else strob = true;
            while(kbd.klawisz(4));
        }
    
       if(kbd.klawisz(6)){
            if(!on_off){
                lampa1.zalacz();
                lampa2.zalacz();
                lampa3.zalacz();
                lampa4.zalacz();
                sw1.zalacz();
                on_off = true;
            }
            else{
                lampa1.wylacz();
                lampa2.wylacz();
                lampa3.wylacz();
                lampa4.wylacz();
                sw1.wylacz();
                on_off = false;
            }
    
            while(kbd.klawisz(6));
        }
    
        } //for(;;)
    } //main
    
  • REKLAMA
  • Pomocny post
    #2 9317511
    Szumlus
    Poziom 17  
    Witam,

    Uruchom normalnie Timer w trybie PWM. Teraz dodadkowo potrzebne Ci będa dwa przerwania tego timera: CTC i Timer Overflow.
    W przerwaniu CTC ustawiaj pin a w przerwaniu OVF go zeruj lub odwrotnie jeśli chcesz tryb invert PWM. Nie zapomnij o od maskowaniu przerwań i ustawieniu globalnej flagi zezwalającej na przerwania oraz nie przesadź z częstotliwością PWM aby procesor się wyrabiał. Danie w tym wypadku preskalera na 1 raczej odpada polecam wartości od 8 w góre.

    Pozdrawiam,
    Marcin
  • #3 9317674
    rafalkosc
    Poziom 13  
    Dziękuję za odpowiedź. Rzeczywiście, pin teraz wyraźnie "podąża", tzn, jeśli ustawię wypełnienie na 0, lampka na zastępczym pinie gaśnie, jak ustawię wyższe wypełnienie, zapala się, ale o płynności sterowania nie można, niestety mówić. Chyba jednak będę musiał odżałować te 15zł ;)
REKLAMA