mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PWM Mega8


Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich möchte eine Leistungsregelung machen.
Nun zu meiner Frage.

Ist es möglich beim Mega 8 .
Ist es möglich mit einem Timer (Timer1) eine Pulsweitenmodulation mit 
der Grundperiode 10ms zu machen.
Das heißt ich möchte einen Timer Overflow bei 10 ms haben.
Da eine AD Messung machen warten bis AD Messung fertig ist.
Nun reload wert berechnen ob Pulsweite größer oder kleiner.
Und Comparewert ins register schieben.

Aber sowie ich den Timer1 als PWM Initialisiere stimmen meine 
errechneten Overflow werte nicht mehr.

Ich hoffe Ihr versteht was ich meine.

Ich habe das Programm im Moment auf einen C515 laufen. Da ist es kein 
Problem  den Timer 2 so zu konfigurieren.

Wahrscheinlich habe ich einen Denkfehler irgendwo.

Hier ist mal der Code vom 80c515
Dann ist es womöglich einfacher zu verstehen was ich vorhabe.
#define Clock    12  //Quarzfrequenz    12MHz
#define Vorteiler    12  // 12er Vorteiler     1MHz
#define F_pre      Clock/Vorteiler    // Frequenz geteilt
#define Step      10  // Zählerwert für 10ms
#define Timer2_Value 65536 - (F_pre * Step * 1000)// 10ms Timer = 55536

#define AD_Value_Soll   46  // (255 / 5V) * 0,91 = 46,41 Schritte bei 6V am An der Lampe

#define Sek    10000        // Zeit 10ms

// Globale Variablen


unsigned char T2_Low,T2_High;        


/*---------------------------------------------------------------------------------------------
Timer 2 Interrupt Serviceroutine

----------------------------------------------------------------------------------------------*/
_interrupt(5) void Timer_2_Interrupt(void)   // Interrupt 5
{
unsigned int cmp;


P1_0 = 0;

TF2  = 0;        // Interrupt Request auf 0
DAPR = 0;        // ADC in Single Mode  0 - 5 V Messbereich und neue Wandlung starten

while(BSY){};    // Warte bis ADC - Wandlung fertig

if(ADDAT <= AD_Value_Soll)  // Ist Spannung größer ? 
{
CCH1=T2_High = (Timer2_Value+1) >> 8;  // Compareregister low vorladen (+1 um keine Probleme beim Vergleich zu bekommen)

CCL1=T2_Low  = (Timer2_Value+1) & 0xFF;  // Compaeregister High vorladen
}
else
{
cmp = (unsigned)(((long)Sek * AD_Value_Soll * AD_Value_Soll) / (ADDAT * ADDAT));  // Reloadwert für Compare berechnen 
    // Formel (Schritte * AD_Soll * AD_Soll)/(ADC * ADC)

cmp = 65536 - cmp;      // Berechneten Timerwert vom Max Zähl wert abziehen
CCH1 = T2_High = cmp >> 8;    // Compareregister low vorladen 
CCL1 = T2_Low  = cmp & 0xFF;    // Compaeregister High vorladen

}
}


void main(void)
{
//Initialisierungen

IEN0 = 0;    // Alle Interrupts aus
IEN1 = 0;    // Alle Externen Interrupts aus

// Timer 2 Init

T2I1 = 0;    // Keine Inputs
T2I0 = 1;    // Inputs
T2PS = 0;    // Vorteiler auf 12

T2CM = 0;    // Compare Mode 0 Aktiv
CCEN = 8;    // Compare Mode 0/1 Togle Port1.1

MX0 = 0;    // Analogeingang P6_0 Eingang
MX1 = 0;    // Analogeingang P6_0 Eingang
MX2 = 0;    // Analogeingang P6_0 Eingang

// ADC Init

ADM = 0;    // ADC Wandler auf Singelmode

ET2 = 1;    // Timer 2 Interrupt freigabe
EAL = 1;    // Globale Interrupts


CRCH=T2_High = Timer2_Value >> 8;       // Compareregister low vorladen 
CRCL=T2_Low  = Timer2_Value & 0xFF;  // Compaeregister High vorladen

T2R1 = 1;      // Mode 9 autoreload wenn Timer überläuft
T2R0 = 0;      // Mode 9 autoreload wenn Timer überläuft

P1_1 = 0;      // Port1 Pin 1 auf 0



while(1);




}


Vielen Dank

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es wäre evtl. besser gewesen den AVR_Code zu posten...
Beim Timer1 des AVR achte mal auf:
- die Reihenfolge, in der die 16-Bit Register angesprochen werden (mach 
16Bit zugriffe, wenn der Compiler das kann, z.B. der AVR.GCC)
- CTC ist besser als (p)reload (beim AVR!), es gibt mehrere PWM/CTC Modi 
(modes? ;)
 -die Vorteiler sind anders (aber das wird dir wohl schon aufgefallen 
sein)

hth -Jörg

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also.
Das was du mit dem ATmega8 vorhast geht. Ich würde dir nur folgendes 
raten:
Timer mittels Vorladewert und VOrteiler auf 10ms PWM-Periodendauer 
einstellen. Immer mit dem Overflow-Int das AD-Ergebnis holen, eine neue 
AD-Wandlung anstoßen, und mittels eines P(I)-Algorithmus 
(Differenzengleichung) den neuen PWM-Compare-wert errechnen und 
schreiben.
Also etwa so:
(pseudocode)
ISR (Timer_Overflov)
{
ADW-Messwert holen und in TEMP speichern.
neue Wandlung starten
Compare-Wert = f( TEMP,...)  //PI
}

Zu dem Quellcode kann ich nix sagen, ich kenne den µC nicht.
Weitere Hinweise kann ich auch nicht geben, da du nur spärlich 
beschreibst, was nicht geht, und was es werden soll...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.