Понятно. Аналог задержки, но без задержки...Alexeyslav писал(а):каждое 10-е прерывание - тупо запоминаем состояние портов с кнопками и всё.
Опрос кнопок микроконтроллером
Re: Помогите опросить кнопку
- КРАМ
- Друг Кота
- Сообщения: 25151
- Зарегистрирован: Чт янв 10, 2008 22:01:02
- Откуда: Московская область, Фрязино
Re: Помогите опросить кнопку
Барсик писал(а):В чём смысл отложить опрос состояния кнопок на 10 мс?
Не отложить, а ЗАЩЕЛКИВАТЬ состояние кнопки раз в 10 мс. Тут дело не в 10 мс, а во времени дребезга кнопки. При защелкивании состояния кнопки реже, чем длится дребезг, дребезг исчезнет.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Помогите опросить кнопку
зачем откладывать? бери и пользуйся. Вот прямо как прерывание произошло, состояние защелкнули - так сразу можешь брать и пользоваться. Смысл в чем, в том что состояние кнопок фиксируется один раз за цикл, и даже если фиксация попадёт на момент дребезга - максимум что может быть то один раз зафиксируем неверное состояние кнопки в момент перехода а это чревато только тем что нажатие мы увидим в худшем случае на следующий цикл опроса. Но сам дребезг программа не увидит.
из этого кстати следует естественное ограничение данного алгоритма - кнопка может быть в нажатом(отпущенном) состоянии для правильной работы не менее 2-х циклов опроса. Если не соблюсти это условие максимум что случится - пропустим событие нажатия кнопки. Человек, к примеру, так быстро нажимать кнопки не сможет. А для концевых выключателей или датчиков частоты вращения вала нужны другие методы подавления дребезга, зачастую даже механические.
из этого кстати следует естественное ограничение данного алгоритма - кнопка может быть в нажатом(отпущенном) состоянии для правильной работы не менее 2-х циклов опроса. Если не соблюсти это условие максимум что случится - пропустим событие нажатия кнопки. Человек, к примеру, так быстро нажимать кнопки не сможет. А для концевых выключателей или датчиков частоты вращения вала нужны другие методы подавления дребезга, зачастую даже механические.
Re: Помогите опросить кнопку
Дошло... Спасибо.КРАМ писал(а):...а ЗАЩЕЛКИВАТЬ...
проблема при подключение кнонки к atmega8...
По задумке по нажатию кнопки должен загораться светодиод и гореть 3 сек.
Подключил кнопку, сделал подтяжку пина к земле. Сигнал на пин поступает, но не обрабатывается.
Подскажите что не так. Или это просто протеус логает

Подключил кнопку, сделал подтяжку пина к земле. Сигнал на пин поступает, но не обрабатывается.
Подскажите что не так. Или это просто протеус логает
Спойлер

