Hi, bisher habe ich Software PWM's mit einem AVR board mit "ISR(TIMER1_COMPA_vect)" (Compare Match Funktion) und entsprechend setzen/wechseln des DutyCycle durch OCR1x. Allerdings steige ich nun auf ein STM32 (ARM) Board um. Mit ARM Boards habe ich leider keine Erfahrung. Sind die Register ähnlich dem AVR Board, bzw gibt es sowas wie "Compare Match Funktion"? Hat jemand evtl. sogar ein Beispiel-Code bzw. eine Tutorial wie man Software PWM Signale mit STM32 Boards generiert? PWM-Frequenz sollte bei ~20kHz liegen. Die Compare Match Funktion habe ich verwendet um das PWM Signal an und ab zu schalten in definierten Abständen. Beispiel: |||...: High, __...:LOW, ||_||_||: ~20kHz ||||||_||_||_||______||||||_||_||_||_||_||_||||||__||_||_||_||___||||||_ __... Vielen Dank!
:
Bearbeitet durch User
Hallo, der ESP32 ist aber kein ARM-Core sondern ein Tensilika. Womit willst Du ihn denn Programmieren? Direkt mit dem IDK von Espressif oder aus der ArduinoIDE? Gruß aus Berlin Michael
Hallo, Jk M. schrieb: > Sorry, ich meine ein STM32 Board. ok, da mußt Du auf andere warten, nicht meine Schiene. Gruß aus Berlin Michael
Ich empfehle folgende Lektüre: http://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf
> Sind die Register ähnlich dem AVR Board, bzw gibt es sowas wie "Compare > Match Funktion"? Ja, ähnlich. Ich kann Dir ein beispiel für Hardware PWM zeigen: http://stefanfrings.de/stm32/index.html#pwm Warum willst du PWM Signale per Software erzeugen? Die STM32 Controller haben sehr viel mehr PWM Ausgänge, als die kleinen AVR's. Abgesehen davon, wenn Du dich geschickt anstellst kannst du die Informationen meiner Webseite kombinieren, um deine Soft-PWM zu realisieren.
Ziel ist es 32+ PWM Signale wie oben beschrieben zu generieren. Diese müssen aber voneinander unabhängig einstellbar sein. Sprich die Dauer der 20kHz PWM, welche sich im "Negativen-Hall"-Zeitfester der 10Hz-100Hz einstellbaren PWM befinden. PWM1 20Khz: ||_||_||_|| PWM2 zb. 100Hz: ||||||__________________||||||___________ kombiniert Bsp 1: ||||||_||_||_||_||______||||||_||_||_||__... kombiniert Bsp 2: ||||||_||_||____________||||||_||_||_____... kombiniert Bsp 2: ||||||_||_||_||___||||||_||_||_||___||||||_... Hoffe so ist es verständlicher... Ich schaue mir deine Webseite mal an. DAnke.
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <stdint.h> |
4 | #include <stdbool.h> |
5 | |
6 | // Pin
|
7 | #define PART_DDR (DDRB) //legt outputs fest
|
8 | #define PART_PORT (PORTB) // high low der outputs
|
9 | |
10 | #define PART_PORTD (PORTD)
|
11 | #define PART_DDRD (DDRD)
|
12 | |
13 | //#define PART 0x30//(1<<5) //bitshifting
|
14 | |
15 | int c=1; |
16 | volatile long counter = 0; |
17 | |
18 | |
19 | byte PART=0x30; |
20 | byte PART1=0x30; |
21 | byte PART2=0x10; |
22 | |
23 | |
24 | volatile long multiDC = 3; |
25 | volatile long freq = (0x7cff)-0x1f3f-(multiDC*0x320)-1; |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | void init_application() { |
34 | // set PART to output and turn it off
|
35 | PART_PORT &= ~PART; |
36 | PART_DDR |= PART; |
37 | // reset timer register
|
38 | TCNT1 = 0x0000; |
39 | // set OCR1A register
|
40 | //OCR1A = 0x1fe;
|
41 | OCR1A = 0x1f3f; |
42 | // enable output compare match interrupt A
|
43 | TIMSK1 |= (1<<OCIE1A); |
44 | // set precaler=1, Timerstep @ 16 MHz = 0,0625 us, 65535 Timersteps (2^16); 16000=1ms
|
45 | TCCR1B = _BV(CS10); |
46 | // globally enable interrupts
|
47 | sei(); |
48 | }
|
49 | |
50 | |
51 | |
52 | //void init_application2() {
|
53 | //// set PART to output and turn it off
|
54 | //
|
55 | //PART_PORTD &= ~PART;
|
56 | //PART_DDRD |= PART;
|
57 | //// reset timer register
|
58 | //TCNT1 = 0x0000;
|
59 | //// set OCR1A register
|
60 | ////OCR1A = 0x1fe;
|
61 | //OCR1A = 0;
|
62 | //// enable output compare match interrupt A
|
63 | //TIMSK1 |= (1<<OCIE1A);
|
64 | //// set precaler=1, Timerstep @ 16 MHz = 0,0625 us, 65535 Timersteps (2^16); 16000=1ms
|
65 | //// |= (1<<CS10) (1<<CS12);
|
66 | //TCCR1B = _BV(CS10); //_BV(WGM11) |_BV(WGM10) | _BV(CS10);
|
67 | //// globally enable interrupts
|
68 | //sei();
|
69 | //}
|
70 | |
71 | |
72 | |
73 | |
74 | int main(void) { |
75 | |
76 | |
77 | init_application(); |
78 | //init_application2();
|
79 | |
80 | for(;;) { |
81 | |
82 | }
|
83 | |
84 | |
85 | }
|
86 | |
87 | |
88 | |
89 | |
90 | |
91 | // interrupt service routine for timer 1 compare match A
|
92 | ISR(TIMER1_COMPA_vect) { |
93 | uint16_t current_OCR1A = OCR1A; |
94 | static bool PART_on = true; |
95 | |
96 | switch(c) { |
97 | |
98 | case 1: |
99 | |
100 | PART=PART1; |
101 | PART_PORT |= PART; // PORT= PORT OR PART |
102 | PART_PORTD |= PART; |
103 | OCR1A = current_OCR1A+0x1f3f; |
104 | |
105 | c=2; |
106 | break; |
107 | |
108 | |
109 | |
110 | case 2: |
111 | |
112 | |
113 | if(PART_on) { |
114 | PART_PORTD = PART_PORT |= PART; // PORT= PORT OR PART |
115 | OCR1A = current_OCR1A+0xc8; |
116 | }
|
117 | |
118 | |
119 | else { |
120 | PART_PORTD =PART_PORT &= ~PART; //PORT= PORT AND PART |
121 | |
122 | OCR1A = current_OCR1A+0x258; |
123 | counter++; |
124 | |
125 | if(counter==multiDC){ |
126 | PART = PART2; |
127 | PART_PORT &= ~PART; //PORT= PORT AND PART |
128 | |
129 | }
|
130 | }
|
131 | |
132 | |
133 | if(counter==multiDC){ |
134 | c=3; |
135 | }
|
136 | |
137 | break; |
138 | |
139 | |
140 | |
141 | |
142 | case 3: |
143 | |
144 | PART_PORTD = PART_PORT &= ~PART; //PORT= PORT AND PART |
145 | |
146 | OCR1A =current_OCR1A+ freq;// |
147 | |
148 | c=1; |
149 | counter=0; |
150 | |
151 | break; |
152 | |
153 | }
|
154 | |
155 | |
156 | PART_on = !PART_on; // toogle PART on every call of isr |
157 | }
|
:
Bearbeitet durch Moderator
Beitrag #5388171 wurde von einem Moderator gelöscht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.