This repository has been archived by the owner on Feb 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### 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
- Loading branch information
1 parent
13bc730
commit 4e4a7fe
Showing
8 changed files
with
1,478 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
/**************************************************************************************************************************** | ||
ISR_16_PWMs_Array.ino | ||
For F/L/H/G/WB/MP1 boards | ||
Written by Khoi Hoang | ||
Built by Khoi Hoang https://github.com/khoih-prog/STM32_Slow_PWM | ||
Licensed under MIT license | ||
Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by | ||
unsigned long miliseconds), you just consume only one timer and avoid conflicting with other cores' tasks. | ||
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers | ||
Therefore, their executions are not blocked by bad-behaving functions / tasks. | ||
This important feature is absolutely necessary for mission-critical tasks. | ||
*****************************************************************************************************************************/ | ||
|
||
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \ | ||
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \ | ||
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5)) | ||
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting. | ||
#endif | ||
|
||
// These define's must be placed at the beginning before #include "STM32_Slow_PWM.h" | ||
// _PWM_LOGLEVEL_ from 0 to 4 | ||
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. | ||
#define _PWM_LOGLEVEL_ 3 | ||
|
||
#define USING_MICROS_RESOLUTION true //false | ||
|
||
// Default is true, uncomment to false | ||
//#define CHANGING_PWM_END_OF_CYCLE false | ||
|
||
#define MAX_STM32_PWM_FREQ 1000 | ||
|
||
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error | ||
#include "STM32_Slow_PWM.h" | ||
|
||
#define LED_OFF LOW | ||
#define LED_ON HIGH | ||
|
||
#ifndef LED_BUILTIN | ||
#define LED_BUILTIN 13 | ||
#endif | ||
|
||
#ifndef LED_BLUE | ||
#define LED_BLUE 2 | ||
#endif | ||
|
||
#ifndef LED_RED | ||
#define LED_RED 3 | ||
#endif | ||
|
||
#define HW_TIMER_INTERVAL_US 20L | ||
|
||
volatile uint64_t startMicros = 0; | ||
|
||
// Depending on the board, you can select H7 Hardware Timer from TIM1-TIM22 | ||
// If you select a Timer not correctly, you'll get a message from compiler | ||
// 'TIMxx' was not declared in this scope; did you mean 'TIMyy'? | ||
|
||
// STM32 OK : TIM1, TIM4, TIM7, TIM8, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17 | ||
// STM32 Not OK : TIM2, TIM3, TIM5, TIM6, TIM18, TIM19, TIM20, TIM21, TIM22 | ||
// STM32 No timer : TIM9, TIM10, TIM11. Only for F2, F4 and STM32L1 | ||
// STM32 No timer : TIM18, TIM19, TIM20, TIM21, TIM22 | ||
|
||
// Init timer TIM1 | ||
STM32Timer ITimer(TIM1); | ||
|
||
// Init STM32_Slow_PWM | ||
STM32_Slow_PWM ISR_PWM; | ||
|
||
////////////////////////////////////////////////////// | ||
|
||
void TimerHandler() | ||
{ | ||
ISR_PWM.run(); | ||
} | ||
|
||
////////////////////////////////////////////////////// | ||
|
||
#define NUMBER_ISR_PWMS 16 | ||
|
||
#define PIN_D0 D0 | ||
#define PIN_D1 D1 | ||
#define PIN_D2 D2 | ||
#define PIN_D3 D3 | ||
#define PIN_D4 D4 | ||
#define PIN_D5 D5 | ||
#define PIN_D6 D6 | ||
#define PIN_D7 D7 | ||
#define PIN_D8 D8 | ||
#define PIN_D9 D9 | ||
#define PIN_D10 D10 | ||
#define PIN_D11 D11 | ||
#define PIN_D12 D12 | ||
|
||
////////////////////////////////////////////////////// | ||
|
||
#define USING_PWM_FREQUENCY true | ||
|
||
////////////////////////////////////////////////////// | ||
|
||
// You can assign pins here. Be carefull to select good pin to use or crash, e.g pin 6-11 | ||
uint32_t PWM_Pin[] = | ||
{ | ||
LED_BUILTIN, LED_BLUE, LED_RED, PIN_D0, PIN_D1, PIN_D2, PIN_D3, PIN_D4, | ||
PIN_D5, PIN_D6, PIN_D7, PIN_D8, PIN_D9, PIN_D10, PIN_D11, PIN_D12 | ||
}; | ||
|
||
// You can assign any interval for any timer here, in microseconds | ||
uint32_t PWM_Period[] = | ||
{ | ||
1000000, 500000, 333333, 250000, 200000, 166667, 142857, 125000, | ||
111111, 100000, 66667, 50000, 40000, 33333, 25000, 20000 | ||
}; | ||
|
||
// You can assign any interval for any timer here, in Hz | ||
float PWM_Freq[] = | ||
{ | ||
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, | ||
9.0f, 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 40.0f, 50.0f | ||
}; | ||
|
||
// You can assign any interval for any timer here, in milliseconds | ||
float PWM_DutyCycle[] = | ||
{ | ||
5.00, 10.00, 20.00, 30.00, 40.00, 45.00, 50.00, 55.00, | ||
60.00, 65.00, 70.00, 75.00, 80.00, 85.00, 90.00, 95.00 | ||
}; | ||
|
||
typedef void (*irqCallback) (); | ||
|
||
|
||
// In STM32, avoid doing something fancy in ISR, for example complex Serial.print with String() argument | ||
// The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment | ||
// Or you can get this run-time error / crash | ||
void doingSomething0() | ||
{ | ||
} | ||
|
||
void doingSomething1() | ||
{ | ||
} | ||
|
||
void doingSomething2() | ||
{ | ||
} | ||
|
||
void doingSomething3() | ||
{ | ||
} | ||
|
||
void doingSomething4() | ||
{ | ||
} | ||
|
||
void doingSomething5() | ||
{ | ||
} | ||
|
||
void doingSomething6() | ||
{ | ||
} | ||
|
||
void doingSomething7() | ||
{ | ||
} | ||
|
||
void doingSomething8() | ||
{ | ||
} | ||
|
||
void doingSomething9() | ||
{ | ||
} | ||
|
||
void doingSomething10() | ||
{ | ||
} | ||
|
||
void doingSomething11() | ||
{ | ||
} | ||
|
||
void doingSomething12() | ||
{ | ||
} | ||
|
||
void doingSomething13() | ||
{ | ||
} | ||
|
||
void doingSomething14() | ||
{ | ||
} | ||
|
||
void doingSomething15() | ||
{ | ||
} | ||
|
||
irqCallback irqCallbackStartFunc[NUMBER_ISR_PWMS] = | ||
{ | ||
doingSomething0, doingSomething1, doingSomething2, doingSomething3, | ||
doingSomething4, doingSomething5, doingSomething6, doingSomething7, | ||
doingSomething8, doingSomething9, doingSomething10, doingSomething11, | ||
doingSomething12, doingSomething13, doingSomething14, doingSomething15 | ||
}; | ||
|
||
//////////////////////////////////////////////// | ||
|
||
void setup() | ||
{ | ||
Serial.begin(115200); | ||
while (!Serial); | ||
|
||
delay(2000); | ||
|
||
Serial.print(F("\nStarting ISR_16_PWMs_Array on ")); Serial.println(BOARD_NAME); | ||
Serial.println(STM32_SLOW_PWM_VERSION); | ||
|
||
// Interval in microsecs | ||
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler)) | ||
{ | ||
startMicros = micros(); | ||
Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros); | ||
} | ||
else | ||
Serial.println(F("Can't set ITimer. Select another freq. or timer")); | ||
|
||
#if 1 | ||
// Just to demonstrate, don't use too many ISR Timers if not absolutely necessary | ||
// You can use up to 16 timer for each ISR_PWM | ||
for (uint16_t i = 0; i < NUMBER_ISR_PWMS; i++) | ||
{ | ||
//void setPWM(uint32_t pin, float frequency, float dutycycle | ||
// , timer_callback_p StartCallback = nullptr, timer_callback_p StopCallback = nullptr) | ||
|
||
#if USING_PWM_FREQUENCY | ||
|
||
// You can use this with PWM_Freq in Hz | ||
ISR_PWM.setPWM(PWM_Pin[i], PWM_Freq[i], PWM_DutyCycle[i], irqCallbackStartFunc[i]); | ||
|
||
#else | ||
#if USING_MICROS_RESOLUTION | ||
// Or using period in microsecs resolution | ||
ISR_PWM.setPWM_Period(PWM_Pin[i], PWM_Period[i], PWM_DutyCycle[i], irqCallbackStartFunc[i]); | ||
#else | ||
// Or using period in millisecs resolution | ||
ISR_PWM.setPWM_Period(PWM_Pin[i], PWM_Period[i] / 1000, PWM_DutyCycle[i], irqCallbackStartFunc[i]); | ||
#endif | ||
#endif | ||
} | ||
#endif | ||
} | ||
|
||
void loop() | ||
{ | ||
} |
Oops, something went wrong.