Reputation: 11
I'm using an STM32F411RE Nucleo board to develop some code for a digital guitar effects pedal, and I need to be able to implement a tap tempo.
I'm fairly inexperienced with coding in general. Does anybody know the easiest way to simply press a GPIO button twice, measuring the interval between the two presses, and assign that value to a parameter? Or at the very least just take that interval and flash an LED at that delay time? Assuming this is going to be utilizing some sort of interrupt.
Thanks!
Edit: I am using STM32CubeIDE with the HAL (Hardware Abstraction Layer) Library. I am able to easily read inputs and send outputs to various GPIO pins via the use of this library. I am also utilizing an external 8MHz clock.
Upvotes: 1
Views: 425
Reputation: 93566
If you need help with reading the input, setting the output, and the timing then the question is too broad and you should post separate questions for each concept. However, assuming you have the following fundamental building blocks:
bool getTempoInput() ;
- function that reads state of tempo setting input switch.void setTempoOutput( bool state)
- function that sets the state of the tempo indicator.unsigned getMillisecTick()
- function that returns a free-running millisecond count.Clearly the names and signature of the functions need not be as above, but that allows the following pseudo-code (since we do not know what actual framework or library you might be using - if any).
#define TEMPO_OUT_PULSE_WIDTH_MS 100
unsigned tempo_set_start_timestamp = 0 ;
unsigned tempo_millisec = 1000 ; // 1 second to start with (arbitrarily)
bool tempo_timing_in_progress = false ;
bool button_down = false ;
unsigned button_down_timestamp = 0 ;
unsigned tempo_start_timestamp = getMillisecTick() ;
setTempoOutput( true ) ; // LED on
for(;;)
{
// Get current millsec count
unsigned now = getMillisecTick() ;
//--------------------------------
// LED timing
//--------------------------------
unsigned time_since_start = tempo_start_timestamp - now ;
// If past end of LED on period...
if( time_since_start >= TEMPO_OUT_PULSE_WIDTH_MS )
{
// If past the endo the tempo period...
if( time_since_start >= tempo_millisec )
{
// Restart tempo period
tempo_start_timestamp = now ;
setTempoOutput( true ) ; // LED on
}
else
{
// LED off at end of pulse period
setTempoOutput( false ) ;
}
}
//--------------------------------
//--------------------------------
// Tempo set timing
//--------------------------------
// Get current button state
bool button_state = getTempoInput() ;
// If button down and previously up...
if( !button_down && button_state )
{
// Button pressed - timestamp it
button_down_timestamp = now ;
button_down = true ;
// If tempo set timing not in progress...
if( !tempo_timing_in_progress )
{
// Start timing
tempo_set_start_timestamp = now ;
tempo_timing_in_progress = true ;
}
else
{
// Set tempo, stop timing
tempo_millisec = tempo_set_start_timestamp - now ;
tempo_timing_in_progress = false;
}
}
else if( !button_state && button_down &&
button_down_timestamp >= 2 * TEMPO_OUT_PULSE_WIDTH_MS )
{
// Button up after debounce period
button_down = false ;
}
//--------------------------------
}
Treat the above as illustrative - I have no means of testing it, it may contain flaws. Important points are:
tempo_millisec
shared. The code could be better structured with these blocks in separate functions - (an exercise for the reader).Upvotes: 1