Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CodeVisionAVR помогите по написанию!
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
ssvd
Задумка такая, надо одной кнопкой переключаться между циклами в которых что то выполняется, но если я нажимаю кнопку, то он проскакивает все циклы так как кнопку не успеваешь отпустить! Подскажите как лучше организовать алгоритм переключения одной кнопкой между циклами?!
Вот не правильный текст программы

Код
    //выводим на LCD "нажмите кнопку _start_"
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_putsf("Hello!");
    lcd_gotoxy(0,1);
    lcd_putsf("Press Start!");
    
    while(PINA.0){ } //бесконечный цекл, ждем нажатие кнопки старт!!!
    
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_putsf("Temp. beep");
    lcd_gotoxy(0,1);
    lcd_putchar(t_count);
    
    while(PINA.0){ //бесконечный цекл, ждем нажатие кнопки старт!!!
    //    if (PINA.3){ };
        if (PINA.1){ //если нажата кнопка +
            t_count++;
            lcd_gotoxy(0,1);
            lcd_putchar(t_count);
        };
        if (PINA.2){  //если нажата кнопка -
            t_count--;
            lcd_gotoxy(0,1);
            lcd_putchar(t_count);
        };
    }
demiurg_spb
Вам нужно применить алгоритм подавления дребезга контактов кнопки.
Иначе на одно нажатие пальцем будете получать 10-20 срабатываний.
Поищите информацию по форуму или в google. По-английски ключевое слово "debounce switch".
DRUID3
Нужно просто добавить задержку (насколько помню там есть спец-функции) и проверять "по прошествии" изменилось ли состояние ног.
demiurg_spb
Цитата(DRUID3 @ Oct 31 2009, 11:15) *
Нужно просто добавить задержку...
Если так сделать, до вся вычислительная мощность MCU будет расходоваться на молочение циклов в процедурах задержки.
А ведь это не есть гуд...
DRUID3
Разумно... Но для такого объема программы - самое оно wink.gif ... Кстати, дребезг контактов хорошо давится простейшей интегрирующей RC-цепочкой...
demiurg_spb
Цитата(DRUID3 @ Oct 31 2009, 11:31) *
Разумно... Но для такого объема программы - самое оно wink.gif ...
Согласен. Но лучше привыкать к хорошему тону с малолетства:-)
Цитата
Кстати, дребезг контактов хорошо давится простейшей интегрирующей RC-цепочкой...
Это да. Бывает даже так... Вопрос - а оно надо, если программно всё решается великолепно.
А RC цепочка в динамическом сканировании например не подходит, да и лишние элементы на плате, лишние пайки, деньги...
ssvd
Цитата(demiurg_spb @ Oct 31 2009, 12:48) *
Согласен. Но лучше привыкать к хорошему тону с малолетства:-)Это да. Бывает даже так... Вопрос - а оно надо, если программно всё решается великолепно.
А RC цепочка в динамическом сканировании например не подходит, да и лишние элементы на плате, лишние пайки, деньги...


Подскажите как программно это решить?
Genadi Zawidowski
Вот в этом архиве есть файл keyboard.c - в нём программное подавление дддребезга. А в файле hardware.c (hardware_ged_pressed_key()) - два варианта опроса клавиатуры - или кнопки, замыкающие вход процессора на массу или набор до четырёх кнопок, через резисторную цепочку подключенных ко входу АЦП на процессоре (до четырёх кнопок на один вход АЦП). Схемы резисторной цепочки в файле doc\keyboard_matrix.pdf

http://electronix.ru/forum/index.php?act=a...st&id=37570
ssvd
Цитата(Genadi Zawidowski @ Oct 31 2009, 15:03) *
Вот в этом архиве есть файл keyboard.c - в нём программное подавление дддребезга. А в файле hardware.c (hardware_ged_pressed_key()) - два варианта опроса клавиатуры - или кнопки, замыкающие вход процессора на массу или набор до четырёх кнопок, через резисторную цепочку подключенных ко входу АЦП на процессоре (до четырёх кнопок на один вход АЦП). Схемы резисторной цепочки в файле doc\keyboard_matrix.pdf

http://electronix.ru/forum/index.php?act=a...st&id=37570


