Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.93/142: Рейтинг темы: голосов - 142, средняя оценка - 4.93
z-z
170 / 169 / 56
Регистрация: 22.06.2011
Сообщений: 980

обработка нажатия пользовательской кнопки

25.06.2012, 21:47. Показов 27867. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
написал, чтобы при нажатии кнопки менялось состояние диодов. но что то не стабильно он работает. иногда надо нажимать 5-6 раз, чтобы переключить состояние. хотя иногда переклчается сразу. в чем может быть проблема?

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   unsykned int control;
control = 1;
 
while(1)
{
if((GPIOA->IDR&0x01)==1) //нажатие кнопки
{
control = control << 1;
if (control>2) control = 1;
}
if(control == 1)
{
GPIOC->BSRR = GPIO_BSRR_BS9;
GPIOC->BSRR = GPIO_BSRR_BR8;
}
if(control == 2)
{
GPIOC->BSRR = GPIO_BSRR_BS8;
GPIOC->BSRR = GPIO_BSRR_BR9;
}
 
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.06.2012, 21:47
Ответы с готовыми решениями:

Обработка нажатия кнопки...
Есть программа для AVR, имитирует работу светофора, написана с Code Vision AVR. #define B_g PORTB=0b00000100; #define B_y...

Обработка нажатия кнопки
Есть кнопка без фиксатора( нажали отпустили и она разомкнулась) Как обработать событие нажали, она разомкнулась и программа дальше начала...

Обработка долгого нажатия кнопки
Оговорюсь что читал похожую тему на форуме и умею пользоватся поиском (так думаю)! Есть задача обработать короткое и длинное нажатие...

34
oordvork
29.06.2012, 23:12
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от z-z
а как тогда событие нажатия отследить?
Ну, как-то так (одновременно и с дребезгом поборемся):
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define MAXCNT 10
char flip=0, pressed=0;
 
while(1)
{
if((GPIOA->IDR&0x01)==0) //кнопка не нажата (или 0 читается во впемя дребезга) - готовимся к обработке
{
pressed=0;
cntr=0;
}
else
if(!pressed) //кнопка вроде бы нажата, но возможно это пока что только дребезг
{
cntr++; // сосчитаем до десяти в надежде, что за это время переходные процессы завершатся
if(cntr>MAXCNT) // десять последних проходов кнопка в состоянии "нажато" - считаем, что событие "нажатие кнопки" свершилось
{  // тут соб-сно ваша реакция на событие "нажатие кнопки", т.е. переход от 0 к 1
flip=!flip;  // организуем простейший двоичный переключатель ("flip-flop")
if(flip)      // и в зависимости от его состояния выполняем ту или иную ветвь
{
GPIOC->BSRR = GPIO_BSRR_BS9;
GPIOC->BSRR = GPIO_BSRR_BR8;
}
else
{
GPIOC->BSRR = GPIO_BSRR_BS8;
GPIOC->BSRR = GPIO_BSRR_BR9;
}
pressed=1;  // отработав событие "нажатие кнопки", отключаем проверку на это событие -> до следующего отпускания кнопки
}
}
else //кнопка в состоянии "нажато" (после отловленного события "нажатие кнопки") - в нашем случае неинтересно
{
}
}
z-z
170 / 169 / 56
Регистрация: 22.06.2011
Сообщений: 980
29.06.2012, 23:20
oordvork, а если я вместо двоичного переключателя сделаю больее количество переключений... в принципе и качестве работы ничего же не изменится, да?)
0
oordvork
29.06.2012, 23:30
Ну, поскольку в вашем примере рассматривалось два состояния переключателя, я счел за лучшее упростить соответствующий участок до невозможности.
Ну а если N>2, то да - как у вас ранее.
Кстати, MAXCNT, возможно, придется увеличить, если вдруг длительность импульсов при дребезге окажется больше времени, необходимого для пробегания 10 вышеописанных циклов - могут проскакивать ложные срабатывания.
z-z
170 / 169 / 56
Регистрация: 22.06.2011
Сообщений: 980
29.06.2012, 23:32
Цитата Сообщение от oordvork
Цитата Сообщение от z-z
а как тогда событие нажатия отследить?
Ну, как-то так (одновременно и с дребезгом поборемся):
Code
1
2
3
4
5
6
7
8
9
10
11
12
#define MAXCNT 10
char flip=0, pressed=0;
 
