реклама на сайте
подробности

 
 
> ARM, Кнопка
SimplyLovely
сообщение Nov 7 2013, 11:03
Сообщение #1





Группа: Новичок
Сообщений: 4
Регистрация: 7-11-13
Пользователь №: 79 088



Здравствуйте, столкнулся с проблемой, что не могу найти как сделать однократное прочтение состояния кнопки.

Код
  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);
    }
        
  }


Мне нужно что бы нажатие кнопки включало функцию один раз, а не несколько раз на протяжении всего времени нажатия.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
kovigor
сообщение Nov 7 2013, 11:30
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



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

Подавление дребезга нужно сделать. Дребезг не очень хорошей кнопки может запросто длиться >20 мС. Можно, например, сделать так: после обнаружения нажатия кнопки не реагировать на ее состояние в течение, например, 50 мС. Это очень удобно делать по прерыванию от таймера. Например, прерывание возникает раз в 50 мс, и вы опрашиваете клавиатуру только при возникновении прерывания (т.е., в обработчике прерывания).
В некоторых задачах нужно также дождаться отпускания кнопки, опять же, подавляя возникающий при этом дребезг.
Go to the top of the page
 
+Quote Post
SimplyLovely
сообщение Nov 7 2013, 11:39
Сообщение #3





Группа: Новичок
Сообщений: 4
Регистрация: 7-11-13
Пользователь №: 79 088



Насколько я понял, нужно сделать выполнение функции, после того как кнопка будет нажата и отпущена?
Как это можно реализовать?

Просто пока я нажимаю кнопку, цикл успевает 200000 раз пройти и значение Time вырастает непомерно.

Сообщение отредактировал SimplyLovely - Nov 7 2013, 11:41
Go to the top of the page
 
+Quote Post
igorle
сообщение Nov 7 2013, 11:39
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 338
Регистрация: 14-07-12
Пользователь №: 72 753



Код
  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);
  }
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 7 2013, 11:43
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Кто-нибудь может объяснить, что должна делать вот эта строка?
CODE
GPIO_WriteBit (GPIOB,GPIO_Pin_10, Bit_RESET);


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SimplyLovely
сообщение Nov 7 2013, 11:59
Сообщение #6





Группа: Новичок
Сообщений: 4
Регистрация: 7-11-13
Пользователь №: 79 088



Цитата(Сергей Борщ @ 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();
}


Сообщение отредактировал SimplyLovely - Nov 7 2013, 11:48
Go to the top of the page
 
+Quote Post
kovigor
сообщение Nov 7 2013, 13:25
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(SimplyLovely @ Nov 7 2013, 14:59) *
Но не получилось.

Выкиньте все эти заумные вызовы и сделайте обычный обработчик прерывания от таймера. Пусть он вызывается 20 раз в секунду. В обработчике проверяйте, нажата ли кнопка. Если да, вызовите свою функцию. После чего ждите отпускания кнопки, всякий раз при воникновении прерывания проверяя, отпущена ли она. Все.
Проще всего сделать цифровой автомат, состояния которого будут переключаться в обработчике.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 7 2013, 13:27
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (SimplyLovely @ Nov 7 2013, 14:59) *
Так я думал сбрасывать бит нажатия кнопки.

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

Заведите переменную "предыдущее состояние кнопки" и вызывайте свою функцию только в случае "предыдущее состояние - отпущена, текущее состояние - нажата".


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kovigor
сообщение Nov 7 2013, 13:57
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(SimplyLovely @ Nov 7 2013, 14:59) *
Так я думал сбрасывать бит нажатия кнопки.

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

Go to the top of the page
 
+Quote Post
smk
сообщение Nov 7 2013, 14:10
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Я обычно при нажатии кнопки запоминаю какая нажата и запускаю таймер. А в прерывании таймера проверяю та ли кнопка все еще нажата и от этого отталкиваюсь.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Nov 8 2013, 11:06
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Если после нажатия кнопки и после выполнения действия больше делать ничего не надо кроме как ждать отпускания кнопки то
Код
    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)); наверно поможет
Go to the top of the page
 
+Quote Post
SimplyLovely
сообщение Nov 8 2013, 16:07
Сообщение #12





Группа: Новичок
Сообщений: 4
Регистрация: 7-11-13
Пользователь №: 79 088



Вобщем я сделал так.

Код
  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.
А то с системным проблемы какие-то у меня, начинает подвисать иногда.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 21:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01458 секунд с 7
ELECTRONIX ©2004-2016