Код: Выделить всё
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void){
DDRB |= (1<<PB7);
DDRC &= ~(1<<PC3);
while(1){
if((PINC & (1<<PC3)) == 1){ //If switch is pressed
PORTB |= (1<<PB7); //Turns ON LED
_delay_ms(3000); //3 second delay
PORTB &= ~(1<<PB7); //Turns OFF LED
}
}
}
- Вложения
-
- кнопка.rar
- :
Proteus
CVAVR 5.0 - (39 КБ) 345 скачиваний
Последний раз редактировалось nurekil Пт ноя 13, 2015 00:33:34, всего редактировалось 2 раза.
- Mishany
- Электрический кот
- Сообщения: 1031
- Зарегистрирован: Чт июн 20, 2013 00:00:58
- Откуда: москва, м.Сходненская
Re: проблема при подключение кнонки к atmega8...
if(PINC & (1<<PC3) == 1){ //If switch is pressed
не хватает скобок if((PINC&(1<<PC3))==1){
не хватает скобок if((PINC&(1<<PC3))==1){
Re: проблема при подключение кнонки к atmega8...
Mishany писал(а):if(PINC & (1<<PC3) == 1){ //If switch is pressed
не хватает скобок if((PINC&(1<<PC3))==1){
Спсибо, исправил. Но, к сожалению, не работает.
- B@R5uk
- Собутыльник Кота
- Сообщения: 2896
- Зарегистрирован: Сб ноя 13, 2010 12:53:25
- Откуда: приходит весна?
Re: проблема при подключение кнонки к atmega8...
Токоограничивающий резистор надо последовательно со светодиодом поставить.
Re: проблема при подключение кнонки к atmega8...
B@R5uk писал(а):Токоограничивающий резистор надо последовательно со светодиодом поставить.
Поставил. Сперва 110ом, а потом 150. Не загорается...

- СКАЗОЧНИК
- Идёт направо - песнь заводит, Налево - сказку говорит.
- Сообщения: 5000
- Зарегистрирован: Чт апр 21, 2011 17:55:50
- Откуда: Иркутск
Re: проблема при подключение кнонки к atmega8...
nurekil писал(а):Сперва 110ом, а потом 150. Не загорается..
В Протеусе моежешь не ставить. ))) Это в реальной жизни надо. А если так, то и приучаться к хорошему надо везде.
Может и херню скажу, но обычно кнопки ставят от порта на землю, а подтяжку делают к плюсу.... Как внутреннюю, так и внешнюю.
(это вроде традиции еще от старых МК пошло, если захотите - прочитаете). Здесь же в вашей схеме может так и задумано.
Косяк у вас в программе где-то...
Я плохо помню Си. А если в программе без всяких опросов кнопок сконфигурировать порт В7 на выход - будет светодиод гореть?
Станислав
- B@R5uk
- Собутыльник Кота
- Сообщения: 2896
- Зарегистрирован: Сб ноя 13, 2010 12:53:25
- Откуда: приходит весна?
Re: проблема при подключение кнонки к atmega8...
Отпаяйте базовый резистор от МК и подключите на плюс питания. Если не загорится и в этом случае, то проблема с транзистором или светодиодом.nurekil писал(а):Не загорается...
И если можно, то спрячте первую картинку под спойлер, а то не лезет форум по ширине в экран.
- СКАЗОЧНИК
- Идёт направо - песнь заводит, Налево - сказку говорит.
- Сообщения: 5000
- Зарегистрирован: Чт апр 21, 2011 17:55:50
- Откуда: Иркутск
Re: проблема при подключение кнонки к atmega8...
B@R5uk писал(а):Отпаяйте базовый резистор от МК и подключите на плюс питания.
В Протеусе???
Станислав
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: проблема при подключение кнонки к atmega8...
Код: Выделить всё
if((PINC & (1<<PC3)) == 1)Код: Выделить всё
if(PINC & (1<<PC3))Ну или вместо 1 напишите 0b00001000, но это лишнее.
Re: Помогите опросить кнопку
Всем спасибо за ответы. Помог совет в конце 2 страницы этой темы. Заработало 
Re: Помогите опросить кнопку
В большинстве телевизоров кнопки стоят на линии АЦП . всего два провода и до 6 кнопок .
а тут я накалякал на 3кнопки
а тут я накалякал на 3кнопки
Код: Выделить всё
void OPROS_KN ()
{ unsigned char VIBORKA1 ;
VIBORKA1= read_adc(0);
if ( VIBORKA1 >240 ) return; //ничего не нажато подтяжка тянет
delay_ms(15);
if (read_adc(0) >VIBORKA1+1 ) return; // если повторный уровень олтчается больше чем на +-1 то вых
if ( VIBORKA1 >read_adc(0)+1 ) return; // если повторный уровень олтчается больше чем на +-1 то вых
if (VIBORKA1<8) /// нажат выбор реж
{
if (Mode_SLCT <2) Mode_SLCT++;
else Mode_SLCT=0;
}
if (Mode_SLCT ==0)
{
LCD_PutChar (0, 0 ,80); //P
LCD_PutChar (9, 0 ,79); //O
LCD_PutChar (18, 0 ,82); //R
nlcd_Line(porog,10,porog, 160, black ) ;
if ( VIBORKA1>75 & VIBORKA1<85) porog=porog-2 ; // ацп канал 0 выход =80 нажат минус
if ( VIBORKA1>98 & VIBORKA1<108) porog=porog+2 ; // ацп канал 0 выход =103 нажат плюс
nlcd_Line(porog,10,porog, 160, yellow ) ;
print_int( 36,0, porog);
}
if (Mode_SLCT ==1)
{ LCD_PutChar (0, 0 ,77); //M
LCD_PutChar (9, 0 ,88); //X
LCD_PutChar (18, 0 ,61); //=
if ( VIBORKA1>75 & VIBORKA1<85) multiplerX++ ; // ацп канал 0 выход =80 нажат минус
if ( VIBORKA1>98 & VIBORKA1<108) multiplerX-- ; // ацп канал 0 выход =103 нажат плюс
if (multiplerX==0 ) multiplerX= 1 ;
print_int( 36,0, multiplerX);
}
if (Mode_SLCT ==2)
{ LCD_PutChar (0, 0 ,77); //M
LCD_PutChar (9, 0 ,89); //X
LCD_PutChar (18, 0 ,61); //=
if ( VIBORKA1>75 & VIBORKA1<85) { multiplerY=1; DEL_ON ; } // ацп канал 0 выход =80 нажат минус
if ( VIBORKA1>98 & VIBORKA1<108) { multiplerY=0 ;DEL_OFF; } // ацп канал 0 выход =103 нажат плюс
print_int( 36,0, multiplerY);
}
}
- Вложения
-
- кнопки.PNG
- кнопки в ТВ
- (55.87 КБ) 611 скачиваний
ух ты.... показывает
- prinv
- Вымогатель припоя
- Сообщения: 677
- Зарегистрирован: Чт янв 20, 2011 09:07:08
- Откуда: Пермь
- Контактная информация:
Программный антидребезг
Котаны, поделитесь удачными примерами программного антидребезга.
Делаю сейчас вот так
Но иногда не срабатывает, а иногда наоборот, дребезг всё-таки пролетает.
Помогут ли кондёры 0.1uF параллельно тактовым кнопкам?
Триггеры Шмидта будут в следующей конструкции.
Делаю сейчас вот так
Код: Выделить всё
// Чтение клавиатуры
do
{
_delay_ms(50); // Задержка от дребезга контактов
Key1 = PIND & ~PINSQW; // На PINSQW приходит меандр 1 Гц от DS1307, исключаем меандр из опроса клавиш.
_delay_ms(50);
Key2 = PIND & ~PINSQW;
}
while (Key1 != Key2);
Но иногда не срабатывает, а иногда наоборот, дребезг всё-таки пролетает.
Помогут ли кондёры 0.1uF параллельно тактовым кнопкам?
Триггеры Шмидта будут в следующей конструкции.
Никакая контра не уйдёт от нас
- Oxford
- Опытный кот
- Сообщения: 819
- Зарегистрирован: Вт окт 23, 2012 13:17:25
- Откуда: Прокопьевск
- Контактная информация:
Re: Программный антидребезг
https://www.youtube.com/watch?v=VD8OaPyAEtI
Тут хороший алгоритм разжеван. Сможете настроить фильтр.
Тут хороший алгоритм разжеван. Сможете настроить фильтр.
Инженер R@D
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
- prinv
- Вымогатель припоя
- Сообщения: 677
- Зарегистрирован: Чт янв 20, 2011 09:07:08
- Откуда: Пермь
- Контактная информация:
Re: Программный антидребезг
Большое спасибо!
Алгоритм понятен, попробую реализовать - посмотрим что получится.
Алгоритм понятен, попробую реализовать - посмотрим что получится.
Никакая контра не уйдёт от нас
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Программный антидребезг
Спойлер
Код: Выделить всё
// kbd_drv.h
//==================
#ifndef KBD_DRV_H
#define KBD_DRV_H
#include "kbd_drv.h"
#include "main_def_func.h"
//==================
//==================
#ifdef __PROJECT_MODE_WORK__
#define DEBOUNCE_DELAY 30
#define HOLD_1_DELAY 1500
#define HOLD_2_DELAY 2500
#define REPEAT_1_DELAY 150
#define REPEAT_2_DELAY 50
#endif
#ifdef __PROJECT_MODE_DEBUG__
#define DEBOUNCE_DELAY 3
#define HOLD_1_DELAY 5
#define HOLD_2_DELAY 7
#define REPEAT_1_DELAY 5
#define REPEAT_2_DELAY 3
#endif
//==================
//==================
#define KEY_ENTER 1
#define KEY_ENTER_BIT 1<<KEY_ENTER
//----------
#define KEY_MINUS 2
#define KEY_MINUS_BIT 1<<KEY_MINUS
//----------
#define KEY_PLUS 0
#define KEY_PLUS_BIT 1<<KEY_PLUS
//==================
//==================
#define KEYS_MASK (KEY_ENTER_BIT | KEY_MINUS_BIT | KEY_PLUS_BIT)
//==================
//==================
typedef enum kbd_codes
{
KEY_ENTER_COD = 1,
KEY_MINUS_COD,
KEY_PLUS_COD,
} kbd_codes;
//==================
//==================
#define HOLD 1<<7
#define REPEAT 1<<6
#define KEY_ENTER_HOLD_COD (KEY_ENTER_COD | HOLD)
#define KEY_MINUS_HOLD_COD (KEY_MINUS_COD | HOLD)
#define KEY_PLUS_HOLD_COD (KEY_PLUS_COD | HOLD)
#define KEY_ENTER_REPEAT_COD (KEY_ENTER_COD | REPEAT)
#define KEY_MINUS_REPEAT_COD (KEY_MINUS_COD | REPEAT)
#define KEY_PLUS_REPEAT_COD (KEY_PLUS_COD | REPEAT)
//==================
//==================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 1)
#define Set_Is_Key_Enter_Pressed() !(check_bit (spi_receive_buf [0], KEY_ENTER)) // Low level.
//#define Set_Is_Key_Enter_Pressed() check_bit (KEY_ENTER_PIN, KEY_ENTER) // High level.
#define Set_Is_Key_Minus_Pressed() !(check_bit (spi_receive_buf [0], KEY_MINUS)) // Low level.
//#define Set_Is_Key_Minus_Pressed() check_bit (KEY_MINUS_PIN, KEY_MINUS) // High level.
#define Set_Is_Key_Plus_Pressed() !(check_bit (spi_receive_buf [0], KEY_PLUS)) // Low level.
//#define Set_Is_Key_Plus_Pressed() check_bit (KEY_PLUS_PIN, KEY_PLUS) // High level.
// Ïðè ðàáîòå ñ áóôåðîì âõîäîâ (ðàñøèðåíèå ââîäà-âûâîäà):
// #define Set_Is_Key_Stop_Pressed() check_bit (inputs_buf [0], KEY_STOP)
//==================
//==================
typedef enum _kbd_drv
{
KBD_DRV_INIT = 0,
KBD_DRV_NOCHANGE,
KBD_DRV_CHANGE,
KBD_DRV_HOLD_REPEAT,
} kbd_drv_t;
//==================
//==================
typedef enum kbd_drv_mode
{
KBD_DRV_NO_MODE,
KBD_DRV_NOUNPRESS,
KBD_DRV_HOLD,
KBD_DRV_REPEAT_1,
KBD_DRV_REPEAT_2,
} kbd_drv_mode_t;
//==================
//==================
u08 scan_keys (void);
void kbd_drv (void);
void kbd_drv_init (void);
void kbd_drv_nochange (void);
void kbd_drv_change (void);
void kbd_drv_hold_repeat (void);
u08 recoding_keys (void);
u08 GetKeyCode (void);
//==================
#endif
Спойлер
Код: Выделить всё
//==================
#include "kbd_drv.h"
//==================
//==================
static kbd_drv_t _kbd_drv;
static kbd_drv_mode_t kbd_drv_mode;
static u08 keys_prev;
static u08 keys_curr;
static u08 keys_buf;
static soft_timer ST_KBD_1;
static soft_timer ST_KBD_2;
//==================
//==================
u08 scan_keys (void)
{
u08 a = 0;
if (Set_Is_Key_Enter_Pressed ()) a |= KEY_ENTER_BIT;
if (Set_Is_Key_Plus_Pressed ()) a |= KEY_PLUS_BIT;
if (Set_Is_Key_Minus_Pressed ()) a |= KEY_MINUS_BIT;
return a;
}
//==================
//==================
void kbd_drv (void)
{
keys_curr = scan_keys ();
switch (_kbd_drv)
{
case KBD_DRV_INIT: kbd_drv_init (); break;
case KBD_DRV_NOCHANGE: kbd_drv_nochange (); break;
case KBD_DRV_CHANGE: kbd_drv_change (); break;
case KBD_DRV_HOLD_REPEAT: kbd_drv_hold_repeat (); break;
}
}
//==================
//==================
#ifdef __PROJECT_MODE_WORK__
#pragma inline = forced
#endif
void kbd_drv_init (void)
{
#ifdef __PROJECT_MODE_DEBUG__
spi_receive_buf [0] = 0xFF;
#endif
kbd_drv_mode = KBD_DRV_NOUNPRESS;
keys_prev = 0xFF;
_kbd_drv = KBD_DRV_NOCHANGE;
}
//----------
#ifdef __PROJECT_MODE_WORK__
#pragma inline = forced
#endif
void kbd_drv_nochange (void)
{
if (keys_prev != keys_curr) // Если предыдущее состояние кнопок не равно предыдущему.
{
keys_prev = keys_curr;
reset_soft_timer (ST_KBD_2);
set_soft_timer (ST_KBD_1, DEBOUNCE_DELAY, 0); // Таймер подавления дребезга.
_kbd_drv = KBD_DRV_CHANGE;
}
}
//----------
#ifdef __PROJECT_MODE_WORK__
#pragma inline = forced
#endif
void kbd_drv_change (void)
{
if (keys_prev == keys_curr)
{
if (handle_soft_timer (ST_KBD_1)) // Таймер подавления дребезга.
{
if (keys_curr)
{
Set_Event (EV_ID_KEY_PRESSED, USER_EVENT);
keys_buf = recoding_keys ();
set_soft_timer (ST_KBD_1, HOLD_1_DELAY, 0); // Установка таймера удержания.
kbd_drv_mode = KBD_DRV_HOLD;
_kbd_drv = KBD_DRV_HOLD_REPEAT;
}
else
{
if (kbd_drv_mode == KBD_DRV_NOUNPRESS)
kbd_drv_mode = KBD_DRV_NO_MODE;
else
Set_Event (EV_ID_KEY_UNPRESSED, USER_EVENT);
_kbd_drv = KBD_DRV_NOCHANGE;
}
}
}
else
_kbd_drv = KBD_DRV_NOCHANGE;
}
//----------
#ifdef __PROJECT_MODE_WORK__
#pragma inline = forced
#endif
void kbd_drv_hold_repeat (void)
{
if (keys_prev == keys_curr)
{
switch (kbd_drv_mode)
{
case KBD_DRV_HOLD:
if (handle_soft_timer (ST_KBD_1))
{
Set_Event (EV_ID_KEY_PRESSED, USER_EVENT);
keys_buf = (recoding_keys () | HOLD);
set_soft_timer (ST_KBD_1, REPEAT_1_DELAY, REPEAT_1_DELAY);
set_soft_timer (ST_KBD_2, HOLD_2_DELAY, 0);
kbd_drv_mode = KBD_DRV_REPEAT_1;
}
break;
case KBD_DRV_REPEAT_1:
if (handle_soft_timer (ST_KBD_2))
{
set_soft_timer (ST_KBD_1, 0, REPEAT_2_DELAY);
kbd_drv_mode = KBD_DRV_REPEAT_2;
return;
}
case KBD_DRV_REPEAT_2:
if (handle_soft_timer (ST_KBD_1))
{
Set_Event (EV_ID_KEY_PRESSED, USER_EVENT);
keys_buf = (recoding_keys () | REPEAT);
}
break;
}
}
else
_kbd_drv = KBD_DRV_NOCHANGE;
}
//==================
//==================
u08 recoding_keys (void)
{
switch (keys_curr)
{
case KEY_ENTER_BIT: return KEY_ENTER_COD;
case KEY_PLUS_BIT: return KEY_PLUS_COD;
case KEY_MINUS_BIT: return KEY_MINUS_COD;
}
return 0;
}
//==================
//==================
u08 GetKeyCode (void)
{
return keys_buf;
}
//==================
- prinv
- Вымогатель припоя
- Сообщения: 677
- Зарегистрирован: Чт янв 20, 2011 09:07:08
- Откуда: Пермь
- Контактная информация:
Re: Программный антидребезг
У меня вот так получилось
Спойлер
Код: Выделить всё
// Чтение клавиатуры
Key = 0;
OldKey = 0;
KeyCount = 0;
do
{
Key = (~PIND) & (PINMODE|PINSET0|PINPLUS|PINMINUS);
if (Key == OldKey)
{
KeyCount++;
}
else
{
KeyCount = 0;
OldKey = Key;
}
_delay_ms(20);
}
while (KeyCount<5);Никакая контра не уйдёт от нас
