Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ARM
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
SimplyLovely
Здравствуйте, столкнулся с проблемой, что не могу найти как сделать однократное прочтение состояния кнопки.

Код
  while(1)
  {
    //Если нажатa кнопка...
    if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1)
    {
      Start();
      GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);
    }
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==1)
    {
      Time += 1000;
      GPIO_ResetBits (GPIOB,GPIO_Pin_11);
    }
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)==1)
    {
      Time -= 1000;
      GPIO_WriteBit (GPIOB,GPIO_Pin_12, Bit_RESET);
    }
        
  }


Мне нужно что бы нажатие кнопки включало функцию один раз, а не несколько раз на протяжении всего времени нажатия.
kovigor
Цитата(SimplyLovely @ Nov 7 2013, 15:03) *
Мне нужно что бы нажатие кнопки включало функцию один раз, а не несколько раз на протяжении всего времени нажатия.

Подавление дребезга нужно сделать. Дребезг не очень хорошей кнопки может запросто длиться >20 мС. Можно, например, сделать так: после обнаружения нажатия кнопки не реагировать на ее состояние в течение, например, 50 мС. Это очень удобно делать по прерыванию от таймера. Например, прерывание возникает раз в 50 мс, и вы опрашиваете клавиатуру только при возникновении прерывания (т.е., в обработчике прерывания).
В некоторых задачах нужно также дождаться отпускания кнопки, опять же, подавляя возникающий при этом дребезг.
SimplyLovely
Насколько я понял, нужно сделать выполнение функции, после того как кнопка будет нажата и отпущена?
Как это можно реализовать?

Просто пока я нажимаю кнопку, цикл успевает 200000 раз пройти и значение Time вырастает непомерно.
igorle
Код
  int is_pressed = 0;
  while(1)
  {
    //Если нажатa кнопка...
    if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1)
    {
        /* Защита от дребезга  */
        if (is_pressed < 200 && is_pressed++ != 100 )
            Start();
        GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);
    }
    else
        is_pressed = 0;
    ...
    sleep(1);
  }
Сергей Борщ
Кто-нибудь может объяснить, что должна делать вот эта строка?
CODE
GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);
SimplyLovely
Цитата(Сергей Борщ @ Nov 7 2013, 14:43) *
Кто-нибудь может объяснить, что должна делать вот эта строка?
Код
GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);


Так я думал сбрасывать бит нажатия кнопки.

Но не получилось.

Цитата(igorle @ Nov 7 2013, 14:39) *
Код
  int is_pressed = 0;
  while(1)
  {
    //Если нажатa кнопка...
    if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1)
    {
        /* Защита от дребезга  */
        if (is_pressed < 200 && is_pressed++ != 100 )
            Start();
        GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);
    }
    else
        is_pressed = 0;
    ...
    sleep(1);
  }


Говорит что функция sleep() задана неявно
Видимо без этой функции работать не будет.
А как можно обрабатывать нажатие не через цикл?
Заодно прилагаю код полностью.
Код
//Не забываем подключить заголовочный файл с описание регистров микроконтроллера

#include "stm32f10x.h"
#include "stm32f10x_conf.h"

static __IO uint32_t TimingDelay;

void Delay_ms(__IO uint32_t nTime);//обьявляем функцию отсчета времени

void Start (void); //обьявляем функцию начала работы мотора
  
unsigned int Time = 1000;//переменная хранящая время задержки

//Наша главная функция

