Перейти к содержанию
    

Мгновенно реагировать на нажатие кнопки. Attiny 2313

Учусь программировать под Attiny 2313, написал такую программку:

Если нажать на кнопку, то запускается цикл мигания 6 светодиодов, если в конце мигания шестого светодиода нажать кнопку, то мигание выключится.

Вот код для gcc:

unsigned char LIGHT = 0;
while (1) {
  // Если свет не горит и нажата кнопку
  if (LIGHT == 0 && bit_is_clear(PIND,0)) {
    // Включить свет
    while (LIGHT == 0) {
        PORTB = 0b11111110;
        _delay_ms(200);
        PORTB = 0b11111101;
        _delay_ms(200);
        PORTB = 0b11111011;
        _delay_ms(200);
        PORTB = 0b11110111;
        _delay_ms(200);
        PORTB = 0b11101111;
        _delay_ms(200);
        PORTB = 0b11011111;
        _delay_ms(200);
        // Если нажата кнопка, то выключаем свет
        if (bit_is_clear(PIND,0)) {
            PORTB = 0b11111111;
            _delay_ms(200);
            LIGHT = 1;
        }
    }
  }
  // Если свет выключен и нажата кнопка, то включаем свет
  if (LIGHT == 1 && bit_is_clear(PIND,0)) {
    LIGHT = 0;
  }
}

Работает как я и планировал, но есть одна недоработка.

 

Как сделать так, чтобы нажав на кнопку в ЛЮБОЙ момент времени светодиоды остановились мигать (а не только в конце цикла мигания)? подскажите куда копать? если есть простой пример на Си буду рад его изучить.

Изменено пользователем aivs

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как сделать так, чтобы нажав на кнопку в ЛЮБОЙ момент времени светодиоды остановились мигать (а не только в конце цикла мигания)? подскажите куда копать? если есть простой пример на Си буду рад его изучить.

 

Вам надо фиксацию нажатия кнопки выполнять в прерывании или периодически по таймеру обязательно с алгоритмом антидребезга. И управлять длительностью моргания формируя задержки с помощью таймера.

 

Для простоты замените delay_ms(200) на некую процедуру которая будет опрашивать флаг таймаута и состояние нажатия кнопки. Если обнаружено нажатие кнопки, то гасите светодиоды и переходите в исходное состояние. Если обнаружен флаг таймаута, то выполняете цикл моргания дальше. Флаг таймаута устанавливайте в прерывании от таймера счётчика.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как сделать так, чтобы нажав на кнопку в ЛЮБОЙ момент времени светодиоды остановились мигать (а не только в конце цикла мигания)? подскажите куда копать? если есть простой пример на Си буду рад его изучить.

По-научному это называется "машина состояний" ("state machine")", или "цифровой автомат". Например:

http://mcu.ucoz.ru/publ/programmirovanie/r...llerov/11-1-0-4

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-научному это называется "машина состояний" ("state machine")", или "цифровой автомат".

 

+1

Сам поначалу описал вариант с применением автомата состояний, но потом для простоты предложил заменить процедуру.

Опишу ещё раз.

Вводите переменную состояние устройства state которая будет принимать значения 0 - ожидание нажатия, 1 - исполнение цикла.

button - флаг нажатия кнопки.

timer - таймер для формирования требуемой задержки

led_cnt - счётчик морганий

 

switch(state)
{
case 0: 
if(button)
{
//переход на моргание по нажатию кнопки
button = 0;
state = 1;
ledOn();
timer = _200mS;
led_cnt = 12;
}
break;

case 1:
if(button)
{
//переход в исходное состояние по нажатию кнопки
button = 0;
state = 0;
ledOff();
timer = 0;
}

if(timer == 0)
{

if(led_cnt>0)
{
//инвертируем состояние светодиодов
led_cnt--;
ledInvert();
timer = _200mS;
}
else
{
//переход в исходное состояние т.к. отработали цикл
button = 0;
state = 0;
ledOff();
timer = 0;
}

}
break;


default: 
//переход в исходное из неизвестного состояния автомата (это на всякий случай)
button = 0;
state = 0;
ledOff();
timer = 0;
break;
}

 

