Forum: Mikrocontroller und Digitale Elektronik Soft PWM Beispiel (ATMEGA32) auf ATMEGA168 umschreiben


von Hansi C. (honsey)


Lesenswert?

ich sitze jetzt schon den ganzen nachmittag dran, aber bekomme es 
einfach nicht hin. in der artikelsammlung gibt es ein beispiel für soft 
pwm auf einem mega32.

der code sieht wie folgt aus:
1
/*
2
    Eine 8-kanalige PWM mit einfachem Lösungsansatz
3
 
4
    ATmega32 @ 8 MHz
5
 
6
*/
7
 
8
// Defines an den Controller und die Anwendung anpassen
9
 
10
#define F_CPU 8000000L                  // Systemtakt in Hz
11
#define F_PWM 100                       // PWM-Frequenz in Hz
12
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
13
#define PWM_PORT PORTD                  // Port für PWM
14
#define PWM_DDR DDRD                    // Datenrichtungsregister für PWM
15
 
16
// ab hier nichts ändern, wird alles berechnet
17
 
18
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
19
 
20
#if (T_PWM<(152+5))
21
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
22
#endif
23
 
24
// includes
25
 
26
#include <stdint.h>
27
#include <string.h>
28
#include <avr/io.h>
29
#include <avr/interrupt.h>
30
 
31
// globale Variablen
32
 
33
volatile uint8_t pwm_setting[8];                    // Einstellungen für die einzelnen PWM-Kanäle
34
 
35
// Timer 1 Output COMPARE A Interrupt
36
 
37
ISR(TIMER1_COMPA_vect) {
38
    static uint8_t pwm_cnt=0;
39
    uint8_t tmp=0, i=0, j=1;
40
 
41
    OCR1A += (uint16_t)T_PWM;
42
 
43
    for (; i<8; i++) {    
44
      if (pwm_setting[i] > pwm_cnt) tmp |= j;
45
            j<<=1;
46
  }
47
    PWM_PORT = tmp;                         // PWMs aktualisieren
48
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
49
        pwm_cnt=0;
50
    else
51
        pwm_cnt++;
52
}
53
 
54
int main(void) {
55
 
56
    // PWM einstellen
57
    
58
    PWM_DDR = 0xFF;         // Port als Ausgang
59
    
60
    // Timer 1 OCRA1, als variablem Timer nutzen
61
 
62
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
63
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
64
 
65
    sei();                  // Interrupts gloabl einschalten
66
 
67
/*********************************************************************/
68
// nur zum Testen, im Anwendungsfall löschen
69
 
70
    volatile uint8_t tmp;
71
const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
72
const uint8_t t2[8]={27, 40, 3, 0, 150, 99, 5, 9};
73
const uint8_t t3[8]={27, 40, 3, 17, 3, 99, 3, 0};
74
const uint8_t t4[8]={0, 0, 0, 0, 0, 0, 0, 0};
75
const uint8_t t5[8]={0, 0, 0, 0, 0, 0, 0, 9};
76
const uint8_t t6[8]={33, 33, 33, 33, 33, 33, 33, 33};
77
 
78
// Messung der Interruptdauer
79
    tmp =0;
80
    tmp =0;
81
    tmp =0;
82
 
83
// Debug 
84
 
85
    memcpy(pwm_setting, t1, 8);
86
    
87
    memcpy(pwm_setting, t2, 8);
88
 
89
    memcpy(pwm_setting, t3, 8);
90
 
91
    memcpy(pwm_setting, t4, 8);
92
 
93
    memcpy(pwm_setting, t5, 8);
94
    
95
    memcpy(pwm_setting, t6, 8);
96
 
97
/*********************************************************************/
98
 
99
    return 0;
100
}

ich habe eigentlich alles unverändert gelassen, bis auf wenige stellen.

1) der cpu takt. mein atmega168 wird mit einem externen quarz auf 16Mhz 
betrieben, deshalb:
1
#define F_CPU 16000000L                  // Systemtakt in Hz

2) die aktivierung des interrupts:
1
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
2
    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten

leider funktioniert es garnicht. die leds bleiben einfach dunkel... was 
übersehe ich? da ich davon ausgehe, dass der code stimmt, wenn er so in 
der artikelsammlung abgeheftet ist, wird es wohl nicht an dem liegen was 
ich vermuten würde. (habe es auch ausprobiert, aber es hat auch nicht 
geholfen...)

1) zum zeitpunkt, wenn der interrupt aktiviert wied ist OCR1A noch 
garnicht definiert?
2) die helligkeitswerte müssten doch an irgendeiner stelle im programm 
in das array pwm_setting geschrieben werden?

vielen dank für eure hilfe,
hans

von Oliver (Gast)


Lesenswert?

In dem Artikel sind drei Varianten der Soft-PWM gezeigt. Nimm die 
letzte, die sollte funktionieren. Deine Änderungen sind wohl so in 
Ordnung.

Oliver

von Falk B. (falk)


Lesenswert?

@  Honsey Kk (honsey)

>#define F_CPU 16000000L                  // Systemtakt in Hz

Kein Problem, das ist der Sinn der Sache.

>    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
>    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten

Hab das Datenblatt im Moment nicht hier.

>1) zum zeitpunkt, wenn der interrupt aktiviert wied ist OCR1A noch
>garnicht definiert?

Ist auch unwichtig, das regelt sich allein.

>2) die helligkeitswerte müssten doch an irgendeiner stelle im programm
>in das array pwm_setting geschrieben werden?

Das machen die Zeilen

1
    memcpy(pwm_setting, t1, 8);

MFG
Falk

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.