Skocz do zawartości

Attiny2313 konfiguracja PWM.


nyta

Pomocna odpowiedź

Witam. Mam prośbę o sprawdzenie konfiguracji PWM. Robię to pierwszy raz. Mikroprocesor jak w temacie Attiny2313. PWM ma działać jako 16 bitowy. PWM mam zamiar sterować prędkością pracy silników DC. Oto jak ustawiłem rejestry:

void pwm()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (0 << WGM11)|(1 << WGM10); 
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(0 << WGM13)|(0 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); 
  TCCR1C=0x00;
  TIMSK=0x00;
  TIFR=0X00;
  OCR1AH=0xff;
  OCR1AL=0xff;
  OCR1BH=0xff;
  OCR1BL=0xff; 
  TCNT1H=0x00;
  TCNT1L=0x00;

}

Mam taki problem ponieważ aby regulować PWM mam zamiar zmieniać wartość rejestru OCR1, natomiast aby PWM był 16 bitowy OCR1A musi być ustawiony na TOP czyli 0xffff (tak wyczytałem w nocie), a więc jak to zrobić aby zarówno PWM był 16 bitowy i można było go regulować.

Link do komentarza
Share on other sites

Tzn. pierwsze pytanie jest takie.

Konkretnie jaki tryb PWM chcesz używać szybki, z poprawną fazą, z poprawną fazą i częstotliwością.

Dla silników zalecane są dwa ostatnie, ale generują 2 x mniejszą częstotliwość.

Musisz także pamiętać że najpierw zapisuje się bajt MSB (H), a potem dopiero LSB (L) w trybie 16 bitowym.

Do OCRn wpisujesz współczynnik wypełnienia, a wartość TOP to wartość MAX do jakiej może zliczać w danym trybie Timer.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dla zaawansowanych trybów PWM zalicza się tryb poprawnej fazy. Od szybkiej modulacji PWM odróżnia go sposób pracy licznika. W jego przypadku zliczanie następuje na przemian w górę i w dół, a zmiana kierunku odbywa po osiągnięciu wartości maksymalnej lub zero..........

Tryb PWM poprawnej fazy jest dwukrotnie wolniejszy od szybkiej modulacji PWM, ponieważ jeden cykl jego pracy wymaga dwóch pełnych cykli licznikowych.

Więc się raczej nie pomyliłem bo napisałem:

Dla silników zalecane są dwa ostatnie, ale generują 2 x mniejszą częstotliwość.
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

nyta:

po pierwsze ustawiłeś tryb PWM, Phase Correct, 8-bit

po drugie proponował bym ci zamiast rejestru OCR1A do ustawiania wartości szczytowej użyć rejestru ICR1 (Tabela 46 pozycja 14 w dokumentacji ATtiny 2313)

po trzecie jeżeli użyjesz rejestru ICR1 do ustawienia wartości szczytowej to za pomocą rejestrów OCR1A i OCR1B możesz regulować wypełnienie. W tym przypadku odnoszą się one do rzeczywistych wyjść mikro-kontrolera OCR1A = PB3 i OCR1B = PB4

np:

ICR1=0xFFFE //(65534)

OCR1A=32767

OCR1B=32767

w takim przypadku uzyskasz 50% wypełnienie tzn. że jeżeli okres zliczania będzie trwał 30ms to stan wysoki będziesz miał przez 15ms, a stan niski przez 15ms

  • Lubię! 1
Link do komentarza
Share on other sites

void pwm()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  TCCR1C=0x00;
  TIMSK=0x00;
  TIFR=0X00;
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
  TCNT1H=0x00;
  TCNT1L=0x00;

}

Czy teraz jest ok? Czy muszę ustawiać rejestr TCNT1?

Link do komentarza
Share on other sites

Teraz powinno być dobrze. Jak masz oscyloskop to sprawdź na odpowiednich pinach czy pojawiła się fala prostokątna.

Darował bym sobie zerowanie odpowiednich komórek rejestrów. A jeżeli chcesz je zerować to rób to tak

