 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
rakec14 Član

Pridružen-a: Ned 20 Sep 2009 10:50 Prispevkov: 11 Aktiv.: 0.06 Kraj: Celje
|
Objavljeno: Čet Sep 27, 2012 1:04 am Naslov sporočila: PWM in Atmega32-nastavljanje frekvence in duty cycla |
|
|
Pozdravljeni!
Sem začetnik v programiranju AVR-jev in delu s C-jem. Zanima me, kako napisati kodo za Atmega32, da bi lahko nastavljal frekvenco in duty cycle PWM-ja z gumboma + in - . To je moja koda (malo sposojena, malo napisana), ki ne dela.
Koda: |
#include <avr/io.h>
#include <util/delay.h>
void pwm_init ()
{
TCCR1A = (1<<COM1A1) | (1<<WGM11);//Clear OC1A on compare, bottom
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS12);//Fast PWM top=ICR1 , 256 prescaler
ICR1=0x0014; // set TOP
OCR1A=0x00FF; // set duty cycle
DDRD |= (1<<PD5);// set PD5 as output
}
void main ()
{
uint8_t duty;
duty = 0;
uint8_t freq;
freq = 0;
while(1)
{
// increment duty
if (PD0)
{
if (duty <= 245)
{
//increment duty by 10
duty = duty + 10;
// set the duty in OCR1A
OCR1A = duty;
}_delay_ms(35);
}
// decrement duty
if (PD1)
{
if (duty >= 10)
{
//decrement duty by 10
duty = duty - 10;
// set the duty in OCR1A
OCR1A = duty;
_delay_ms(35);
}
}
//increment freq
if (PD2)
{
if (freq >=1)
{
//increment freq by 10
freq = --freq;
//set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
// decrement freq
if (PD3)
{
if (freq <= 18)
{
//decrement freq by 10
freq = ++freq;
// set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
}
}
// repeat this forever
}
}
|
Že vnaprej se vam zahvaljujem za pomoč! |
|
Nazaj na vrh |
|
 |
urosg Član


Pridružen-a: Pet 27 Apr 2007 14:30 Prispevkov: 565 Aktiv.: 2.56
|
Objavljeno: Čet Sep 27, 2012 7:12 am Naslov sporočila: |
|
|
Sicer sam ne delam nič z ATMega ampak programiram kaj drugega, iz samega stališča osnovne zanke bi rekel da napak ni, bolj se mi poraja vprašanje če je inicializacija in nastavitev I/O pinov pravilna.
Poleg tega imaš sicer definirano funkcijo "pwm_init()" vendar je niti ne pokličeš na začetku main().
Za lažjo pomoč naprej bo pripomoglo tudi to če boš priložil shemo vezja, ki ga imaš, saj bomo le tako lahko točno videli, če naslavljaš prave pine. |
|
Nazaj na vrh |
|
 |
gumby Član


Pridružen-a: Sob 28 Apr 2007 12:32 Prispevkov: 4066 Aktiv.: 18.41
|
Objavljeno: Čet Sep 27, 2012 8:53 am Naslov sporočila: |
|
|
PD0..PD3 niso dejanska stanja na pinu, ampak samo indeks bita v registrih. _________________ Tule nisem več aktiven. |
|
Nazaj na vrh |
|
 |
rakec14 Član

Pridružen-a: Ned 20 Sep 2009 10:50 Prispevkov: 11 Aktiv.: 0.06 Kraj: Celje
|
Objavljeno: Čet Sep 27, 2012 10:26 am Naslov sporočila: |
|
|
Spremenil sem vhodne pine na port B in vključil pwm_init() v main zanko, vendar vseeno ne da nič od sebe. Program preizkušam na programatorju STK500. Na PORTB imam priključene tipke, na PORTD pa ''ledice''.
Popravljena koda:
Koda: |
#include <avr/io.h>
#include <util/delay.h>
void pwm_init ()
{
TCCR1A = (1<<COM1A1) | (1<<WGM11);//Clear OC1A on compare, bottom
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS12);//Fast PWM top=ICR1 , 256 prescaler
ICR1=0x0014; // set TOP
OCR1A=0x00FF; // set duty cycle
DDRD |= (1<<PD5);// set PD5 as output
DDRB = 0x00; //PORTB as input
PORTB = 0x0F; //enable pull ups for pins 0, 1, 2, 3
}
int main (void)
{
uint8_t duty;
duty = 0;
uint8_t freq;
freq = 0;
pwm_init;
while(1)
{
// increment duty
if (PINB == 0x01)
{
if (duty <= 245)
{
//increment duty by 10
duty = duty + 10;
// set the duty in OCR1A
OCR1A = duty;
}_delay_ms(35);
}
// decrement duty
if (PINB == 0x02)
{
if (duty >= 10)
{
//decrement duty by 10
duty = duty - 10;
// set the duty in OCR1A
OCR1A = duty;
_delay_ms(35);
}
}
//increment freq
if (PINB == 0x04)
{
if (freq >=1)
{
//increment freq by 10
freq = --freq;
//set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
// decrement freq
if (PINB == 0x08)
{
if (freq <= 18)
{
//decrement freq by 10
freq = ++freq;
// set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
}
}
// repeat this forever
}
}
|
|
|
Nazaj na vrh |
|
 |
lojzek Član



Pridružen-a: Pet 25 Jan 2008 8:00 Prispevkov: 3387 Aktiv.: 15.99
|
Objavljeno: Čet Sep 27, 2012 10:41 am Naslov sporočila: |
|
|
@rakec14: če delaš z AVR Studiem, poiskusi program najprej v njegovem programskem simulatorju... Tam boš hitro videl (sploh pri tem kratkem programu), kje ga v temo brcaš..
Kot prvo mi pa niso tisti
stavki všeč. Zakaj: ker običajno uporabljamo na vhodih interne pullup upore (normalna vrednost vhoda = 1 in tako bi PINB imel vrednost 0xFF, ko ni nič pritisnjenega), tipka pa vhod postavi na maso (vrednost vhoda = 0, torej 0b11111101 ali 0xFD).
In tako bi za uresničitev tega pogoja moral pritisniti tipke na vhodih PB0, PB2 - PB7 naenkrat.
Kapiš?
EDIT: nisem se pa poglagljal v registre in njihovo definicijo, ki jo izvedeš na začetku... Če so te stvari prav nastavljene, lahko hitro preveriš s simulatorjem in datasheetom... |
|
Nazaj na vrh |
|
 |
tilz0R Član


Pridružen-a: Čet 31 Maj 2012 15:39 Prispevkov: 898 Aktiv.: 5.65 Kraj: Črnomelj
|
Objavljeno: Pet Sep 28, 2012 3:15 pm Naslov sporočila: |
|
|
ampak funkcije pwm_init() še vedno nisi klical v glavnem programu  _________________ Knowledge sharing is caring.
majerle.eu | stm32f4-discovery.net |
|
Nazaj na vrh |
|
 |
rakec14 Član

Pridružen-a: Ned 20 Sep 2009 10:50 Prispevkov: 11 Aktiv.: 0.06 Kraj: Celje
|
Objavljeno: Ned Sep 30, 2012 3:06 pm Naslov sporočila: |
|
|
Sem dal pwm_init; v glavno zanko, ampak še kar ne dela. Ne vem, če nimam narobe definiran ICR1, ampak ne vem, kako bi ga moral nastaviti.
Koda: |
#include <avr/io.h>
#include <util/delay.h>
void pwm_init ()
{
TCCR1A = (1<<COM1A1) | (1<<WGM11);//Clear OC1A on compare, bottom
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS12);//Fast PWM top=ICR1 , 256 prescaler
ICR1=0x0014; // set TOP
OCR1A=0x00FF; // set duty cycle
DDRD |= (1<<PD5);// set PD5 as output
DDRB = 0x00; //PORTB as input
PORTB = 0x0F; //enable pull ups for pins 0, 1, 2, 3
}
int main (void)
{
uint8_t duty;
duty = 0;
uint8_t freq;
freq = 0;
while(1)
{
pwm_init;
// increment duty
if (PINB == 0x01)
{
if (duty <= 245)
{
//increment duty by 10
duty = duty + 10;
// set the duty in OCR1A
OCR1A = duty;
}_delay_ms(35);
}
// decrement duty
if (PINB == 0x02)
{
if (duty >= 10)
{
//decrement duty by 10
duty = duty - 10;
// set the duty in OCR1A
OCR1A = duty;
_delay_ms(35);
}
}
//increment freq
if (PINB == 0x04)
{
if (freq >=1)
{
//increment freq by 10
freq = --freq;
//set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
// decrement freq
if (PINB == 0x08)
{
if (freq <= 18)
{
//decrement freq by 10
freq = ++freq;
// set the freq in ICR1
ICR1 = freq;
_delay_ms(35);
}
}
}
// repeat this forever
}
}
|
|
|
Nazaj na vrh |
|
 |
tilz0R Član


Pridružen-a: Čet 31 Maj 2012 15:39 Prispevkov: 898 Aktiv.: 5.65 Kraj: Črnomelj
|
Objavljeno: Ned Sep 30, 2012 3:08 pm Naslov sporočila: |
|
|
pwm_init kliči samo 1x, torej preden začneš z while zanko.
in pa kliči jo kot funkcijo, torej
_________________ Knowledge sharing is caring.
majerle.eu | stm32f4-discovery.net |
|
Nazaj na vrh |
|
 |
lojzek Član



Pridružen-a: Pet 25 Jan 2008 8:00 Prispevkov: 3387 Aktiv.: 15.99
|
Objavljeno: Pon Okt 01, 2012 7:19 am Naslov sporočila: |
|
|
A mojega posta pa nisi ne prebral in ne upošteval?  |
|
Nazaj na vrh |
|
 |
rakec14 Član

Pridružen-a: Ned 20 Sep 2009 10:50 Prispevkov: 11 Aktiv.: 0.06 Kraj: Celje
|
Objavljeno: Pon Okt 01, 2012 8:43 pm Naslov sporočila: |
|
|
Lojzek, sem prebral, vendar nisem vedel, kako bi spremenil. Ka si mislil tako:
Koda: |
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
void pwm_init ()
{
TCCR1A = (1<<COM1A1);//Clear OC1A on compare, bottom
TCCR1B = (1<<WGM13) | (1<<CS12);//phase&frequency PWM top=ICR1 , 256 prescaler
ICR1=0x0000; // set TOP
OCR1A=0x0000; // set duty cycle
DDRD |= (1<<PD5);// set PD5 as output
}
int main (void)
{
pwm_init();
uint16_t duty;
duty = 0;
uint16_t freq;
freq = 0;
while(1)
{
// increment duty
if (!(PIND&0xO1))
{
if (duty <= 58981)
{
//increment duty by 10
duty = duty + 6555;
// set the duty in OCR1A
duty = OCR1A;
}_delay_ms(35);
}
// decrement duty
if (!(PIND&0xO2))
{
if (duty >= 6555)
{
//decrement duty by 10
duty = duty - 6555;
// set the duty in OCR1A
duty = OCR1A;
_delay_ms(35);
}
}
//increment freq
if (!(PIND&0xO4))
{
if (freq <= 58981)
{
//increment freq by 10
freq = freq + 6555;
//set the freq in ICR1
freq = ICR1;
_delay_ms(35);
}
// decrement freq
if (!(PIND&0xO8))
{
if (freq <= 6555)
{
//decrement freq by 10
freq = freq - 6555;
// set the freq in ICR1
freq = ICR1;
_delay_ms(35);
}
}
}
// repeat this forever
}
}
|
|
|
Nazaj na vrh |
|
 |
lojzek Član



Pridružen-a: Pet 25 Jan 2008 8:00 Prispevkov: 3387 Aktiv.: 15.99
|
Objavljeno: Tor Okt 02, 2012 6:05 am Naslov sporočila: |
|
|
A simulacijo programa si pa poizkusil? Tam lahko tudi tipke pritiskaš, spreminjaš vrednosti spremenljivk,... Seveda če delaš z aVR studiem
Drugače pa jaz preverjam stanje enega vhoda npr. takole:
Koda: |
if(bit_is_clear (PINB, 1))
{
.
}
|
ali pa nasprotna verzija:
Koda: |
if (bit_is_set (PINB,1))
{
.
} |
Ta princip deluje tudi na spremenljivkah, ne samo na vhodih/izhodih. Mi preverjanje stanja bita z maskami ni tako "razumljivo" |
|
Nazaj na vrh |
|
 |
rakec14 Član

Pridružen-a: Ned 20 Sep 2009 10:50 Prispevkov: 11 Aktiv.: 0.06 Kraj: Celje
|
Objavljeno: Tor Okt 16, 2012 11:04 am Naslov sporočila: |
|
|
V simulaciji se mi PORTB nič ne spremeni. |
|
Nazaj na vrh |
|
 |
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 493 dni
Powered by phpBB © 2001, 2005 phpBB Group
|