Обработка нажатия кнопки в AVR...

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

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

в твоей программе есть задержки 150 и 1000мкс. можно настроить таймер на сработку 1 раз в 50мкс, а внутри прерывания вставить такое

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

х++:  if(x==  )  x=0;
switch (x)
{
case __:  тут зажигаешь первый режим светофора
break;
.
.              тут по очереди зажигаешь остальные режимы светофора
.
.
case __:  тут зажигаешь последний режим светофора
break;
}
конкретные, нужные тебе значения х - посчитай сам. переменная х должна быть либо глобальной. или локальной но static.

зы. наверное, можно сделать и по другому......
KIT
Реклама
Аватара пользователя
Upgrader
Друг Кота
Сообщения: 26671
Зарегистрирован: Пт май 18, 2007 22:56:58

Re: Обработка нажатия кнопки в AVR...

Сообщение Upgrader »

Подскажите, что я делаю не так?
Вот счетчик нажатий кнопки:
У меня такая задача: задержки как можно меньше (должно успевать считать быстро), но не использовать прерываний.

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

  if (PIND.3==1) {
  delay_ms(10);
    if (PIND.3==1) {
     while(PIND.3==1) {}; // ожидание отпускания кнопки
     sw2=sw2+1;
     delay_ms(15);
    }
  }
В Proteus работает правильно, а в железе реально: если кнопку держать - считает бесконечное количество раз (пока держится кнопка). Почему так, из-за дребезга?

Вместо кнопки реально будет фотодиод оптического датчика, подключенный вот таким образом: http://easyelectronics.ru/img/starters/ ... detect.GIF
Но изменение его яркости будет достаточно резкое, по этому сильного "дребезга" в этом случае надеюсь не будет.
Не променяю медь на ржавую несгорайку!
Реклама
leowka
Открыл глаза
Сообщения: 42
Зарегистрирован: Ср мар 24, 2010 08:08:20
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение leowka »

Внешний резистор не нужен, используйте внутренний. Соответственно вам считать нужно не высокий уровень и низкий
if (PIND.3==0)
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Программу светофора я запустил, таймер тикает раз в секунду. Но вот я нажал кнопку, цикл остановился, а таймер дальше считает. Получается, что перед повторным запуском цикла (нажатии другой кнопки) таймер будет считать не с нуля а с некоторого значения. Вот мне и нужно перезапустить таймер, чтобы счет начался сначала.

P.S.

Может я что-то не правильно понял в работе таймера, поправьте если что... :)
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Upgrader
Друг Кота
Сообщения: 26671
Зарегистрирован: Пт май 18, 2007 22:56:58

Re: Обработка нажатия кнопки в AVR...

Сообщение Upgrader »

leowka писал(а):Внешний резистор не нужен, используйте внутренний. Соответственно вам считать нужно не высокий уровень и низкий if (PIND.3==0)
Да мне как раз высокий надо... Так уже схема спаяна.
А это имеет какое-то значение?
Не променяю медь на ржавую несгорайку!
Реклама
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

КАШАК Все правильно понял.
А из того что я писал выше чтото понял? там описано что тебе нужно. в твоем случаи обнулять ничего не нужно. таймер считает сам по себе, и когда отсчитывает нужный кусок времени, срабатывает прерывание, в обработчике которого ты зажигаешь нужные лампочки. а таймер в это время, сам обнуляется, и начинает считать с нуля. И когда снова отсчитывает заданный интервал, снова происходит прерывание, в котором ты загигаешь уже другие лампочки, а таймер обнуляется и тикает дальше. И снова все повторяется по кругку. Единственное что тебе нужно сделать чтоб таймер сам обнулялся, это настроить его в режим СТС. Если ты используешь прерывание по переполнению, то СТС ненужен.
KIT
Реклама
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Спасибо. Будут вопросы, напишу :))
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Переписал программу с использование таймера, вот что получилось:

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

int a, b, per=0;

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
a++;                         // Увеличиваем а на 1 при каждом прерывании
}                             

