Skocz do zawartości

ATtiny85 - generacja PWM z f > 20 KHz i krokiem 0,5 us


Pomocna odpowiedź

11 godzin temu, kaczakat napisał:

Witam

Zrobiłem coś podobnego na attiny13, ale skok 1us, może przez zegar 9600000, na attiny45 po ustawieniu na 16MHz w Arduino (ja akurat mam core Attiny Microcontrollers) po prostu chodzi OK z krokiem 500n, więc pewnie rejestry są takie same i już nie sprawdzałem. Wypełnienie ustala się potencjometrem na PB2, wyjście PWM na PB1. PWM ma ~20kHz, pewnie zależy od egz.


#define LED PB1
void adc_setup (void)
{
    // Set the ADC input to PB2/ADC1
    ADMUX |= (1 << MUX0);
    ADMUX |= (1 << ADLAR);

    // Set the prescaler to clock/128 & enable ADC
    // At 9.6 MHz this is 75 kHz.
    // See ATtiny13 datasheet, Table 14.4.
    ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}

int adc_read (void)
{
    // Start the conversion
    ADCSRA |= (1 << ADSC);

    // Wait for it to finish
    while (ADCSRA & (1 << ADSC));

    return ADCH/2;
}

void pwm_setup (void)
{
    // Set Timer 0 prescaler to clock/8.
    // At 9.6 MHz this is 1.2 MHz.
    // See ATtiny13 datasheet, Table 11.9.
    TCCR0B |= (1 << CS01);

    // Set to 'Fast PWM' mode TOP=0xFF
   // TCCR0A |= (1 << WGM01) | (1 << WGM00);

    // Set to 'Fast PWM' mode TOP= OCR0A
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // co ciekawe ten WGM02 jest w innym rejestrze
    TCCR0B|= (1 << WGM02);


    OCR0A = 99;

    // Clear OC0B output on compare match, upwards counting.
//    TCCR0A |= (1 << COM0B1);
    // Set OC0B output on compare match, down counting.
    TCCR0A |= (1 << COM0B1)|(1 << COM0B0);
}

void pwm_write (int val)
{
    OCR0B = val;
}

int main (void)
{


    // LED is an output.
    DDRB |= (1 << LED);

    adc_setup();
    pwm_setup();

    while (1) {
        // Get the ADC value
       uint8_t adc_in = adc_read();
        // Now write it to the PWM counter

        pwm_write(adc_in);
    }
}

Cześć,

dzięki za kod. W weekend wypróbuję.

Pozdrawiam

 

Gość es2

Nie widzę nigdzie informacji o wymaganej rozdzielczości. Jeśli wystarczy 8-bit to nie trzeba PLL. Nawet przy 8MHz uzyska się 31.250Hz rozdzielczość  125ns.

Dnia 7.12.2018 o 01:34, kaczakat napisał:

Witam

Zrobiłem coś podobnego na attiny13, ale skok 1us, może przez zegar 9600000, na attiny45 po ustawieniu na 16MHz w Arduino (ja akurat mam core Attiny Microcontrollers) po prostu chodzi OK z krokiem 500n, więc pewnie rejestry są takie same i już nie sprawdzałem. Wypełnienie ustala się potencjometrem na PB2, wyjście PWM na PB1. PWM ma ~20kHz, pewnie zależy od egz.

Cześć,

sprawdziłem dzisiaj ten kod na ATtiny85 (Atmel Studio 7 + AVR-ISP-MK2) i nie działa (nie generuje PWM na pinie PB1). Odczyty z ADC zastąpiłem po prostu wartością 128 i wyeliminowałem funkcje ADC  bo są tu zbędne. Wydaje mi się, że dla timera zero są inne piny nim sterowane niż PB1, ale mogę się mylić.

Pozdrawiam

Gość es2
3 godziny temu, FlyingDutch napisał:

Wydaje mi się, że dla timera zero są inne piny nim sterowane niż PB1, ale mogę się mylić.

Sprawdź w nocie katalogowej.

Ponadto, Tiny13 i Tiny85 maja różne timery.

