- Автор темы
- #1
При работе с отладочной платой STM столкнулся с проблемой — тактовая кнопка стала давать дребезг, из-за чего программа перестала адекватно воспринимать нажатия. Изложу здесь способы, которыми частично удалось решить ситуацию, буду рад, если кому-то будет чем дополнить/поправить меня.
Сразу оговорюсь, что задача стояла устранить неполадки именно программно. Хоть самым грамотным выбором и была бы реализация ФНЧ, но под рукой не всегда оказываются подходящий набор ЭРИ и паяльник. Изначально попробовал поискать какие-нибудь библиотеки, так как проблема, думаю, встречается довольно часто, но таких удобных функций для STM, как под Arduino, мне найти не удалось.
Чтобы искать решение рациональнее, для начала нужно понять, как именно этот дребезг общается с программой. Допустим, мы прописываем в коде, что за нажатую кнопку мы принимаем сигнал «1». При корректной работе тактовой кнопки, наша STM должна будет видеть однозначные фронты подъемы и спада, а, следовательно, и понимать, когда была нажата кнопка. Но при дребезге наш прямоугольный сигнал превращается в пилообразный, из-за чего вместо двух явных фронтов возникает несколько тысяч подъемов и спадов, которые программа может так же начать воспринимать за нажатия.
Способы решения очень зависят от тех задач, которые мы ставим перед нашей кнопкой. Пока квалифицируем их на три случая:
- необходима только фиксация факта нажатия, например, как когда мы вызываем лифт;
- нужное нам действие происходит только пока кнопка находится в нажатом состоянии, например, дверной звонок (пример грубый, но в каком-то смысле даже очень близкий);
- нужное нам действие начинается после первого нажатия и заканчивается после второго, например, кнопка включения телевизора.
Первый случай самый простой, так как хоть сигнал и начинает поступать очень хаотично, но нам важен лишь факт начала этого сигнала. Следовательно, нам грозит лишь ситуация, если кнопка вдруг может «вздрогнуть» сама по себе. Поскольку любое осмысленное нажатие куда более продолжительно, чем тот единичный сигнал, который может быть вызван самопроизвольным дребезгом, нам нужно лишь реализовать счетчик положительных состояний, максимальное значение которого можно подобрать исходя из скорости работы STM или же просто эмпирически.
Вот как это будет примерно выглядеть для кнопки, заведенной на пин A5:
#include "stm32f10x.h"
void work(a,b)
{}
int main()
{
GPIOA->ODR = (1 << 5);
unsigned int n;
if n > 99
{
n=0;
work(a,b);
}
if (!(GPIOA->IDR & (1 << 5)))
{
n++;
}
}
В данном примере мы берем для счетчика переменную n, которая не считает фронты, а увеличивается на 1 при каждом прогоне программы, где на пин A5 поступает единица. Как только количество таких прогонов достигает 100, переменная обнуляется и выполняется некая функция work. Вместо 100 может быть любое значение, которое можно подобрать самому — главное, чтобы оно было на порядок больше того, которое может дать нечаянный дребезг.
Разберем вторую ситуацию, при которой нам нужно еще и распознать отпуск кнопки. Добавим переменную m, которая будет показывать состояние кнопки, и будем ее менять в зависимости от того, сколько было насчитано поднятого или опущенного сигнала, попутно переключая внимание программы, чтобы не делать лишних действий и не есть нашу память.
unsigned int n,m,p;
if m == 1
{
work(a,b);
}
if ((m==0) && (GPIOA->IDR & (1 << 5)))
{
n++;
}
if ((m==1) && (!(GPIOA->IDR & (1 << 5))))
{
p++;
}
if n > 99
{
n=0;
m=1;
}
if p > 99
{
p=0;
m=0;
}
Описанный выше способ работает и для третьей задачи, но не на всех скоростях. Например, нажатия с разницей в пару секунд камень воспринимает без проблем, но вот если постараться прожать кнопку несколько раз достаточно быстро, STM почему-то может проигнорировать всю серию нажатий. Пытался уменьшить число прогонов с сотни до минимума, но в какой-то момент опять начинает проскакивать дребезг.
Из прочитанных материалов еще видел, как народ реализовывает подобные решения на прерываниях, но мне, честно говоря, пока мой топорный метод более по душе. Буду рад, если кто-то расскажет, как сам решал подобные проблемы на STM.
Сразу оговорюсь, что задача стояла устранить неполадки именно программно. Хоть самым грамотным выбором и была бы реализация ФНЧ, но под рукой не всегда оказываются подходящий набор ЭРИ и паяльник. Изначально попробовал поискать какие-нибудь библиотеки, так как проблема, думаю, встречается довольно часто, но таких удобных функций для STM, как под Arduino, мне найти не удалось.
Чтобы искать решение рациональнее, для начала нужно понять, как именно этот дребезг общается с программой. Допустим, мы прописываем в коде, что за нажатую кнопку мы принимаем сигнал «1». При корректной работе тактовой кнопки, наша STM должна будет видеть однозначные фронты подъемы и спада, а, следовательно, и понимать, когда была нажата кнопка. Но при дребезге наш прямоугольный сигнал превращается в пилообразный, из-за чего вместо двух явных фронтов возникает несколько тысяч подъемов и спадов, которые программа может так же начать воспринимать за нажатия.
Способы решения очень зависят от тех задач, которые мы ставим перед нашей кнопкой. Пока квалифицируем их на три случая:
- необходима только фиксация факта нажатия, например, как когда мы вызываем лифт;
- нужное нам действие происходит только пока кнопка находится в нажатом состоянии, например, дверной звонок (пример грубый, но в каком-то смысле даже очень близкий);
- нужное нам действие начинается после первого нажатия и заканчивается после второго, например, кнопка включения телевизора.
Первый случай самый простой, так как хоть сигнал и начинает поступать очень хаотично, но нам важен лишь факт начала этого сигнала. Следовательно, нам грозит лишь ситуация, если кнопка вдруг может «вздрогнуть» сама по себе. Поскольку любое осмысленное нажатие куда более продолжительно, чем тот единичный сигнал, который может быть вызван самопроизвольным дребезгом, нам нужно лишь реализовать счетчик положительных состояний, максимальное значение которого можно подобрать исходя из скорости работы STM или же просто эмпирически.
Вот как это будет примерно выглядеть для кнопки, заведенной на пин A5:
#include "stm32f10x.h"
void work(a,b)
{}
int main()
{
GPIOA->ODR = (1 << 5);
unsigned int n;
if n > 99
{
n=0;
work(a,b);
}
if (!(GPIOA->IDR & (1 << 5)))
{
n++;
}
}
В данном примере мы берем для счетчика переменную n, которая не считает фронты, а увеличивается на 1 при каждом прогоне программы, где на пин A5 поступает единица. Как только количество таких прогонов достигает 100, переменная обнуляется и выполняется некая функция work. Вместо 100 может быть любое значение, которое можно подобрать самому — главное, чтобы оно было на порядок больше того, которое может дать нечаянный дребезг.
Разберем вторую ситуацию, при которой нам нужно еще и распознать отпуск кнопки. Добавим переменную m, которая будет показывать состояние кнопки, и будем ее менять в зависимости от того, сколько было насчитано поднятого или опущенного сигнала, попутно переключая внимание программы, чтобы не делать лишних действий и не есть нашу память.
unsigned int n,m,p;
if m == 1
{
work(a,b);
}
if ((m==0) && (GPIOA->IDR & (1 << 5)))
{
n++;
}
if ((m==1) && (!(GPIOA->IDR & (1 << 5))))
{
p++;
}
if n > 99
{
n=0;
m=1;
}
if p > 99
{
p=0;
m=0;
}
Описанный выше способ работает и для третьей задачи, но не на всех скоростях. Например, нажатия с разницей в пару секунд камень воспринимает без проблем, но вот если постараться прожать кнопку несколько раз достаточно быстро, STM почему-то может проигнорировать всю серию нажатий. Пытался уменьшить число прогонов с сотни до минимума, но в какой-то момент опять начинает проскакивать дребезг.
Из прочитанных материалов еще видел, как народ реализовывает подобные решения на прерываниях, но мне, честно говоря, пока мой топорный метод более по душе. Буду рад, если кто-то расскажет, как сам решал подобные проблемы на STM.
Последние темы в этом разделе:
- Бот телеграмм звезд
- Подскажите хороший бесплатный впн на пк
- Объясните мне
- Монитор не хочет работать в 165 герц
- Подскажите пж I Roblox
- Как скачать все файлы из .mht?
- Серверы для начинающих разработчиков
- Подскажите пожалуйста хороший ВПН сервис для телефона
- GSM и SIP флуд жив?
- подскажите пожалуйста купить игры в псстор с украинского аккаунт