Запускаете такой автомат в вечном цикле. А в прерывании от таймера сканируете кнопку и выполняете обратный отсчёт переменной timer с самоостановом

if(timer) timer--;

 

Если ввести много состояний и определить условия перехода из одного в другой, то можете реализовывать различные световые эффекты или обеспечить некоторую световую индикацию. Я подобный образом формирую индикацию режимов работы своих устройств где в зависимости от состояния устройства(устройство спит, подключено к серверу, ищет сеть GSM и т.д.) светодиод зажигается/гасится на абсолютно разные интервалы времени.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Могу предложить рабочий кусок кода с простеньким планировщиком задач и службой времени. Правда немного поправить наверно придется...это всё для меги8 писалось.

Антидребезг также присутсвтует.

 

Основной цикл будет выглядеть как-то так:

void some_task()
{
//делаем что-то каждые 200ms
}

void some_task2()
{
//делаем что-то каждые 50ms
}

int main(void)
{
    uint8_t last_keys, keys;
    timer0_init();
    kbd_init();
    //клавиатура опрашивается каждые 20 миллисекунд
    shed_add_task(kbd_upd_rawstate, 20);
        //делаем что-то каждые 200ms
    shed_add_task(some_task, 200);
        //делаем что-то каждые 50ms
    shed_add_task(some_task2, 50);
    last_keys = 0;
    while(1)
    {       
        shed_upd_state();
        shed_run_tasks();            
        
        keys = kbd_get_keys();
        if ( (last_keys != keys) )
        {
            if ( (keys & 0x2) )
            {        
            //делаем что-то по кнопке 2
            }
            
            if ( (keys & 0x1) )
            {
            //делаем что-то по кнопке 1
            }    
            last_keys = keys;
        }
    }            
}

Выкладывать? Или сами птренеруетесь?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

примитивные решения. надо многозадачную ОС для решения этой задачи. а чтобы было проще - бросить ущербную 8-битную архитектуру, взять ARM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

римитивные решения. надо многозадачную ОС для решения этой задачи. а чтобы было проще - бросить ущербную 8-битную архитектуру, взять ARM.
Согласен, но для начала и AVR покатит))

Electronix_help.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

примитивные решения. надо многозадачную ОС для решения этой задачи. а чтобы было проще - бросить ущербную 8-битную архитектуру, взять ARM.

Да. Каждой детской песочнице - по мощному экскаватору. Самое то ...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

примитивные решения. надо многозадачную ОС для решения этой задачи. а чтобы было проще - бросить ущербную 8-битную архитектуру, взять ARM.

ARM для такой задачи ТС слабоват. Вот со скрипом , может быть потянет. Но лучше поставить 2 и сразу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще нет, надо отечественный четырехядерник ставить, в интеле закладки же могут быть!

Можно кстати одним ядром клаву опрашивать, а вторым лампочки зажигать ) профит))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще нет, надо отечественный четырехядерник ставить, в интеле закладки же могут быть!

Советские микросхемы - самые большие микросхемы в мире! (с) :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Советские микросхемы - самые большие микросхемы в мире!...

 

это потому, что наши закладки студенты пишут на си бимоле :)))

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще нет, надо отечественный четырехядерник ставить, в интеле закладки же могут быть!

Можно кстати одним ядром клаву опрашивать, а вторым лампочки зажигать ) профит))

Вы забыли упомянуть, что это всё надо делать только под Линуксом, потому что микро-РТОС для таких задач совершенно не подходят, т.к. для них нет готовых коммуникационных стеков и драйверов! )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну это само собой! RT патч только не забыть))))

 

P.S. ой чую влетит нам щас за оффтоп )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...