void main(void)
{
PORTA=0x00; DDRA=0x07;

PORTB=0x00; DDRB=0x00;

PORTC=0x00; DDRC=0x07;

PORTD=0x00; DDRD=0x07;

TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Используем таймер 1, т.к таймера 0 не хватает, коэффициет больше 256
TCCR1A=0x00;                 //
TCCR1B=0x0C;                 // Режим СТС, делитель 256
TCNT1H=0x00;                 //
TCNT1L=0x00;                 //
ICR1H=0x00;                  //
ICR1L=0x00;                  //
OCR1AH=0x7A;                 // Ждем пока наберется 31250
OCR1AL=0x12;                 //
OCR1BH=0x00;                 //
OCR1BL=0x00;                 //

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
MCUCSR=0x00;

TIMSK=0x10;

ACSR=0x80;
SFIOR=0x00;

#asm("sei")                    // Разрешаем прерывания

while (1)
      {
      
      if (PINA.3==1){          // Включаем программу
      delay_ms(100);           // Антидребезг
      TCNT1H=0;                //
      TCNT1L=0;                // Обнуляем таймер
      a=0;                     // Обнуляем комбинацию включенных светодиодов
      per=1;                   //
      }
      
      if (PINA.4==1){          // Выключаем программу
      delay_ms(100);           // Антидребезг
      PORTA=0b00000000;        //
      PORTD=0b00000000;        // Гасим все светодиоды
      PORTC=0b00000000;        //
      per=0;                   //
      }
      
if (per==1){                   // Проверяем, можно-ли запуститься
            
      if (a==0){               // (0 секунда) 
      PORTA=0b00000100;        // Зеленый
      PORTD=0b00000100;        // Зеленый
      PORTC=0b00000001;        // Красный
      }
      
      if (a==5){               // Ждем 5 секунд (5 секунда)
                     
      for(b=0; b<=4; b++){     // Мигаем зеленым
      delay_ms(500);           //
      PORTA=0b00000100;        // Зеленый вкл.
      PORTD=0b00000100;        // Зеленый вкл.
      delay_ms(500);           //
      PORTA=0;                 // Зеленый выкл.
      PORTD=0;                 // Зеленый выкл.
      }
       }
      
      if (a==10 || a==25){     // Ждем 5 секунд (10 секунда, 25 секунда)
      PORTA=0b00000010;        // Желтый
      PORTD=0b00000010;        // Желтый
      PORTC=0b00000010;        // Желтый
      }
      
      if (a==15){              // Ждем 5 секунд (15 секунда)
      PORTA=0b00000001;        // Красный
      PORTD=0b00000001;        // Красный
      PORTC=0b00000100;        // Зеленый
      }
      
      if (a==20){              // Ждем 5 секунд (20 секунда)
      for(b=0; b<=4; b++){     // Мигаем зеленым 5 секунд
      delay_ms(500);           //
      PORTC=0b00000100;        // Зеленый вкл
      delay_ms(500);           //
      PORTC=0;                 // Зеленый выкл.
      }
       }
      
      if (a>=30){              // Ждем 5 секунд (30 секунда)
      a=0;                     // Обнуляем комбинацию включенных светодиодов
      }
       }
        }  
};
Как её еще можно изменить или укоротить?

P.S.

Написал небольшую програмку для расчета времени задержки таймера. Кому интересно, качайте AVR_Калькулятор :) (обменник бесплатный, никакого времени ожидания, кодов и т.п.)
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

Молодец :beer: если раньше программировать не пробовал, то очень не плохо за три дня разобрался. я буксовал на этом этапе месяц :oops:
По проге я бы сделал так.
во первых повесил бы все лампочки на один порт, на 3 младших разряда.
таймер настроил бы на прерывание на самый маленький интервал, и кучу if заменил бы на один switch. переменную а обнулять можно тоже в этом же switch

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

switch  (a)
        {
        case 0:                           PORTA=0b00000xxx;  break;
        case __:                          PORTA=0b00000xxx;  break;
        case __:                          PORTA=0b00000xxx;  break;
        case (__ || __):                  PORTA=0b00000xxx;  break;
        case (__ || __ || __ || __.....): PORTA=0b00000xxx;  break;
        case __:  а=0;
        }
С кнопками тоже можно чтото оптимизировать. но у тебя и у самого не плохо получается :)))
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

До этого контроллеры вообще не программировал, писал только на С++ :)) Вот и программку по быстрому сделал, чтобы с калькулятором не сидеть :))
Ваши замечания обязательно учту. А на лампочки на разные порты повесил, чтобы в Proteus удобнее собирать было :). Теперь хотелось бы научиться работать с ШИМ и АЦП...
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

Ну раз Си знаешь, это хорошо. Тогда многое из того что я говорю для тебя должно быть прописной истиной.
Я вообще понятия не имел о языке, и контроллерах. исходник что на Си, что на асме был для меня набором букв и цифр. :shock:
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Вот, переписал программу. Потом на счет кнопок подумаю :) . Со swith-case намного удобнее работать

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

while (1)
      {
      if (PINA.3==1){          // Включаем программу
      delay_ms(100);           // Антидребезг
      TCNT1H=0;                //
      TCNT1L=0;                // Обнуляем таймер
      a=0;                     // Обнуляем комбинацию включенных светодиодов
      per=1;                   //
      }
      
      if (PINA.4==1){          // Выключаем программу
      delay_ms(100);           // Антидребезг
      PORTA=0b00000000;        //
      PORTD=0b00000000;        // Гасим все светодиоды
      PORTC=0b00000000;        //
      per=0;                   //
      }
      if(per==1){
      switch  (a)
        {
        case 0:                           PORTA=0b00000100; PORTC=0b00000001; PORTD=0b00000100;  break;
        case 5:           
                for(b=0; b<=4; b++){     // Мигаем зеленым
                delay_ms(500);           //
                PORTA=0b00000100;        // Зеленый вкл.
                PORTD=0b00000100;        // Зеленый вкл.
                delay_ms(500);           //
                PORTA=0;                 // Зеленый выкл.
                PORTD=0;                 // Зеленый выкл.
                }                  break;
        case 10:        
        case 25:                          PORTA=0b00000010; PORTC=0b00000010; PORTD=0b00000010;  break;
        case 15:                          PORTA=0b00000001; PORTC=0b00000100; PORTD=0b00000001;  break;
        case 20: 
                for(b=0; b<=4; b++){     // Мигаем зеленым
                delay_ms(500);           //
                PORTC=0b00000100;        // Зеленый вкл.
                delay_ms(500);           //
                PORTC=0;                 // Зеленый выкл.
                }                  break;
        case 30:  a=0;
        }
         }
          }  
};
Где можно про ШИМ и АЦП почитать?
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

