Forum: Mikrocontroller und Digitale Elektronik PWM Mega8


von Andi (Gast)


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.
1
#define Clock    12  //Quarzfrequenz    12MHz
2
#define Vorteiler    12  // 12er Vorteiler     1MHz
3
#define F_pre      Clock/Vorteiler    // Frequenz geteilt
4
#define Step      10  // Zählerwert für 10ms
5
#define Timer2_Value 65536 - (F_pre * Step * 1000)// 10ms Timer = 55536
6
7
#define AD_Value_Soll   46  // (255 / 5V) * 0,91 = 46,41 Schritte bei 6V am An der Lampe
8
9
#define Sek    10000        // Zeit 10ms
10
11
// Globale Variablen
12
13
14
unsigned char T2_Low,T2_High;        
15
16
17
/*---------------------------------------------------------------------------------------------
18
Timer 2 Interrupt Serviceroutine
19
20
----------------------------------------------------------------------------------------------*/
21
_interrupt(5) void Timer_2_Interrupt(void)   // Interrupt 5
22
{
23
unsigned int cmp;
24
25
26
P1_0 = 0;
27
28
TF2  = 0;        // Interrupt Request auf 0
29
DAPR = 0;        // ADC in Single Mode  0 - 5 V Messbereich und neue Wandlung starten
30
31
while(BSY){};    // Warte bis ADC - Wandlung fertig
32
33
if(ADDAT <= AD_Value_Soll)  // Ist Spannung größer ? 
34
{
35
CCH1=T2_High = (Timer2_Value+1) >> 8;  // Compareregister low vorladen (+1 um keine Probleme beim Vergleich zu bekommen)
36
37
CCL1=T2_Low  = (Timer2_Value+1) & 0xFF;  // Compaeregister High vorladen
38
}
39
else
40
{
41
cmp = (unsigned)(((long)Sek * AD_Value_Soll * AD_Value_Soll) / (ADDAT * ADDAT));  // Reloadwert für Compare berechnen 
42
    // Formel (Schritte * AD_Soll * AD_Soll)/(ADC * ADC)
43
44
cmp = 65536 - cmp;      // Berechneten Timerwert vom Max Zähl wert abziehen
45
CCH1 = T2_High = cmp >> 8;    // Compareregister low vorladen 
46
CCL1 = T2_Low  = cmp & 0xFF;    // Compaeregister High vorladen
47
48
}
49
}
50
51
52
void main(void)
53
{
54
//Initialisierungen
55
56
IEN0 = 0;    // Alle Interrupts aus
57
IEN1 = 0;    // Alle Externen Interrupts aus
58
59
// Timer 2 Init
60
61
T2I1 = 0;    // Keine Inputs
62
T2I0 = 1;    // Inputs
63
T2PS = 0;    // Vorteiler auf 12
64
65
T2CM = 0;    // Compare Mode 0 Aktiv
66
CCEN = 8;    // Compare Mode 0/1 Togle Port1.1
67
68
MX0 = 0;    // Analogeingang P6_0 Eingang
69
MX1 = 0;    // Analogeingang P6_0 Eingang
70
MX2 = 0;    // Analogeingang P6_0 Eingang
71
72
// ADC Init
73
74
ADM = 0;    // ADC Wandler auf Singelmode
75
76
ET2 = 1;    // Timer 2 Interrupt freigabe
77
EAL = 1;    // Globale Interrupts
78
79
80
CRCH=T2_High = Timer2_Value >> 8;       // Compareregister low vorladen 
81
CRCL=T2_Low  = Timer2_Value & 0xFF;  // Compaeregister High vorladen
82
83
T2R1 = 1;      // Mode 9 autoreload wenn Timer überläuft
84
T2R0 = 0;      // Mode 9 autoreload wenn Timer überläuft
85
86
P1_1 = 0;      // Port1 Pin 1 auf 0
87
88
89
90
while(1);
91
92
93
94
95
}


Vielen Dank

von Joerg X. (Gast)


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

von Matthias (Gast)


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...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.