спасибо конечно, но ничего в этих текстах не понял (((
demiurg_spb
Цитата(ssvd @ Oct 31 2009, 12:12) *
Подскажите как программно это решить?
Вот Вам ещё три варианта:
CODE
#define MAX_CHECKS 10 // # checks before a switch is
debounced
uint8_t Debounced_State; // Debounced state of the switches
uint8_t State[MAX_CHECKS]; // Array that maintains bounce status
uint8_t Index; // Pointer into State
// Service routine called by a timer interrupt
void DebounceSwitch3()
{
uint8_t i,j;
State[Index]=RawKeyPressed();
++Index;
j=0xff;
for(i=0; i<MAX_CHECKS-1;i++) j=j & State[i];
Debounced_State= j;
if(Index>=MAX_CHECKS) Index=0;
}

//=================================================================
bool_t DebounceSwitch2()
{
static uint16_t State = 0; // Current debounce status
State=(State<<1) | !RawKeyPressed() | 0xe000;
if(State==0xf000) return TRUE;
return FALSE;
}

//=================================================================
#define CHECK_MSEC 5 // Read hardware every 5 msec
#define PRESS_MSEC 10 // Stable time before registering pressed
#define RELEASE_MSEC 100 // Stable time before registering released
// This function reads the key state from the hardware.
extern bool_t RawKeyPressed();
// This holds the debounced state of the key.
bool_t DebouncedKeyPress = false;
// Service routine called every CHECK_MSEC to
// debounce both edges
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed)
{
static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
bool_t RawState;
*Key_changed = false;
*Key_pressed = DebouncedKeyPress;
RawState = RawKeyPressed();
if (RawState == DebouncedKeyPress)
{
// Set the timer which allows a change from current state.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
}
else
{
// Key has changed - wait for new state to become stable.
if (--Count == 0)
{
// Timer expired - accept the change.
DebouncedKeyPress = RawState;
*Key_changed=true;
*Key_pressed=DebouncedKeyPress;
// And reset the timer.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
}
}
}
P.S. Чтобы понять как оно работает много ума не надо.
ssvd
Цитата(demiurg_spb @ Oct 31 2009, 17:36) *
Вот Вам ещё три варианта:


как я уже сказал, что С только начал изучать...
можете построчно описать какой нибудь способ?
demiurg_spb
Цитата(ssvd @ Oct 31 2009, 18:43) *
как я уже сказал, что С только начал изучать...
можете построчно описать какой нибудь способ?
Все когда-то начинали. Читайте книги по си.
Как для первоклассника:

Функция DebounceSwitch2 не получает никаких аргументов и возвращает беззнаковый байт результата 1-истина 0-ложь
Вызывать эту функцию надо с интервалом 5-10мс.
Код
uint8_t DebounceSwitch2(void)
{
// 1. Объявляется локальная статическая переменная и единожды инициализируется нулём при включении контроллера.

static uint16_t State = 0;                                        

// 2. State сдвигается влево на один бит (было 0b 0000 0000 0000 0011 станет 0b 0000 0000 0000 0110)
// 3. далее результат, возвращаемый функцией RawKeyPressed() логически инвертируем (был 0 стал 1 и наоборот)
// 4. далее делаем побитовое ИЛИ результата пункта 2 и пункта 3
// 5. далее делаем побитовое ИЛИ результата пункта 4 с константой 0xe000 = 0b 1110 0000 0000 0000
// 6. присваиваем результат пункта 5 переменной State

State=(State<<1) | !RawKeyPressed() | 0xe000;

// 7. сравниваем State с константой 0xf000 =  = 0b 1111 0000 0000 0000 и ели равны возвращаем 1 если иначе 0

return (State==0xf000);
}
побитовое ИЛИ работает так:
a=0b00000001
b=0b00000010
c=a|b; // c станет равно 0b00000011

RawKeyPressed() возвращает нефильтрованное состояние логического входа (кнопка нажата = 0).
и как только кнопка зажата средний член выражения (State<<1) | !RawKeyPressed() | 0xe000
превращается в 1. Получаем (State<<1) | 1 | 0xe000
CODE
Переменная State начинает меняться:
State = 0xe001
State = 0xe003
State = 0xe007
State = 0xe00f
State = 0xe01f
State = 0xe03f
State = 0xe07f
State = 0xe0ff
State = 0xe1ff
State = 0xe3ff
State = 0xe7ff
State = 0xefff
State = 0xffff
State = 0xffff
State = 0xffff
State = 0xffff

Как только кнопку отпустили: (State<<1) | 0 | 0xe000
State = 0xfffe
State = 0xfffc
State = 0xfff8
State = 0xfff0
State = 0xffe0
State = 0xffc0
State = 0xff80
State = 0xff00
State = 0xfe00
State = 0xfc00
State = 0xf800
State = 0xf000 << бинго
State = 0xe000
State = 0xe000
State = 0xe000
State = 0xe000
Такой вот вариант (я его не использую). Существует масса других...
Надо понимать, что при использовании этого алгоритма необходимо буферировать (очепятка была)smile.gif результат подавления дребезга в некоторой переменной...
Genadi Zawidowski
Цитата(ssvd @ Oct 31 2009, 15:20) *
спасибо конечно, но ничего в этих текстах не понял (((


там, вроде, комментарии в файле keyboard.c на русском языке были, когд я писал.

Функция hardware_ged_pressed_key() из файла hardware.c возвращает прзнак того, нажата ли какая-либо из кнопок и, собственно, номер (код) кнопки. Никаких ожиданий в этой функкции нет, так как она вызывается из обработчика таймерного прерывания около ста раз в секунду. Там, где она вызывается (ищется любым текстовым редактором) в файле keyboard.c - учитывается текущее состояние клавиатуры и давится дребезг (а так же определяется состойние "зажатой" кнопки - для отработки автоповтора (две скорости) или возврата признака "длинного" нажатия в вызывающую программу через функцию
Код
/* получение скан-кода клавиши или 0 в случае отсутствия.
* если клавиша удержана, возвращается скан-код с добавленным битом 0x80
*/
uint_least8_t kbd_scan(uint_least8_t * key, uint_least8_t * repeat)
{
...
}
Vetal-Soft
Сделай так
Код

while(PINA.0){ }; //бесконечный цекл, ждем нажатие кнопки старт!!!
delay_ms(100);
while(!PINA.0){ }; //бесконечный цекл, ждем отпускания кнопки старт!!!
ssvd
вот что написал, проверьте пожалуйста.
вызывается для проверки каждой нажатой кнопки if (KeyState()==0x00){}
проверка делается полностью на порт PINB.

Код
int KeyState(void){
    button_state[1]=PINB;
    for(i=2;i<9;i++){
        button_state[i]=PINB;
        if(button_state[i]==button_state[i-1]){
            anti_drb_counter++;
            delay_ms(20);
        }
        else {
            anti_drb_counter=0;
            break;
        };
    }
    if(anti_drb_counter==9){
        while(1){
            if(button_state[1]!=PINB){
                return(button_state[1]);
                break;
            }
        }
    }
}
Vetal-Soft
бред...

Модератор (rezident). Это сообщение является флудом и нарушает п.2.1в Правил форума. Как-либо аргументируйте Вашу оценку предыдущего сообщения топикстартера.
ssvd
Цитата(Vetal-Soft @ Nov 3 2009, 12:33) *
бред...


я вообще то за помощью сюда пришел, а не выслушивать тупые высказывания... Хочешь отписывать "умными" высказывания или где флудят.
Vetal-Soft
Цитата(ssvd @ Nov 3 2009, 18:51) *
я вообще то за помощью сюда пришел, а не выслушивать тупые высказывания... Хочешь отписывать "умными" высказывания или где флудят.

Прошу прошения, погорячился.

Проверяем:
1. Почему фукция определена как int ? Прочитайте про типы переменных в Си. По логике она должна возвращать char т.е. байт.
2. Зачем городить массив button_state[]?
3. И самое главное. Что будет возвращать эта функция?
если return выполняется только при услвии if(anti_drb_counter==9)
и когда будет выполнятся это условие? отвечу )) если не нажата ни одна кнопка то KeyState() равно 0xff (при условии что выводы родтянуты к VCC) ... или если нажата кнопка и в момент вызова этой функции нет дребезгаконтактов. Во всех другиг случаях она будет взвращять НОЛЬ!
ЗЫ .... я, если честно совершенно не понимаю, чего хотел человек от этого куска кода, здесь даже знания си ни причем, просто полное не понимание происходяшего ....
XVR
Цитата(Vetal-Soft @ Nov 3 2009, 11:33) *
бред...
Ну переборщил человек немного с кодом, бывает rolleyes.gif
Все должно быть проще -

Код
int KeyState(void)
{
int i,pinb_state = PINB;

for(i=0;i<10;++i)
  {
   int new_pinb_state;
   delay_ms(20);
   new_pinb_state = PINB;
   if (new_pinb_state==pinb_state) return pinb_state;
   pinb_state=new_pinb_state;
  }
return -1;
}
ssvd
Цитата(XVR @ Nov 5 2009, 11:36) *
Ну переборщил человек немного с кодом, бывает rolleyes.gif
Все должно быть проще -



Спасибо большое!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.