кнопка и прерывания

Обсуждаем контроллеры компании Atmel.
Ответить
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

подскажите пожалуста не пойму как опрашивать кнопку через прерывания

Код: Выделить всё

#include <mega8.h>
#include <delay.h>

void main(void)
{
 PORTD=0x02;
 DDRD=0x01; 

  label0:

 while(PIND.1==1)
 { 
  PORTD.0=0;
 }


   while (1)
   { 
  
  PORTD.0=1;
  delay_ms(10);
  while(PIND.1==0)
  {goto label0;}

}}
суть в том чтобы при нажатии на кнопку загорелся светодиод,при повторном нажатии он должен потухнуть,токо этот код плохо работает когда в цикле много всего,подскажите как его можно реализовать подругому - разными способами,на первом месте хотелось бы рассмотреть прерывания- исключая внешнее прерывания
Последний раз редактировалось sirha Вт окт 21, 2014 20:03:49, всего редактировалось 1 раз.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

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

Просто - опрос кнопок правильнее делать в регулярном прерывании по таймеру\счетчику, а не по внешнему прерыванию...

Если только нужно будить устройство из сна, то это другое дело...
Последний раз редактировалось shads Вт окт 21, 2014 20:23:23, всего редактировалось 1 раз.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а):Не темни... объясни сразу что за причина, по которой нужно использовать именно прерывание...
просто хочу рассмотреть все способы кроме внешних прерываний
shads писал(а):Просто - опрос кнопок правильнее делать в регулярном прерывании по таймеру\счетчику
приведи пример кодом если несложно
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а):Где то в этих ветках, кроме прочих есть мои примеры...

http://radiokot.ru/forum/viewtopic.php?f=57&t=101520
напиши тут пожалуйста,некоторые ветки не для codivision,хотелось бы на этом компиляторе
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

sirha писал(а):
shads писал(а):Где то в этих ветках, кроме прочих есть мои примеры...

http://radiokot.ru/forum/viewtopic.php?f=57&t=101520
напиши тут пожалуйста,некоторые ветки не для codivision,хотелось бы на этом компиляторе
Блин... я им не пользуюсь, и у меня все для AVRSTUDIO...
Ну ща попробую установить CV и поправить свою либу...
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а): Ну ща попробую установить CV и поправить свою либу...
буду ждать,спасибо :)
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

:facepalm: еле разобрался в ентом CV... срочно переходите на нормальный компилятор - AVRSTUDIO4+GCC 8) .....

В общем там примерчик управления 8-мю светиками с помощью 4-х кнопок... короткие нажатия - управляют младшими 4-мя светиками, длинные нажатия - управляют старшими 4-мя светиками...

Ито я не понял как там библиотеку создавать, все свалил в главный файл... так что - наверное сами разберетесь, как по отдельным файлам распихать...
Вложения
mega8_button_example1.7z
(32.89 КБ) 146 скачиваний
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а)::facepalm:
В общем там примерчик управления 8-мю светиками с помощью 4-х кнопок... короткие нажатия - управляют младшими 4-мя светиками, длинные нажатия - управляют старшими 4-мя светиками...
громоздко(,буду разбираться,а еше как -нибудь можно пороще
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Ну ща сделаю для одной кнопки, чтобы проще было...
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а):Ну ща сделаю для одной кнопки...
ПАСИБ я сам не специалист еще в программировании поэтому разобраться сразу не смогу,знаю не мало,в прерываниях слаб еще
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Вот для одной кнопки...
Сложность кажущаяся только в прерывании... но это нужно для более менее грамотной обработки нажатий... Тут по другому никак...
Вложения
1 buttons.7z
(32.42 КБ) 117 скачиваний
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а):Вот для одной кнопки...
Сложность кажущаяся только в прерывании....
буду разбираться
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Еще чуть упростил обработку одной кнопки...
Теперь все выглядит как то так....
Спойлер

Код: Выделить всё

//анализ состояния кнопки
//если на линии - лог 1, то кнопка не нажата, когда кнопка нажата, то соотв на линии - лог 0.
//вот тут мы и вылавливаем лог 0 на линии, т.е. ждем когда результат сравнения будет противоположный значению TRUE (отрицание !)
if (! (BTN_PIN & BTN_LINE)){                                  
    
    //итак кнопка нажата, и мы инкрементируем счетчик защелки LockCoun, для отсеивания дребезга
    //почему (BTN_LOCK_TIME/10), да потому что частота прерываний 100 Гц (т.е. 100 прерываний в секунду) 
    //а задаем мы время защелки в милисекундах (т.е. 1000 отсчетов в секунду)
    //вот вам и разница в 10 раз... поэтому константу задержки и делим на 10...
    if (LockCoun < (BTN_LOCK_TIME/10)){        
        LockCoun++;
        
        //пока защелка не дощитала до значения (BTN_LOCK_TIME/10) - просто выскакиваем
        return;                                
    }

    //ага... счетчик защелки дотикал, значит можно предварительно отметить, что факт фиксации нажатия свершился 
    BtnLockBit =1;
    
    //дальше нужно посчитать время удержания кнопки, для того чтобы определить короткое это нажатие или длинное...
    if (LongCoun >= (BTN_LONG_TIME/10))      
    
        //сюда попадем, если счетчик длительности нажатия уже равен константе длинного нажатия
        //а это означает что он еще раньше дотикал до этого состояния,
        //и следовательно, все что нужно в связи с этим уже было сделано, соответственно - просто выходим...
        return;     

    //раз мы сюда проскочили, то время удержания пока что меньше чем нужно для фиксации длинного нажатия
    //поэтому продолжаем инкремент переменной времени удержания
    if (++LongCoun >= (BTN_LONG_TIME/10))   
    
        //ух ты... счетчик только что досчитал до значения времени длинного нажатия... 
        //это и есть момент фиксации длинного нажатия, устанавливаем бит длинного нажатия 
        BtnFlags |= BTN_LONG;         
        
        //ну и дальше мы уже будем выскакивать на идущей раньше строчке if (++LongCoun >= (BTN_LONG_TIME/10))
        //до тех пор пока кнопка не отпустится...
}
            