TCCR1A &=~(1<

 

Nie musisz też zerować rejestrów TCCR1C, TIMSK, TIFR i rejestru TCNT1.

Link do komentarza
Share on other sites

Czy mógłbym prosić o sprawdzenie tego programu? zmontowałem płytkę i chciałbym zaprogramować mikroprocesor ale WinAVR pokazuje błędy

> Process Exit Code: 2

> Time Taken: 00:00

z tego co wyczytałem w poradniku powinno być

> Process Exit Code: 0

A oto program domyślam się że da się jakoś uprościć z pwm żeby tylko wpisywać wartość wypełnienia a konfiguracje zrobić na samym początku ale nie za bardzo wiem jak to napisać.

#include <avr/io.h>
#include <util/delay.h>

void pwm_lewo()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  //TCCR1C=0x00;
  //TIMSK=0x00;
  //TIFR=0X00;
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
  //TCNT1H=0x00;
  //TCNT1L=0x00;

void pwm_prawo()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  //TCCR1C=0x00;
  //TIMSK=0x00;
  //TIFR=0X00;
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
  //TCNT1H=0x00;
  //TCNT1L=0x00;

void pwm_max()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  //TCCR1C=0x00;
  //TIMSK=0x00;
  //TIFR=0X00;
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
  //TCNT1H=0x00;
  //TCNT1L=0x00;

}
int main(void)
{
/* Wszystkie linie portu B będą wyjściami */
DDRB = 0xff;
PORRTB = 0xff
/* PWszystkie linie portu D będą wejściami, PD2...PD5 podciągnięte do VCC */
DDRD = 0x00;
PORTD = 0x3c;
/* Początek nieskończonej pętli */
while(1)
{
/* Jeśli pierwszy przycisk wciśnięty LEWO */
if(!(PIND & 0x38))
{
	pwm_lewo ();
	PORTB = 0x9f;
	_delay_ms(100);
}
while(!(PIND & 0x38)) {}
_delay_ms(80);

/* Jeśli drugi przycisk wciśnięty PRAWO*/
if(!(PIND & 0x34)) 
{
	pwm_prawo ();
	PORTB = 0x7b;
	_delay_ms(100);
}
while(!(PIND & 0x34)) {}
_delay_ms(80);

/* Jeśli trzeci przycisk wciśnięty PRZÓD*/
if(!(PIND & 0x2c)) 
{
	pwm_max ();
	PORTB = 0x5b;
	_delay_ms(100);
}
while(!(PIND & 0x2c)) {}
_delay_ms(80);

/* Jeśli czwarty przycisk wciśnięty TYŁ*/
if(!(PIND & 0x1c)) 
{
	pwm_max ();
	PORTB = 0xbb;
	_delay_ms(100);
}
while(!(PIND & 0x1c)) {}
_delay_ms(80);
}
}
Link do komentarza
Share on other sites

Czy mógłby ktoś sprawdzić program:

#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>


void pwm_lewo()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
  }
void pwm_prawo()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;
}
void pwm_max()

{
  TCCR1A= (1 << COM1A1)|(0 << COM1A0)|(1 << COM1B1)|(0 << COM1B0)| (1 << WGM11)|(0 << WGM10); // Fast PWM
  TCCR1B= (0 << ICNC1)|(0 << ICES1)|(1 << WGM13)|(1 << WGM12)| (0 << CS12)|(0 << CS11)|(1 << CS10); // No prescaling
  ICR1=0xFFFE; //(65534)
  OCR1A=32767;
  OCR1B=32767;

}
int main(void)
{
/* Wszystkie linie portu B będą wyjściami */
DDRB = 0xff;
PORTB = 0xff;
/* PWszystkie linie portu D będą wejściami, PD2...PD5 podciągnięte do VCC */
DDRD = 0x00;
PORTD = 0x3c;
/* Początek nieskończonej pętli */
while(1)
{
/* Jeśli pierwszy przycisk wciśnięty LEWO */
if(!(PIND & 0x38))
{
	pwm_lewo ();
	PORTB = 0x9f;
	_delay_ms(100);
}
while(!(PIND & 0x38)) {}
_delay_ms(80);

/* Jeśli drugi przycisk wciśnięty PRAWO*/
if(!(PIND & 0x34)) 
{
	pwm_prawo ();
	PORTB = 0x7b;
	_delay_ms(100);
}
while(!(PIND & 0x34)) {}
_delay_ms(80);

/* Jeśli trzeci przycisk wciśnięty PRZÓD*/
if(!(PIND & 0x2c)) 
{
	pwm_max ();
	PORTB = 0x5b;
	_delay_ms(100);
}
while(!(PIND & 0x2c)) {}
_delay_ms(80);

/* Jeśli czwarty przycisk wciśnięty TYŁ*/
if(!(PIND & 0x1c)) 
{
	pwm_max ();
	PORTB = 0xbb;
	_delay_ms(100);
}
while(!(PIND & 0x1c)) {}
_delay_ms(80);
}
}


program skompilował się bezbłędnie jednak po wgraniu go na Attiny2313 nie działa. Sprawdzałem połączenia na płytce i powinno być wszystko ok. Płytka wykonana według schematu załączonego poniżej.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.