Skip to content
This repository was archived by the owner on Feb 4, 2023. It is now read-only.

Commit 4e4a7fe

Browse files
authored
v1.2.3 to fix DutyCycle bug, etc.
### Releases v1.2.3 1. Fix `DutyCycle` bug. Check [float precisison of DutyCycle only sometimes working #3](khoih-prog/SAMD_Slow_PWM#3) 2. Fix `New Period` display bug. Check [random dropouts #4](khoih-prog/SAMD_Slow_PWM#4) 3. Update examples
1 parent 13bc730 commit 4e4a7fe

File tree

8 files changed

+1478
-0
lines changed

8 files changed

+1478
-0
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/****************************************************************************************************************************
2+
ISR_16_PWMs_Array.ino
3+
For F/L/H/G/WB/MP1 boards
4+
Written by Khoi Hoang
5+
6+
Built by Khoi Hoang https://github.com/khoih-prog/STM32_Slow_PWM
7+
Licensed under MIT license
8+
9+
Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by
10+
unsigned long miliseconds), you just consume only one timer and avoid conflicting with other cores' tasks.
11+
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
12+
Therefore, their executions are not blocked by bad-behaving functions / tasks.
13+
This important feature is absolutely necessary for mission-critical tasks.
14+
*****************************************************************************************************************************/
15+
16+
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
17+
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
18+
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5))
19+
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
20+
#endif
21+
22+
// These define's must be placed at the beginning before #include "STM32_Slow_PWM.h"
23+
// _PWM_LOGLEVEL_ from 0 to 4
24+
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
25+
#define _PWM_LOGLEVEL_ 3
26+
27+
#define USING_MICROS_RESOLUTION true //false
28+
29+
// Default is true, uncomment to false
30+
//#define CHANGING_PWM_END_OF_CYCLE false
31+
32+
#define MAX_STM32_PWM_FREQ 1000
33+
34+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
35+
#include "STM32_Slow_PWM.h"
36+
37+
#define LED_OFF LOW
38+
#define LED_ON HIGH
39+
40+
#ifndef LED_BUILTIN
41+
#define LED_BUILTIN 13
42+
#endif
43+
44+
#ifndef LED_BLUE
45+
#define LED_BLUE 2
46+
#endif
47+
48+
#ifndef LED_RED
49+
#define LED_RED 3
50+
#endif
51+
52+
#define HW_TIMER_INTERVAL_US 20L
53+
54+
volatile uint64_t startMicros = 0;
55+
56+
// Depending on the board, you can select H7 Hardware Timer from TIM1-TIM22
57+
// If you select a Timer not correctly, you'll get a message from compiler
58+
// 'TIMxx' was not declared in this scope; did you mean 'TIMyy'?
59+
60+
// STM32 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17
61+
// STM32 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22
62+
// STM32 No timer : TIM9, TIM10, TIM11. Only for F2, F4 and STM32L1
63+
// STM32 No timer : TIM18, TIM19, TIM20, TIM21, TIM22
64+
65+
// Init timer TIM1
66+
STM32Timer ITimer(TIM1);
67+
68+
// Init STM32_Slow_PWM
69+
STM32_Slow_PWM ISR_PWM;
70+
71+
//////////////////////////////////////////////////////
72+
73+
void TimerHandler()
74+
{
75+
ISR_PWM.run();
76+
}
77+
78+
//////////////////////////////////////////////////////
79+
80+
#define NUMBER_ISR_PWMS 16
81+
82+
#define PIN_D0 D0
83+
#define PIN_D1 D1
84+
#define PIN_D2 D2
85+
#define PIN_D3 D3
86+
#define PIN_D4 D4
87+
#define PIN_D5 D5
88+
#define PIN_D6 D6
89+
#define PIN_D7 D7
90+
#define PIN_D8 D8
91+
#define PIN_D9 D9
92+
#define PIN_D10 D10
93+
#define PIN_D11 D11
94+
#define PIN_D12 D12
95+
96+
//////////////////////////////////////////////////////
97+
98+
#define USING_PWM_FREQUENCY true
99+
100+
//////////////////////////////////////////////////////
101+
102+
// You can assign pins here. Be carefull to select good pin to use or crash, e.g pin 6-11
103+
uint32_t PWM_Pin[] =
104+
{
105+
LED_BUILTIN, LED_BLUE, LED_RED, PIN_D0, PIN_D1, PIN_D2, PIN_D3, PIN_D4,
106+
PIN_D5, PIN_D6, PIN_D7, PIN_D8, PIN_D9, PIN_D10, PIN_D11, PIN_D12
107+
};
108+
109+
// You can assign any interval for any timer here, in microseconds
110+
uint32_t PWM_Period[] =
111+
{
112+
1000000, 500000, 333333, 250000, 200000, 166667, 142857, 125000,
113+
111111, 100000, 66667, 50000, 40000, 33333, 25000, 20000
114+
};
115+
116+
// You can assign any interval for any timer here, in Hz
117+
float PWM_Freq[] =
118+
{
119+
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
120+
9.0f, 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 40.0f, 50.0f
121+
};
122+
123+
// You can assign any interval for any timer here, in milliseconds
124+
float PWM_DutyCycle[] =
125+
{
126+
5.00, 10.00, 20.00, 30.00, 40.00, 45.00, 50.00, 55.00,
127+
60.00, 65.00, 70.00, 75.00, 80.00, 85.00, 90.00, 95.00
128+
};
129+
130+
typedef void (*irqCallback) ();
131+
132+
133+
// In STM32, avoid doing something fancy in ISR, for example complex Serial.print with String() argument
134+
// The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment
135+
// Or you can get this run-time error / crash
136+
void doingSomething0()
137+
{
138+
}
139+
140+
void doingSomething1()
141+
{
142+
}
143+
144+
void doingSomething2()
145+
{
146+
}
147+
148+
void doingSomething3()
149+
{
150+
}
151+
152+
void doingSomething4()
153+
{
154+
}
155+
156+
void doingSomething5()
157+
{
158+
}
159+
160+
void doingSomething6()
161+
{
162+
}
163+
164+
void doingSomething7()
165+
{
166+
}
167+
168+
void doingSomething8()
169+
{
170+
}
171+
172+
void doingSomething9()
173+
{
174+
}
175+
176+
void doingSomething10()
177+
{
178+
}
179+
180+
void doingSomething11()
181+
{
182+
}
183+
184+
void doingSomething12()
185+
{
186+
}
187+
188+
void doingSomething13()
189+
{
190+
}
191+
192+
void doingSomething14()
193+
{
194+
}
195+
196+
void doingSomething15()
197+
{
198+
}
199+
200+
irqCallback irqCallbackStartFunc[NUMBER_ISR_PWMS] =
201+
{
202+
doingSomething0, doingSomething1, doingSomething2, doingSomething3,
203+
doingSomething4, doingSomething5, doingSomething6, doingSomething7,
204+
doingSomething8, doingSomething9, doingSomething10, doingSomething11,
205+
doingSomething12, doingSomething13, doingSomething14, doingSomething15
206+
};
207+
208+
////////////////////////////////////////////////
209+
210+
void setup()
211+
{
212+
Serial.begin(115200);
213+
while (!Serial);
214+
215+
delay(2000);
216+
217+
Serial.print(F("\nStarting ISR_16_PWMs_Array on ")); Serial.println(BOARD_NAME);
218+
Serial.println(STM32_SLOW_PWM_VERSION);
219+
220+
// Interval in microsecs
221+
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler))
222+
{
223+
startMicros = micros();
224+
Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros);
225+
}
226+
else
227+
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
228+
229+
#if 1
230+
// Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
231+
// You can use up to 16 timer for each ISR_PWM
232+
for (uint16_t i = 0; i < NUMBER_ISR_PWMS; i++)
233+
{
234+
//void setPWM(uint32_t pin, float frequency, float dutycycle
235+
// , timer_callback_p StartCallback = nullptr, timer_callback_p StopCallback = nullptr)
236+
237+
#if USING_PWM_FREQUENCY
238+
239+
// You can use this with PWM_Freq in Hz
240+
ISR_PWM.setPWM(PWM_Pin[i], PWM_Freq[i], PWM_DutyCycle[i], irqCallbackStartFunc[i]);
241+
242+
#else
243+
#if USING_MICROS_RESOLUTION
244+
// Or using period in microsecs resolution
245+
ISR_PWM.setPWM_Period(PWM_Pin[i], PWM_Period[i], PWM_DutyCycle[i], irqCallbackStartFunc[i]);
246+
#else
247+
// Or using period in millisecs resolution
248+
ISR_PWM.setPWM_Period(PWM_Pin[i], PWM_Period[i] / 1000, PWM_DutyCycle[i], irqCallbackStartFunc[i]);
249+
#endif
250+
#endif
251+
}
252+
#endif
253+
}
254+
255+
void loop()
256+
{
257+
}

0 commit comments

Comments
 (0)