увлекся твоим светофором, как своим :)))
работа шим и ацр расписана в книге в подписи. хоть эта книга является справочником, а не обучалкой, но прочтя её сразу понимаешь что как работает, в каком регистре какой бит установить, чтоб контроллер начал делать то что тебе нужно.
Еще на сайте у дихалта посмотри. там вообще все на пальцах и с картинками. единственно что он делает на примере ассемблера, но суть понять можно.

возвращаясь к твоей программе.
тебе нужно полностью избавится от delay. сделать это очень просто, я писал выше как. Сейчас у тебя получается, что если нажать кнопку когда контроллер отрабатывает delay то она не сработает.
Опиши с указанием времени полный цикл работы светофора, и я набросаю прогу вообще без delay , if. , for. будет один единственный switch с 4-5 case.
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Цикл работы такой:

Включили питание, ничего не происходит. Жмем кнопку, включается программа:

1) 0-секунда: Включились 2 зелёных и один красный;

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

PORTA=0b00000100; PORTC=0b00000001; PORTD=0b00000100;
2) 5-секунда: Зелёные мигают, красный горит;
3) 10-секунда: Красный и зелёный погасли, горят 3 жёлтых;

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

PORTA=0b00000010; PORTC=0b00000010; PORTD=0b00000010;
4) 15-секудна: Жёлтые погасли, загорелись 2 красных и один зелёный.

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

PORTA=0b00000001; PORTC=0b00000100; PORTD=0b00000001;
5) 20-секунда: Зелёный мигает, 2 красных горят.
6) 25-секунда: Красный и зелёный погасли, горят 3 жёлтых;

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

PORTA=0b00000010; PORTC=0b00000010; PORTD=0b00000010;
7) 30-секунда: Возврат цикла на 0-й шаг. Есть ещё кнопка выключения программы. :)
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

переменная а должна увеличиваться каждые 0,5 сек

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

switch  (a)
        {
        case 0:                      2 зелёных и один красный вкл;                  break;
        case (10||12||14||16||18):   Зелёные вкл, красный вкл;                      break;
        case (11||13||15||17||19):   Зелёные выкл;                                  break;
        case 20:                     Красный и зелёный выкл, 3 жёлтых вкл;          break;
        case 30:                     Жёлтые выкл,  2 красных и один зелёный вкл.    break;
        case (40||42||44||46||48):   Зелёный , 2 красных вкл.                       break;
        case (41||43||45||47||49):   Зелёный выкл                                   break;
        case 50:                     Красный и зелёный выкл, 3 жёлтых вкл;          break;
        case 60:  а=0;                                                              break;
        }
если лампочки повесишь на один порт, то код стает минимальным.
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

CodeVision ругается на

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

case (40||42||44||46||48):
Пишет Error: D:\Projects_AVR\Svetofor_2\main.c(92): constant integral expression required
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

хм. действительно. я думал кодевижн такое проглотит. ну тогда придется делать кучу case. :dont_know:
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Перписал без for, все лампочки на порт А повесил.

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

      switch  (a)
        {                           //    PORTA=0b0ygrgrgr
        case 0:                           PORTA=0b00101001; break;
        case 10: case 14: case 18:        PORTA=0b00000001; break;
        case 12: case 16:                 PORTA=0b00101001; break;
        case 20:                          PORTA=0b01000000; break;
        case 30:                          PORTA=0b00100101; break;
        case 40: case 44: case 48:        PORTA=0b00000101; break;
        case 42: case 46:                 PORTA=0b00100100; break;
        case 50:                          PORTA=0b01000000; break;
        case 60:  a=0;
        }
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение O-LED »

Вот как можно оптимизировать работу кнопок.

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

if (PINA.3==1)  TCNT1H=0; TCNT1L=0;  a=0;  #asm("sei")
if (PINA.4==1)  #asm("cli")  
антидребезг в твоём случаи ненужен.

кодевижен схавал это???

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

 case 10: case 14: case 18:
надо запомнить на будущее.
KIT
Аватара пользователя
КАШАК
Это не хвост, это антенна
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение КАШАК »

Спасибо. :)

Пытаюсь разобраться с ШИМ, пока как-то не очень. Можете дать несколько простых примеров с использованием ШИМ?
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»