вторник, 12 сентября 2017 г.

Мигаем светодиодом с проверкой состояния кнопки по таймеру и фильтрацией дребезга.

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_exti.h"


// Функция-фильтр дребезга контактов. Фильтрует дребезг контактов,
// дожидается устойчивого состояния порта и возвращает 1 или 0.
int btn_press (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
   unsigned char buffer = 0x55; // буфер со значением 01010101
   int timeout = 200; // количество циклов проверки

   if (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == 0) //если кнопка сработала, запускаем цикл проверки
   {
      while (timeout-- > 0)
      {
          buffer = buffer << GPIO_ReadInputDataBit(GPIOx, GPIO_Pin); // записываем в буфер значение порта со сдвигом

          if (buffer == 0x00) // проверяем буфер на наличие нулей
          {
              return 0;
          }

          if (buffer == 0xFF) // проверяем буфер на наличие единиц
          {
              return 1;
          }

          uint32_t i;
          for (i=0;i<0x1000;i++); // задержка между проверками в 1 мс

      }
   }

   return 1;
}

int main(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Включаем тактирование порта A

    GPIO_InitTypeDef led; // светодиод
    led.GPIO_Speed = GPIO_Speed_50MHz;
    led.GPIO_Mode  = GPIO_Mode_Out_PP;
    led.GPIO_Pin   = GPIO_Pin_0;
    GPIO_Init(GPIOA, &led);

    GPIO_InitTypeDef button; // кнопка
    button.GPIO_Speed = GPIO_Speed_2MHz;
    button.GPIO_Mode  = GPIO_Mode_IPU;
    button.GPIO_Pin   = GPIO_Pin_1;
    GPIO_Init(GPIOA, &button);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseInitTypeDef timer;
    TIM_TimeBaseStructInit(&timer);
    timer.TIM_Prescaler = 7200-1; //устанавливаем делитель частоты основной шины
    timer.TIM_Period = 7200-1;
    timer.TIM_ClockDivision = 0;
    timer.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &timer);

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM2, ENABLE);  // Включаем таймер

    NVIC_EnableIRQ(TIM2_IRQn); // инициализация прерывания по таймеру

    while(1){}
}

void TIM2_IRQHandler(void) //обработчик прерывания
{
    if (btn_press(GPIOA, GPIO_Pin_1) == 0) // проверяем кнопку с фильтрацией дребезга
           {
               if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) // проверяем состояние светодиода
               {
                   GPIO_SetBits(GPIOA, GPIO_Pin_0); // зажигаем светодиод
               }
               else
               {
                   GPIO_ResetBits(GPIOA, GPIO_Pin_0); // тушим светодиод
               }
           }
}


Все отрабатывает как надо