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