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_A 145 // PWM-Schritte pro Zyklus(1..255)
|
13 | #define PWM_STEPS_B 45 // PWM-Schritte pro Zyklus(1..255)
|
14 | #define PWM_PORT_D PORTD // Port für PWM
|
15 | #define PWM_DDR_D DDRD // Datenrichtungsregister für PWM
|
16 | #define PWM_PORT_C PORTC // Port für PWM
|
17 | #define PWM_DDR_C DDRC // Datenrichtungsregister für PWM
|
18 | // ab hier nichts ändern, wird alles berechnet
|
19 |
|
20 | #define T_PWM_A (F_CPU/(F_PWM*PWM_STEPS_A)) // Systemtakte pro PWM-Takt
|
21 | #define T_PWM_B (F_CPU/(F_PWM*PWM_STEPS_B)) // Systemtakte pro PWM-Takt
|
22 | #if (T_PWM_A<(152+5))
|
23 | #error T_PWM zu klein, F_CPU muss vergrössert werden oder F_PWM oder PWM_STEPS verkleinert werden
|
24 | #endif
|
25 | #if (T_PWM_B<(152+5))
|
26 | #error T_PWM zu klein, F_CPU muss vergrössert werden oder F_PWM oder PWM_STEPS verkleinert werden
|
27 | #endif
|
28 |
|
29 |
|
30 | #if PWM_STEPS > 255
|
31 | #error PWM_STEPS zu gross
|
32 | #endif
|
33 |
|
34 | // includes
|
35 |
|
36 | #include <stdint.h>
|
37 | #include <string.h>
|
38 | #include <avr/io.h>
|
39 | #include <avr/interrupt.h>
|
40 |
|
41 | // globale Variablen
|
42 |
|
43 | volatile uint8_t pwm_setting_A[8]; // Einstellungen für die einzelnen PWM-Kanäle
|
44 | volatile uint8_t pwm_setting_B[8]; // Einstellungen für die einzelnen PWM-Kanäle
|
45 |
|
46 | // Timer 1 Output COMPARE A Interrupt
|
47 |
|
48 | ISR(TIMER1_COMPA_vect) {
|
49 | static uint8_t pwm_cnt=0;
|
50 | uint8_t tmp=0, i=0, j=1;
|
51 |
|
52 | OCR1A += (uint16_t)T_PWM_A;
|
53 |
|
54 | for (; i<8; i++) {
|
55 | if (pwm_setting_A[i] > pwm_cnt) tmp |= j;
|
56 | j<<=1;
|
57 | }
|
58 | PWM_PORT_D = tmp; // PWMs aktualisieren
|
59 | if (pwm_cnt==(uint8_t)(PWM_STEPS_A-1))
|
60 | pwm_cnt=0;
|
61 | else
|
62 | pwm_cnt++;
|
63 | }
|
64 |
|
65 | ISR(TIMER1_COMPB_vect)
|
66 | {
|
67 | static uint8_t pwm_cnt=0;
|
68 | uint8_t tmp=0, i=0, j=1;
|
69 |
|
70 | OCR1B += (uint16_t)T_PWM_B;
|
71 |
|
72 | for (; i<8; i++) {
|
73 | if (pwm_setting_B[i] > pwm_cnt) tmp |= j;
|
74 | j<<=1;
|
75 | }
|
76 | PWM_PORT_C = tmp; // PWMs aktualisieren
|
77 | if (pwm_cnt==(uint8_t)(PWM_STEPS_B-1))
|
78 | pwm_cnt=0;
|
79 | else
|
80 | pwm_cnt++;
|
81 | }
|
82 |
|
83 | int main(void) {
|
84 |
|
85 | // PWM einstellen
|
86 |
|
87 | PWM_DDR_D = 0xFF; // Port als Ausgang
|
88 | PWM_DDR_C = 0xFF; // Port als Ausgang
|
89 |
|
90 | // Timer 1 OCRA1, als variablem Timer nutzen
|
91 |
|
92 | TCCR1B = 1; // Timer läuft mit vollem Systemtakt
|
93 | TIMSK |= (1<<OCIE1B) | (1<<OCIE1A); // Interrupt freischalten
|
94 |
|
95 |
|
96 |
|
97 | sei(); // Interrupts global einschalten
|
98 |
|
99 | /*********************************************************************/
|
100 | // nur zum Testen, im Anwendungsfall löschen
|
101 |
|
102 | volatile uint8_t tmp;
|
103 | const uint8_t t1[8]={270, 400, 30, 1007, 150, 99, 5, 9};
|
104 | const uint8_t t2[8]={270, 400, 30, 0, 150, 99, 5, 9};
|
105 | const uint8_t t3[8]={270, 400, 30, 1007, 3, 99, 3, 0};
|
106 | const uint8_t t4[8]={0, 0, 0, 0, 0, 0, 0, 0};
|
107 | const uint8_t t5[8]={0, 0, 0, 0, 0, 0, 0, 9};
|
108 | const uint8_t t6[8]={330, 330, 330, 3003, 33, 33, 33, 33};
|
109 |
|
110 | // Messung der Interruptdauer
|
111 | tmp =0;
|
112 | tmp =0;
|
113 | tmp =0;
|
114 |
|
115 | // Debug
|
116 |
|
117 | memcpy(pwm_setting_A, t1, 8);
|
118 | memcpy(pwm_setting_A, t2, 8);
|
119 | memcpy(pwm_setting_A, t3, 8);
|
120 | memcpy(pwm_setting_A, t4, 8);
|
121 | memcpy(pwm_setting_A, t5, 8);
|
122 | memcpy(pwm_setting_A, t6, 8);
|
123 |
|
124 | memcpy(pwm_setting_B, t1, 8);
|
125 | memcpy(pwm_setting_B, t2, 8);
|
126 | memcpy(pwm_setting_B, t3, 8);
|
127 | memcpy(pwm_setting_B, t4, 8);
|
128 | memcpy(pwm_setting_B, t5, 8);
|
129 | memcpy(pwm_setting_B, t6, 8);
|
130 |
|
131 | /*********************************************************************/
|
132 |
|
133 | while (1)
|
134 | {
|
135 | }
|
136 |
|
137 | return 0;
|
138 | }
|