Jak wpisałeś 128 to  faktycznie nie będzie działać. Po to jest potencjometr i led by działanie PWM można było zobaczyć, a trudniej skopać, więc jak już to trzeba ustawić na połowę zakresu, tu akurat 49 (OCR0A wpisane jest na sztywno 99, regulujesz OCR0B 0-99, 100 kroków). 

Kod był dla Arduino, dla Eclipse trzeba dopisać linijkę #include <avr/io.h> , a dla AS jeszcze FCPU. Przy przeklejaniu dodaje trzy kropki/apostrofy (niedrukowalne w okienku tu na forum) w funkcji adc_setup i na końcu, nie wiem skąd, załączam plik z kodem.

Modyfikacje sobie rób jak już będziesz widział efekt. Nawet jakby faktycznie ustawienia i rejestry były inne to chyba idea działania jest ważna, a nie nazwy rejestrów, które po porównaniu PDF obu procków po prostu się podmienia.

PWMAttiny45_03.jpg

sketch_dec13aattinyPWM.zip

222.jpg

1111.jpg

AttinyPWM03.jpg

  • Pomogłeś! 1
Gość es2
(edytowany)
4 godziny temu, kaczakat napisał:

a dla AS jeszcze FCPU.

FCPU należy ustawiać w projekcie a nie kodach źródłowych.

Edytowano przez es2
(edytowany)
8 godzin temu, kaczakat napisał:

Jak wpisałeś 128 to  faktycznie nie będzie działać. Po to jest potencjometr i led by działanie PWM można było zobaczyć, a trudniej skopać, więc jak już to trzeba ustawić na połowę zakresu, tu akurat 49 (OCR0A wpisane jest na sztywno 99, regulujesz OCR0B 0-99, 100 kroków). 

Kod był dla Arduino, dla Eclipse trzeba dopisać linijkę #include <avr/io.h> , a dla AS jeszcze FCPU. Przy przeklejaniu dodaje trzy kropki/apostrofy (niedrukowalne w okienku tu na forum) w funkcji adc_setup i na końcu, nie wiem skąd, załączam plik z kodem.

Modyfikacje sobie rób jak już będziesz widział efekt. Nawet jakby faktycznie ustawienia i rejestry były inne to chyba idea działania jest ważna, a nie nazwy rejestrów, które po porównaniu PDF obu procków po prostu się podmienia.

Cześć,

bardzo Ci dziękuję - rzeczywiście kod działa prawidłowo (przestawiłem prescaler na brak podziału).

Wklejam kod dla Atmel Studio (cz. PWM = 22 KHz):

#include <avr/io.h>

#define F_CPU (16000000UL)
#define LED PB1


void pwm_setup (void)
{
	// Set Timer 0 prescaler to clock/8.
	// At 9.6 MHz this is 1.2 MHz.
	// See ATtiny13 datasheet, Table 11.9.
	TCCR0B |= (1 << CS00);

	// Set to 'Fast PWM' mode TOP=0xFF
	// TCCR0A |= (1 << WGM01) | (1 << WGM00);

	// Set to 'Fast PWM' mode TOP= OCR0A
	TCCR0A |= (1 << WGM01) | (1 << WGM00);
	// co ciekawe ten WGM02 jest w innym rejestrze
	TCCR0B|= (1 << WGM02);


	OCR0A = 90;

	// Clear OC0B output on compare match, upwards counting.
	//    TCCR0A |= (1 << COM0B1);
	// Set OC0B output on compare match, down counting.
	TCCR0A |= (1 << COM0B1)|(1 << COM0B0);
}

void pwm_write (int val)
{
	OCR0B = val;
}

int main(void)
{
    /* Replace with your application code */
    // LED is an output.
    DDRB |= (1 << LED);

    //adc_setup();
    pwm_setup();

    while (1) 
    {
        // Get the ADC value
        uint8_t adc_in = 34;
        // Now write it to the PWM counter

        pwm_write(adc_in);
    }
}

Pozdrawiam

Edytowano przez FlyingDutch

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...