I'm trying to understand timer of stm32f0 without using the stm library, in particular I'm using the stmf051 discovery board.
What I'm trying to do is a simple program that detect when a button is short pressed or long pressed.
So the program would be simply start a counter when the microcontroller, detect a button is pressed and if the ARR (auto reload value) reach the limit, light the green led in the board otherwise, turn on the blue led in the board.
What came up so far looking at the example in the datasheet and in this web site, is this piece of code, that it works but there are some problem of debouncing (I've update the code and now the problem of debouncing is solved), and I'm not satisfied with it.
So please can you help me to improve my code, or show me a better way to do it, or simply point me in the right direction.
Thank you for your time, and sorry for my bad english.
#include "stm32f0xx.h"
short buttonPressed(void);
void delay(int a);
int main(void)
{
/* Enable the GPIO A,C,B */
RCC->AHBENR |=
(RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN);
// Enable Timer TIM2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC = 23999; // Set prescaler to 24 000 (PSC + 1)
TIM2->ARR = 800; // Auto reload value 800, for activate the green
// led you need to push the botton for at least 800 ms
TIM2->CR1 = TIM_CR1_CEN; // Enable timer
/* Configure PC8 and PC9 in output mode (led green and blue) */
GPIOC->MODER |= (GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0);
/* Button Pin PA0 in alternate function (user button in the board)*/
GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8 | ~GPIO_OTYPER_OT_9);
//Ensure maximum speed setting (even though it is unnecessary)
GPIOC->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9);
//Ensure all pull up pull down resistors are disabled
GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9);
while (1)
{
short answer = buttonPressed();
if (answer == 1)
{
GPIOC->BSRR = (1 << 9); // Blink the led in PC9 if the button is
delay(300000); // long pressed
GPIOC->BRR = (1 << 9); //
}
if (answer == 2)
{
GPIOC->BSRR = (1 << 8); // Blink the led in PC9 if the button is
delay(300000); // short pressed
GPIOC->BRR = (1 << 8); //
}
}
return 0;
}
short buttonPressed()
{
short return_value = 0;
if (GPIOA->IDR & GPIO_IDR_0) // If the button is pressed
{
delay(80000);
if (GPIOA->IDR | GPIO_IDR_0)
{
TIM2->EGR |= TIM_EGR_UG; // For an update generation with UG=1
TIM2->SR &= ~TIM_SR_UIF; // Clear TIM_ENV update interrupt so the ARR start from 0
while (GPIOA->IDR & GPIO_IDR_0)
{
} // Don't do anything until the button is released
if (TIM2->SR & TIM_SR_UIF) // If ARR reached 800 it means that it the button was long pressed
{
return_value = 1;
TIM2->SR &= ~TIM_SR_UIF; // Clear the ENV register
}
else // otherwise the button was short pressed
{
return_value = 2;
TIM2->SR &= ~TIM_SR_UIF; // Clear the ENV register
}
}
}
return return_value;
}
void delay(int a)
{
volatile int i, j;
for (i = 0; i < a; i++)
{
j++;
}
return;
}
Best Answer
The code could be improved greatly.
First, delays are bad, very bad, don't use delays. It slows your code down and holds it still. The code you have right now can only do one thing. If you ever wanted to code to do anything else it would be difficult.
There are better ways to write time dependent events.
This is just one way of doing it, there are others. This creates a limber operating system that can handle timed events.