void main(void)
{
  SysTick_Config(24000);

  //Разрешаем тактирование шины порта B
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  //Объявляем структуру для настройки порта
  GPIO_InitTypeDef GPIO_Buttons;

  //Заполняем структуру начальными значениями
  GPIO_StructInit(&GPIO_Buttons);

  /* Запишем в поле GPIO_Pin структуры GPIO_Init_struct номер вывода порта, который мы будем     настраивать далее */
  GPIO_Buttons.GPIO_Pin  = (GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12);

  // Подобным образом заполним поля GPIO_Speed и GPIO_Mode
  GPIO_Buttons.GPIO_Speed= GPIO_Speed_2MHz;
  GPIO_Buttons.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  
  //Передаем заполненную структуру, для выполнения действий по настройке регистров
  GPIO_Init(GPIOB, &GPIO_Buttons);
  
  //Разрешаем тактирование шины порта C
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  
  //Объявляем структуру для настройки порта
  GPIO_InitTypeDef GPIO_Motor;

  //Заполняем структуру начальными значениями
  GPIO_StructInit(&GPIO_Motor);
  
  // Настраеваем пины вывода управления мотором
  GPIO_Motor.GPIO_Pin  = (GPIO_Pin_8 | GPIO_Pin_9);
  GPIO_Motor.GPIO_Speed= GPIO_Speed_2MHz;
  GPIO_Motor.GPIO_Mode = GPIO_Mode_Out_PP;
  
  // Передаем заполненую структуру, для выполнения действий по настройке регистров
  GPIO_Init(GPIOC, &GPIO_Motor);
  
int is_pressed = 0;
  while(1)
  {
    //Если нажатa кнопка...
     if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1)
    {
        /* Защита от дребезга  */
        if (is_pressed < 200 && is_pressed++ != 100 )
            Start();
    }
    else
        is_pressed = 0;

    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==1)
    {
      /* Защита от дребезга  */
        if (is_pressed < 200 && is_pressed++ != 100 )
            Time += 1000;
    }
    else
        is_pressed = 0;
    
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)==1)
    {
      /* Защита от дребезга  */
        if (is_pressed < 200 && is_pressed++ != 100 )
            Time -= 1000;
    }
    else
        is_pressed = 0;
    
        
  }
}

void Start (void) //функция начала работы
{
  GPIO_SetBits(GPIOC, GPIO_Pin_9);
  Delay_ms(1000);
  GPIO_ResetBits(GPIOC, GPIO_Pin_9);
  Delay_ms(Time);
  GPIO_SetBits(GPIOC, GPIO_Pin_8);
  Delay_ms(1000);
  GPIO_ResetBits(GPIOC, GPIO_Pin_8);
}


//Функция временной задержки
void Delay_ms(__IO uint32_t nTime)
{
  TimingDelay = nTime;
  while(TimingDelay != 0);
}

void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  {
    TimingDelay--;
  }
}

//Обработчик прерывания системного таймера
void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}
kovigor
Цитата(SimplyLovely @ Nov 7 2013, 14:59) *
Но не получилось.

Выкиньте все эти заумные вызовы и сделайте обычный обработчик прерывания от таймера. Пусть он вызывается 20 раз в секунду. В обработчике проверяйте, нажата ли кнопка. Если да, вызовите свою функцию. После чего ждите отпускания кнопки, всякий раз при воникновении прерывания проверяя, отпущена ли она. Все.
Проще всего сделать цифровой автомат, состояния которого будут переключаться в обработчике.
Сергей Борщ
QUOTE (SimplyLovely @ Nov 7 2013, 14:59) *
Так я думал сбрасывать бит нажатия кнопки.

Но не получилось.
Естественно. Кнопку-то никто не отпустил и этот бит выставился снова. Точнее, он даже сбрасываться не будет.

Заведите переменную "предыдущее состояние кнопки" и вызывайте свою функцию только в случае "предыдущее состояние - отпущена, текущее состояние - нажата".
kovigor
Цитата(SimplyLovely @ Nov 7 2013, 14:59) *
Так я думал сбрасывать бит нажатия кнопки.

Вот вам блок-схема, с подавлением дребезга, ожиданиями нажатий и отпусканий:
http://zalil.ru/34799986

smk
Я обычно при нажатии кнопки запоминаю какая нажата и запускаю таймер. А в прерывании таймера проверяю та ли кнопка все еще нажата и от этого отталкиваюсь.
Lagman
Если после нажатия кнопки и после выполнения действия больше делать ничего не надо кроме как ждать отпускания кнопки то
Код
    if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1)
    {
      Start();
      GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);
      while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10));
    }

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1x)); наверно поможет
SimplyLovely
Вобщем я сделал так.

Код
  unsigned int check_button1 = 0;//флаг нажатия кнопки
  unsigned int check_button2 = 0;
  unsigned int check_button3 = 0;
   while(1)
  {
    //Если нажатa кнопка...
    if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1 && check_button1 == 0)
    {
      Start();
      check_button1 = 1;
    }
    else if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)== 0)
      check_button1 = 0;
    
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==1 && check_button2 == 0)
    {
      Time += 1000;
      check_button2 = 1;
    }
    else if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)== 0)
      check_button2 = 0;
    
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)==1 && check_button3 == 0)
    {
      Time -= 1000;
      check_button3 = 1;
    }
    else if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)== 0)
      check_button3 = 0;
    
        
  }


Если кому не сложно, подскажите как через приерывания сделать.
И еще как реализовать задержку с помощью таймера TIM_6 или TIM_7.
А то с системным проблемы какие-то у меня, начинает подвисать иногда.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.