else{                              

    //клавиша отжата    
    //если кнопка до этого удерживалась, то нужно опять обработкть счетчик защелки, только в обратном направлении
    if (LockCoun){
    
        //начинаем декремент счетчика защелки, чтобы определить - это точно отжатие, или это просто звон некачественной кнопки
        LockCoun --;
        
        //защелка еще не обнулилась - возврат
        return;                        
    }

    //ага... клавиша точно отпущена, смотрим, была ли она до этого определена как нажатая
    // (! BtnLockBit) то же самое что (BtnLockBit == 0)
    if (! BtnLockBit)    

        //увы... кнопка до этого не была нажата, поэтому выходим
        //это место я назвал "СТАТИЧЕСКИЙ ВОЗВРАТ", т.к. программа именно тут выскакивает в режиме бездействия кнопок
        return;                        

    //так, это интересно... раз мы тут, то кнопка была ранее нажата...
   if (LongCoun < (BTN_LONG_TIME/10))

        //установка бита короткого нажатия
        //ЕСЛИ значение счетчика времени удержания меньше чем время необходимое для длинного удержания, 
        //то значит это было короткое нажатие, соответстенно надо установить флаг короткого нажатия
        //т.е. как вы поняли, установка флага короткого нажатия, происходит в момент отпускания кнопки, при условии
        //что кнопка удерживалась меньше времени необходимого для фиксации длинного удержания
        //ЕСЛИ же значение счетчика было равно времени длинного удержания, то мы обойдем эту строку, 
        //т.к. в таком случае, флаг длинного удержания кнопки, был уже установлен ранее строкой BtnFlags |= BTN_LONG;  
        BtnFlags |= BTN_SHRT;            

    //ну и хвосты подчистить надобно... 
    //отжатие зафиксировано
    BtnLockBit =0;              
    
    //сброс счетчика длительности нажатия
    LongCoun = 0;                     
} 
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

Тут как я понил работает прерывание по совпадению
тоесть когда OCR2=TCNT2 то сработает прерывание
я правильно считаю 100 гц?

OCR2=0x4E;

4e=78 это ведь такты
у Т2 8 бит наскоко я знаю, 255 тактов


вы задаете делитель 1024 на частоте 8 мгц

получаем 1024/8000000 =0,128 мс

100 гц = 10 мс


10мс/0,128 мс = 78 тактов за 10 мс



TCNT2=255-78=177 - НАЧАЛЬНОЕ ЗНАЧЕНИЕ ДЛЯ СЧЕТА


обьясните мне как считает счетчик ведь у вас TCNT2 нигде не написан - тоесть он равен 0????

и как токо досчитает до равенства OCR2 то сработает прерывания ведь так??
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Режим CTC - это когда счетчик считает от нуля до значения в регистре OCR2...
При совпадении происходит сброс счетчика на 0 и происходит прерывание (если включено).
Счетчик при этом устанавливать не нужно... вообще все автоматом происходит...

Считаеш частоту прерываний вроде правильно, но я проще считал...
Исходная частота 8000000, делим на 1024 (делитель) получаем частоту приращения счетчика 8000000/1024=7812 Гц.
Т.е. у нас счетчик инкрементируется с частотой 7812 Гц... ну и раз нам нужно 100Гц, то соответственно получаем регистр сравнения: 7812/100=78... Что и наблюдаем в регистре сравнения... Частота точная не нужна, это не часы в конце концов, так что примерно имеем 100Гц...



ЗЫ
Кстати... если нужна точная привязка к реальному времени, то можно сделать так:
Предделитель установить на 256, регистр OCR2 = (250-1)... получаем прерывание с частотой ровно 125 Гц...
Остается сделать в прерывании программный делитель на 125, и вот вам 1 Гц с часовой точностью..... (если конечно от кварца работаем)
Вымогатель припоя
Аватара пользователя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

Сообщение sirha »

shads писал(а):Режим CTC - это когда счетчик считает от нуля до значения в регистре OCR2...
При совпадении происходит сброс счетчика на 0 и происходит прерывание (если включено).
Счетчик при этом устанавливать не нужно... вообще все автоматом происходит...
а я невнимательно посмотрел на назначения битов wgm21 и 20

думал что режим с точной фазой и это в тупик меня привело,теперь дошло :))
Ответить

Вернуться в «AVR»