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

[ATTINY2313 C+]Problem z przepisaniem stanu pinu na inny pin

meninio 28 Sie 2009 00:49 1283 2
  • #1 6952189
    meninio
    Poziom 10  
    Witam.
    Mam oto tutaj taki programik, który imituje generator fali prosotkątnej o regulowanej częstotliwości i jitter, jednak nie jest to tu istotne.
    Korzystając z rejestru porównań i pracy licznika w trybie CTC generowany jest sygnał prostokątny na wyjściu OC0A, czyli na 3 trzecim pinie portu B, czyli PB2.
    Jednak niezbędnym dla mnie jest (bo mam już gotową płytkę z wyprowadzeniami itp id), żeby ten sygnał znalazł się na pierwszym pinie portu D czyli PD0, czyli chodzi mi o przepisanie stanu portu PB2 na port PD0. Trochę już nad tym główkuję i mi nie wychodzi.
    Drodzy użytkownicy forum macie na to jakiś prosty sposób?
    Oto kod:
    #define F_CPU 8000000L 
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdlib.h> 
    
    volatile int jitter=1,freq=0;
    
    SIGNAL(SIG_TIMER0_COMPA)
    {
      OCR0A=rand()%jitter+freq+30;
    }
    
    int main (void)
    {
       DDRD  = 0x01;
       DDRB=0x04;
       PORTB=0x00;
       PORTD = 0x0C;
       sei();
       TCCR0A=0x42;
       TCCR0B=0x81;
       OCR0A=30;
       TIMSK=0x01;
       while(1){
    		while (!(PIND & 0x08)) 
    		{
    			jitter++;
    			if (jitter>25) jitter=1;
    			while (!(PIND & 0x08)) {}
    		}
    			while (!(PIND & 0x04)) 
    		{
    			freq=freq+5;
    			if (freq>101) freq=0;
    			while (!(PIND & 0x04)) {}
    		}
       }
       return(0);
    }


    Bardzo serdecznie z góry dziękuję za wszelkie sugestie.
  • #2 6952312
    kwesoly
    Poziom 15  
    Jeśli dobrze rozumiem przerwanie SIG_TIMER0_COMPA (wywołuje się przy każdym zboczu sygnału wyjściowego?) to dołożenie w nim ręcznej modyfikacji pinu nie zmieni praktycznie szybkości działania. Możesz też użyc po prostu podstawowego Timera,i zrealizować to programowo ustawiając ten pin w przerwaniach (do dyspozycji dwa przerwania OCIE0 (A i B) oraz TOIE0)

    Poza tym:

    Nie bez przyczyny zamiast:

    TCCR0A=0x42;
    TCCR0B=0x81;

    używa się zapisu

    TCCR0A=(1 << WGM01)|(1 << ...); //bit 2 zarezerwowany!
    TCCR0B=(1 << WGM02)|(1<<CS00); //bit 3, bit 0

    W dokumentacji użytego uC na przykład w rejestrze TCCR0A bity 2 i 3 są zarezerwowane, więc mogę przypuszczać że się pomyliłeś używając wartości szesnastkowych. Pomijając już zarezerwowany bit, mamy wybrane tylko WGM01 i WGM02, co z kolei daje zarezerwowany tryb pracy (str 79 ww datasheet, Mode 6 Reserved). Mam nadzieję ze trochę pomogłem i zwróciłem uwagę na pomyłki. Po przejrzeniu datasheeta jak nasuną sie dalsze pytania zapraszam.

    PS.
    Offtop:
    OCR0A=rand()%jitter+freq+30;
    wygląda krótko, ale dość znacznie ogranicza/ograniczy wydajność tego przerwania, co zmniejszy i wydajność i dokładność. Zwróć uwagę że po wystąpieniu tego przerwania procesor musi obliczyć całą prawą stronę zanim zmodyfikuje rejestr OCR0A - nie mam poda ręką jak tego przesymulować, ale nie byłbym zaskoczony gdyby bez preskalera przed zakończeniem tego przerwania wystąpiło następne.
  • #3 6952465
    _Robak_
    Poziom 33  
    Uzyj licznika w trybie ctc (tak jak masz teraz), lecz ustaw bity COMx tak zeby na pinie PB2 nic sie nie dzialo. Ustaw w rejestrze TIMSK odpowiedni bit OCIE i w przerwaniu z tego licznika mozesz juz ustawiac dowolne piny dowolnych portow w dowolnej konfiguracji :)
REKLAMA