PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : pwm mit taster ansteuern



vianney
04.02.2010, 09:25
hallo an alle
ich hoffe ihr könnt mir helfen, hab folgendes problem. ich muss mittels taster die periode und die pulsbreite eines pwm-signals an einem atmega88 mit avr steuern. idealerfall wäre mit 2 taster meine periode ändern d.h wenn s1 gedrückt (inkremetiert) die periode wird größer, wenn auf s2, wird kleiner. und das gleich auch für die pulsbreite mit den 2 restlichen tastern. die period sollte zwischen 50ms-250ms sein, und die pulsbreite zwischen 4ms-20ms.ich hab halt schon mien pwm erzeugt, und wie man die tasteer ansteuert weiss auch schon, hab schon sogar schon geschaft meine pulsbreite zu steuern, durch mein ocr1b-wert. aber jetzt will wiessen wie ich dann meine period mit den restlichen tastern ansteuern sollte, ob ich dafür ein interrupt brauche? ich schicke auch anbei mein bis jetzt fertiges code damit irh euch es auch angückt
danke




// Funktion Tastenentprellen
// ----------------------------------
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) // uint8 = unsigned int 8 bit (eigentlich char)

{
if(!(*port & (1<<pin)))
{ //pin wurde auf masse gezogen, 100ms warten
_delay_ms(100);
if((*port &(1<<pin)))
{ // Anwender Zeit zum Loslassen des Tasters gegeben
_delay_ms(100);
return (true);
}
}
return 0;
}

int main (void)

//Hauptprogramm
{

DDRB |= (1 << PB2);
TCCR1A |= (1<<COM1B0)|(1<<COM1B1) ;
TCCR1B |= (1<<WGM13)|(1<<CS10)|(1<<CS12);
OCR1B=410; //min pulsbreite 4ms
ICR1 = 450; //min period 50ms

while(1)
{
ButtonControl();

if(S1) // für die pulsbreite

{
OCR1B=OCR1B-9;
S1=false;
if(OCR1B<270)
{
OCR1B=270;
}
}

if(S2) //für die pulsbreite

{
OCR1B=OCR1B+9;
S2=false;

if(OCR1B>410)
{
OCR1B=410;
}
}

if(S3) // für die period

{



}

if(S4) // für die period

{

}

}
return 0;
}

void ButtonControl()
{

char SavePORTC = PORTC;
char SaveDDRC = DDRC;

PORTC |= (1<<PC0) | (1<<PC1)| (1<<PC2)| (1<<PC3) ;
//Interne Pull-Up-Widerstände einschalten
DDRC &= ~((1<<DDC0) | (1<<DDC1)| (1<<DDC2)| (1<<DDC3));
//Port C auf Input(0) geschalten

if (debounce(&PINC, PC0)) //Taste S1
{
S1=true;
}

if (debounce(&PINC, PC1)) //Taste S2
{
S2=true;
}
if (debounce(&PINC, PC2)) //Taste S3
{
S3=true;

}
if (debounce(&PINC, PC3)) //Taste S4
{
S4=true;
}

PORTC = SavePORTC;
DDRC = SaveDDRC;
}

The Man
03.02.2011, 23:08
Hi,

da du die Pulsbreite ändern willst, geht es in die Richtung, ein Software PWM auf Basis eines Interuptes zu erzeugen. Die Timer haben ja Vorteiler, die aber nur eine recht grobe Aufteilung bieten.

der Plan lautet also, einen Compare Interrupt herzunehmen. Da gibt es verschiedene Modi, wie sich die Timer verhalten (siehe Datenblatt) . Es bietet sich der CTC (clear Timer on Comparematch) an. Dabei wird der Timer genullt, wenn ein Comparematch eintritt. Der Wert, der dabei den Punkt festlegt kann auch eines der OCRA oder B Register sein. Damit kannst du also die Periodendauer beeinflussen.

In der Interrupt Service Routine zählst du eine Variable hoch, die du gegen einen Wert vergleichst den, du über deine Taster beeinflussen kannst. Dieser Wert stellt deinen Duty Cycle dar, also wann ein Pin seinen logischen Zustand ändert. Welcher Pin das ist liegt bei dir, da es ja ein Software PWM ist.

Betrachte meine Hilfestellung in erster Linie als eine Sammlung von Schlüsselwörtern, über die du dich schlau machen kannst.

"Duty Cycle"
"Software PWM / Hardware PWM"
"Clear Timer on Comparematch"
"Interrupt on Comparematch"

Um das Datenblatt wirst du nicht herum kommen auf Dauer. Aber keine Sorge wenn du siehts, dass es mehr als 300 Seiten hat. Die musst du nicht alles lesen. Immer nur den Teil den du brauchst, aber das siehst du in der Inhaltsangabe.

UND:
dein Code ist kein Assembler! Das sieht mir nach C aus?

Gruß,
The Man