-
Notifications
You must be signed in to change notification settings - Fork 1k
HardwareTimer implementation #576
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small updates to perform and questions.
Else LGTM.
Thanks @ABOSTM
Remove field 'state' from timerPinInfo_t using digit_io_toggle api. Remove global variable 'g_lastPin' as TimerTone_pinInfo contains same info. Add some check to avoid NULL or NC usage. Avoid return in void returning function. Signed-off-by: Frederic.Pillon <[email protected]>
5285bcc
to
b3bbeeb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ABOSTM for the update.
The code at this line:
|
|
Could you add the encoder mode of the timer, there is no encoder API of HardwareTimer, but it's important. |
Hi @roc2 |
#if !defined(STM32F0xx) && !defined(STM32G0xx) | ||
case 2: | ||
uwAPBxPrescaler = clkconfig.APB2CLKDivider; | ||
uwTimclock = HAL_RCC_GetPCLK2Freq(); | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ABOSTM, do you remember why you added this exception (that PCLK2 is not supported on F0 and G0)? I just ran into TIM1 not working on a G030, and found this bit of code. It does seem that F0 and G0 actually have PCLK2 (I checked F030, G0x0 and G0x1 reference manuals). Is there maybe some code missing to enable this clock or so? Maybe @fpistm knows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @matthijskooijman
HAL_RCC_GetPCLK2Freq
does not exist for those series.
I've checked the reference manual for STM32G0x0 and found no PCLK2 only TIMPCLK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matthijskooijman , this is an inheritance of getTimerClkFreq()
from timer.c before implementation of HardwareTimer.
but this doesn't help you much :-)
The real reason behind is that this case 2
concerns TIMERs that are on APB2 bus, but looking at STM32F030 there is no ABP2. so the function HAL_RCC_GetPCLK2Freq()
doesn't exist on G0 and F0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NVM, we seem to have hit an older bug from a previous core version where getTimerClkSrc()
returned a clock source 2 instead of 1 and since case 2 is purposely not defined for the F0/G0 in getTimerClkFreq()
it would end up in case 0's Error_handler()
:-)
This has been fixed in the commit here (core version 2.0.0).
HardwareTimer
1. Introduction
The HardwareTimer library aims to provide access to part of STM32 hardware Timer feature (If other features are required, they could be accessed through STM32Cube HAL/LL).
The use of this library suppose you have some basic knowledge of STM32 hardware timer architecture.
First of all remind that all timers are not equivalent and doesn't support the same features. Please refer to the Reference Manual of your MCU.
Example:
TIM6
andTIM7
doesn't have outpin and this is the reason why, when available, they are used to implement Tone and Servo.whereas other timers have no complementary, or have only 1 or 2 channels...
Each timer may provide several channels, nevertheless it is important to understand that all channels of the same timer share the same counter as thus have the same period/frequency.
2. API
3. Usage
HardwareTimer
is a C++ class, 1st thing to do is to instantiate an object withTIM
instance as parameter.Example:
Then it is possible to configure mode of a channel.
Example:
MyTim->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin);
Supported Mode:
Then it is possible to configure PrescalerFactor. The Timer clock will be divided by this factor (if timer clock is 10Khz, and prescaler factor is 2, then timer will count at 5kHz).
setOverflow
withformat == MICROSEC_FORMAT
orformat == HERTZ_FORMAT
.Example:
Then it is possible to configure overflow (also called rollover or update).
For output it correspond to period or frequency.
For input capture it is suggested to use max value: 0x1000 to avoid rollover before capture occurs .
setOverflow
withformat == MICROSEC_FORMAT
orformat == HERTZ_FORMAT
.Example:
Then it is possible to configure CaptureCompare (channel specific CaptureCompare register).
Example:
It is possible to attach a callback on update interruption (rollover) and/or on Capture/Compare interruption.
If no channel is specified, callback is attach to update event.
Example:
It is now time to start timer.
Example:
MyTim->resume();
Timer can be paused then resumed
Below is an example of full PWM configuration.
Example:
To simplify basic PWM configuration, a dedicated all-in-one API is provided.
Overflow/frequency is in hertz, dutycycle in percentage.
Example:
Some additional APIs allow to retrieve configurations:
Also, to get ride of Interrupt callback:
detachInterrupt()
4. Examples
Following examples are provided in STM32Examples library (available with Arduino Library manager):
Timebase_callback.ino
This example shows how to configure HardwareTimer to execute a callback at regular interval.
Callback toggles pin.
Once configured, there is only CPU load for callbacks executions.
PWM_FullConfiguration.ino
This example shows how to fully configure a PWM with HardwareTimer.
PWM is generated on
LED_BUILTIN
if available.PWM is generated by hardware: no CPU load.
Nevertheless, in this example both interruption callback are used on Compare match (Falling edge of PWM1 mode) and update event (rising edge of PWM1 mode).
Those call back are used to toggle a second pin:
pin2
.Once configured, there is only CPU load for callbacks executions.
All-in-one_setPWM.ino
This example shows how to configure a PWM with HardwareTimer in one single function call.
PWM is generated on
LED_BUILTIN
if available.No interruption callback used: PWM is generated by hardware.
Once configured, there is no CPU load.
InputCapture.ino
This example shows how to configure HardwareTimer in inputcapture to measure external signal frequency.
Each time a rising edge is detected on the input pin, hardware will save counter value into CaptureCompare register.
External signal (signal generator for example) should be connected to
D2
.Measured frequency is displayed on Serial Monitor.
Frequency_Dutycycle_measurement.ino
This example shows how to configure HardwareTimer to measure external signal frequency and dutycycle.
The input pin will be connected to 2 channel of the timer, one for rising edge the other for falling edge.
Each time a rising edge is detected on the input pin, hardware will save counter value into one of the CaptureCompare register.
Each time a falling edge is detected on the input pin, hardware will save counter value into the other CaptureCompare register.
External signal (signal generator for example) should be connected to
D2
.5. Dependencies
Tone, Servo and analogwrite have been updated to use HardwareTimer.
New optional parameter destruct has been added to noTone to decide whether to destruct/free HardwareTimer object.
TODO:
Examples provided in STM32Examples library:
stm32duino/STM32Examples#12
Wiki: https://github.com/stm32duino/wiki/wiki/HardwareTimer-library
Fixes #146