while(1)
{
if((GPIOA->IDR&0x01)==0) //кнопка не нажата (или 0 читается во впемя дребезга) - готовимся к обработке
{
pressed=0;
cntr=0;
}
else
if(!pressed)
я тут немного не понял. что значит if(!pressed) ? ведь pressed изначально определяется char flip=0, pressed=0; как он может быть !pressed ?))
0
oordvork
29.06.2012, 23:49
отрицание от 0 есть 1, т.е. истина.
Ветка if(!pressed) будет исполняться при значении pressed=0.
То есть когда на пине уже есть высокий уровень, но мы еще не уверены, что переключение на этот уровень произошло окончательно и бесповоротно (принимаем, что такая уверенность появится после MAXCNT циклов ожидания при высоком уровне на пине)
z-z
170 / 169 / 56
Регистрация: 22.06.2011
Сообщений: 980
29.06.2012, 23:56
спасибо) остановился на своем первоначальном варианте... правда надо около секунды удерживать кнопку, не знаю, почему. поставил даже delay(2); все равно ждать около секунды))
мне вот интересно стало. ведь редко где надо так нажимать и ждать... например кнопку ноута достаточно нажать и ждать даже на много меньше полусекунды)) как все эти нажатия обрабатываются тогда? или кнопки лучше и дребезга не возникает?)))
0
0 / 0 / 0
Регистрация: 06.04.2010
Сообщений: 1,088
30.06.2012, 01:13
Цитата Сообщение от z-z
спасибо) как все эти нажатия обрабатываются тогда? или кнопки лучше и дребезга не возникает?)))
Везде с механическми контактами возникает дребезг . Кнопку или через триггер подключают или программно с дребезгом борятся.
Суть приметно такова - обнаружил нажатие, посчитал в отдельном счетчике +1, через скажем млсек 10 проверил еще раз, если нажата - добавил еще +1 и т.д. если 5-10 проверок подряд кнопка нажата - значит считай, что это настоящее нажатие и обрабатывай его.
Делают и проще, после первого нажатия повторно через 20-30 млсек проверяют. Если все еще нажата - обрабатывается нажатие.
0
0 / 0 / 0
Регистрация: 06.04.2010
Сообщений: 1,088
30.06.2012, 02:31
Цитата Сообщение от moksir
Можно использовать стандартную библиотеку:
if (GPIO_ReadInputDataByt(GPIOC,GPIO_Pin_4) == Byt_RESIT)....
Можно и так(само коротко и быстро:
if (GPIOС->IDR & GPIO_IDR_IDR4)...
Громоздко ужасно.
Нельзя ли как-то по подобию игрушечных компиляторов сделать?

Code
1
2
#define pin_X  PORTA.1
if (pin_X == 1) {......}
0
0 / 0 / 0
Регистрация: 23.05.2012
Сообщений: 214
30.06.2012, 06:53
Цитата Сообщение от R_uro
Громоздко ужасно.
Нельзя ли как-то по подобию игрушечных компиляторов сделать?

Код:
#define pin_X PORTA.1
if (pin_X == 1) {......}

Так в чем проблема?
Code
1
2
#define pin_X  (GPIOС->IDR & GPIO_IDR_IDR4)
if (pin_X == 1) {......}
Надо понимать, что в ARM не на первом месте ногодрыганье, и даже не на втором...
0
0 / 0 / 0
Регистрация: 28.10.2010
Сообщений: 892
30.06.2012, 11:50
Цитата Сообщение от R_uro
Цитата Сообщение от moksir
Можно использовать стандартную библиотеку:
if (GPIO_ReadInputDataByt(GPIOC,GPIO_Pin_4) == Byt_RESIT)....
Можно и так(само коротко и быстро:
if (GPIOС->IDR & GPIO_IDR_IDR4)...
Громоздко ужасно.
Нельзя ли как-то по подобию игрушечных компиляторов сделать?

Code
1
2
#define pin_X  PORTA.1
if (pin_X == 1) {......}
Считается, что так общепонятно и кросплатформенно...
В отличии от такой записи:

JCP iB,4,M1
0
0 / 0 / 0
Регистрация: 19.01.2011
Сообщений: 72
30.06.2012, 12:57
Цитата Сообщение от z-z
md5sum, опять к вопросу о "массовом" переключении выводов... а если все надо включать и выключать их всех по очереди? включил 0, выключил 0, включил 1, выключил 1...... и так до конца... неужели никак нельзя сократить код? обязательно для каждого вывода писать GPIOB->ODR ^= ??))
например так:
Code
1
2
3
4
5
6
7
8
9
 int i;
