Pulsación corta y larga con stm32f0

0

Estoy tratando de entender el temporizador de stm32f0 sin usar la biblioteca stm, en particular estoy usando el tablero de descubrimiento stmf051 .

Lo que estoy tratando de hacer es un programa simple que detecta cuando se presiona brevemente o se presiona un botón.

Por lo tanto, el programa sería simplemente iniciar un contador cuando el microcontrolador detecte un botón y si ARR (valor de recarga automática) alcance el límite, encienda el límite. verde en la pizarra, de lo contrario, encienda azul en la pizarra.

Lo que surgió hasta ahora al ver el ejemplo en la hoja de datos y en este sitio web, es este fragmento de código, funciona pero hay un problema de debouncing (He actualizado el código y ahora el problema de debouncing está resuelto), y no estoy satisfecho con él.

Así que, por favor, ¿puedes ayudarme a mejorar mi código, mostrarme una mejor manera de hacerlo o simplemente señalarme la dirección correcta?

Gracias por tu tiempo, y lo siento por mi mal inglés.

    #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;
    }
    
pregunta Enrico Tolotto

1 respuesta

1

El código podría mejorarse enormemente.

Primero, los retrasos son malos, muy malos, no los uses. Retrasa tu código y lo mantiene quieto. El código que tienes ahora solo puede hacer una cosa. Si alguna vez quisiste codificar para hacer algo más, sería difícil.

Hay mejores formas de escribir eventos dependientes del tiempo.

  1. Configura un temporizador que cuente con una buena cantidad de tiempo, como un milisegundo.
  2. En el servicio de bucle principal, el temporizador y establece indicadores para eventos de tiempo. Por ejemplo; 1 segundo, 500 milisegundos, 10 milisegundos y así sucesivamente.
  3. En el bucle principal después de que el servicio del temporizador tenga sentencias IF que se activen según las marcas de tiempo. Por ejemplo parpadeando una luz; cada vez que se establece el indicador de 500 milisegundos, la instrucción IF entra en funcionamiento e invierte la luz y luego restablece el indicador.
  4. Para el rebote. Almacena una variable principal que realiza un seguimiento del botón. Cada milisegundo comprueba el botón. Si el botón no coincide con el estado almacenado, inicie un rebote. Para el rebote inicie un contador a 50. Continúe presionando el botón cada milisegundo. Si el botón está alto, agregue 1 al contador. Si el botón está bajo, resta uno del contador. Si el contador llega a 0, el botón está bajo. Si el contador llega a 100, entonces el botón está alto. Almacene ese valor en la variable del botón principal. Finalmente reinicie el indicador de rebote, de esa manera no siempre estará rebotando.

Esta es solo una forma de hacerlo, hay otras. Esto crea un sistema operativo flexible que puede manejar eventos cronometrados.

    
respondido por el vini_i

Lea otras preguntas en las etiquetas