int mask=1;
for(i=0;i++;i<16)
{
GPIOB->ODR ^=mask;
// что-то выполнили
GPIOB->ODR ^=mask;
mask<<=1;
}
включит/выключит по очереди 16 выводов
0
z-z
170 / 169 / 56
Регистрация: 22.06.2011
Сообщений: 980
30.06.2012, 13:34
md5sum, круто! спасибо, это то, что нужно))) это заменило около 120 строк кода на 9 строк!))))
0
0 / 0 / 0
Регистрация: 06.04.2010
Сообщений: 1,088
30.06.2012, 14:52
Цитата Сообщение от moksir
Так в чем проблема?
Код:
#define pin_X (GPIOС->IDR & GPIO_IDR_IDR4)
if (pin_X == 1) {......}

Это, как я понимаю, будет работать только , если надо проверить состояние пина.
Установить pin_X = 1; уже не получится.

Где-то видел, что можно порт представить в виде битового поля и тогда с отдельными битами можно обращаться уже и так
PORTA.0, PORTA.1 и т.д.;
Здесь это возможно?

Code
1
Надо понимать, что в ARM не на первом месте ногодрыганье, и даже не на втором...
Разные у людей задачи бывают. Не всем надо лезть в самые дебри устройства и системы команд ARM. Мне вот надо именно ногами подрыгать.
А с подобными конструкциями мозг сломать можно )))
Code
1
2
if (btn_old_state == 0 && btn_state == 1)
GPIO_WriteByt(GPIOC, LED1, !GPIO_ReadOutputDataByt(GPIOC, LED1));
Насколько понятнее
Code
1
2
#define    LED1   PORTC.2
if (btn_old_state == 0 && btn_state == 1)    LED = ~LED1;
0
0 / 0 / 0
Регистрация: 03.05.2012
Сообщений: 33
30.06.2012, 15:57
а прикрутить прерывание по нажатию кнопки никак? там тогда не нужно никих проверок после нажатия, так как раз срабатывает по фронту нажатия (как тут уж настроишь так и будеть)) или нужно именно читать порт?
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void Init_Key(void)
{
Init_Button( PORTA,  GPIO_Pin_0);  // инициализация пина на прием
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
 
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
 
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Ymtirrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_Line = EXTI_Line0;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
 
EXTI_Init(&EXTI_InitStruct);
 
NVIC_InitTypeDef NVIC_InitStructure;
 
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
 
}
 
void EXTI0_IRQHomdler(void)
{
 
.....
 
EXTI_ClearFlag(EXTI_Line0);
 
}
0
0 / 0 / 0
Регистрация: 06.04.2010
Сообщений: 1,088
30.06.2012, 19:00
Цитата Сообщение от Werman_Otix
а прикрутить прерывание по нажатию кнопки никак?
Так дребез длится миллисекунды, а бработчик обработает нажатие за несколько микросекунд, вернется в цикл и снова на дребезг среагирует. ))
К тому же, подавление дребезга программным путем, это не только подавление самого дребезга, но и проверка истинности нажатия, потому как кратковременная помеха тоже может проскочить и восприняться как нажатие.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.06.2012, 19:00

Обработка нажатия кнопки без фиксации
Здравствуйте! Помогите, пожалуйста. По идее, после нажатия первой кнопки, выполняется вся программа. При этом, имеются две другие кнопки,...

Обработка нажатия кнопок.
Здравствуйте! Подскажите где, как подправить чтобы правильно все заработало? Нажимаем на BUT1 загорается на установленное время и гаснет...

Событие нажатия кнопки.
Кнопка, замыкающаяся на землю подключена к PB0. Светодиод подключен к PB1. Как включить светодиод при нажатии кнопки? МК ATmega16. ...

Обработка нажатия кнопки
Здравствуйте. Имеется HTML код самой кнопки: &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset=&quot;utf-8&quot;&gt; ...

Обработка нажатия на кнопки
Всем привет! У меня есть несколько кнопок на форме. Допустим 5. Мне надо отловить нажатие каждой кнопки. Скажите пожалуйста, можно ли через...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru