Например TDA7294

Форум РадиоКот • Просмотр темы - Опрос кнопок микроконтроллером
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Чт янв 08, 2026 22:58:24

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 509 ]     ... , , , 8, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 10:03:44 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
Получается и так и есть в протеусе, что при нажатии кнопки и не отпускании происходит прерывание по спадающему фронту (т.е. получается теоретически лог.0), порт настроен на вход DDRD=0x00; с подтягивающими резисторами PORTD=0xff; (которые если отключить то прерывание не будет работать) бит PUD в регистре MCUCR отключен, прерывания разрешены и глобально разрешены.
Пишу в обработчике прерываний:
Код:
ISR(INT1_vect)  //MINUS PIND3
{_delay_ms(200);
if (PIND3 == 0)
{s--;}
}

и в протеусе нет реакции на нажатие кнопки, т.е. на входе порта нет лог.0. но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата.
С другой стороны в коде Alex'a прописаны:
Код:
#define ACT_BUTT_LEV    0       // Активный уровень нажатых кнопок

т.е. мне туда прописывать эту тройку, но тогда дальше:
Код:
if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV)) // Если текущее значение - "нажата" и предыдущее - "не нажата"

не будет работать из-за этой тройки, срабатывающей всегда.

Задача стоит такая сделать отслеживание кнопок от таймера:
При нажатии любой кнопки происходит увеличение или уменьшении значения на индикаторе на 1 (это работает, но не на таймере, а на векторах прерываний),
При нажатии и удержании в течении 3сек. происходит запуск обратного отсчета (работает если отслеживать циклом while флаги в регистре EIFR).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 10:33:16 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4599
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Цитата:
но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата
А Вас не смущает, что Вы пин (т.б. 1 бит) сравниваете с числом 3 ? :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 10:55:04 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
Новая концепция: записывать чтобы-там ни было на входе порта в переменную и работать уже с ней:
Только такое условие работает с каждой кнопкой по отдельности, а вместе они почему то конфликтуют.
Код:
int Knopka_Staroe, Knopka_Novoe;
int Knopka_Star2, Knopka_Nov2;


Knopka_Staroe = (PIND&=(1<<3));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
   _delay_ms(80);  // Пауза для подавления дребезга контактов.
   Knopka_Novoe = (PIND&=(1<<3));  //...считываем новое состояние кнопки.

   if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
   {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
      _delay_ms(80);  // Пауза для подавления дребезга контактов.
      s--; 
   }
}
      
// Knopka_Star2 = (PIND&=(1<<2));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
// if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
// {
//    _delay_ms(80);  // Пауза для подавления дребезга контактов.
//    Knopka_Nov2 = (PIND&=(1<<2));  //...считываем новое состояние кнопки.
//
//    if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
//    {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
//       _delay_ms(80);  // Пауза для подавления дребезга контактов.
//       s++;
//    }
// }   


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 11:14:40 
Вымогатель припоя

Карма: 22
Рейтинг сообщений: 114
Зарегистрирован: Пн июн 14, 2010 13:07:29
Сообщений: 630
Откуда: Жуковский
Рейтинг сообщения: 0
Аlex писал(а):
Цитата:
но если прописать if (PIND3 == 3) то прерывание работает, да и это же условие выполняется если кнопка не нажата
А Вас не смущает, что Вы пин (т.б. 1 бит) сравниваете с числом 3 ? :)
:shock: А если учесть, что PIND3 является просто числом 3...
Цитата:
#define PIND3 3


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 12:04:27 
Вымогатель припоя
Аватар пользователя

Карма: 5
Рейтинг сообщений: 74
Зарегистрирован: Пн июн 18, 2012 12:01:04
Сообщений: 650
Откуда: Челябинская область, Копейск
Рейтинг сообщения: 3
Вот что прописано в файле m88def.inc:
Код:
.equ  PIND3      =3
.equ  PIND2      =2

да и вообще если прерывание наступило, зачем тогда в прерывании проверять кнопку, если и так понятно, что она нажата, можно смело выходить из прерывания, и уже в основном цикле проверять это нажатие еще несколько раз на антидребезг, отвыкайте от паузного антидребезга и забудьте слово пауза, есть другое слово - игнор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Чт дек 12, 2013 12:49:36 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4599
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
a_skr писал(а):
:shock: А если учесть, что PIND3 является просто числом 3...
Цитата:
#define PIND3 3
В таком случае, я - балерина :)))
Это как же нужно себя не уважать, чтобы делать такие объявления ? :)))


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 08:19:25 
Друг Кота

Карма: 28
Рейтинг сообщений: 568
Зарегистрирован: Чт май 05, 2011 21:26:34
Сообщений: 4550
Откуда: Украина, Славутич
Рейтинг сообщения: 0
Это определение бита а НЕ ПОРТА, все правильно. PIND3 - константа, которую НАДО подставлять в сравнение вроде PORTD = (1<<PIND3). На этой концепции построено все.
PINB3=PINC3=PIND3=3 ведь все эти биты портов 3-и по счету!!! Разница в имени константы, указывающая на порт всего лишь для удобства.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 10:31:24 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
Тут: http://www.fanatnauki.ru/index.php?opti ... &Itemid=64
пишут, что:
Цитата:
PORTD = 0b10000000; // Подключаем подтягивающий PULL-UP резистор к 7 пину порта D.
DDRD = 0b00000000; // Настроим порт D на ввод информации.
// Важна последовательность! Сперва подключаем PULL-UP резистор,
// и только потом настраиваем порт на ввод, иначе кнопка работать не будет.

даже это не помогло.

Вобщем в связи с новой концепцией посмотрите код вначале цикла while(1), почему конфликтуют обе кнопки, но ведь если по отдельности то работают. Второй блок кнопки закомментирован, прерывания отключены:

Спойлер
Код:
#define F_CPU 1000000UL

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>


#define COUNTDOWN 1

volatile char FLAG = 0;
volatile char s = 6;    //Переменная цифры
volatile char a = 6;
volatile char b = 1;    //Начальный сброс флага
volatile char c = 6;
volatile char j = 6;    //Перескок через ШИМ
// массив знаков на индикатор
char digits[11] = {0b00111111, 0b00000110, 0b00011011, 0b00001111, 0b00100110, 0b00101101, 0b00111101, 0b00000111, 0b00111111, 0b00101111, 0b00101111}; // PORTC 0,1,2,3,4,5,6,7,8,9,x
char digita[11] = {0b00000000, 0b00000000, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000, 0b00000001, 0b00000001, 0b00000001}; // PORTB

/******************************************************************/
#define ACT_BUTT_LEV    0       // Активный уровень нажатых кнопок
#define ACT_BUTT_LEV_2    0
//----------
#define PORT_BUTT_1     PIND    // Порт кнопки №1
#define PIN_BUTT_1      2       // Номер бита порта кнопки №1
#define PORT_BUTT_2     PIND    // Порт кнопки №2
#define PIN_BUTT_2      3       // Номер бита порта кнопки №2
//----------
#define PORT_LED_1      PORTB   // Светики
#define DDR_LED_1       DDRB    //
#define PIN_LED_1       2       //
#define PORT_LED_2      PORTB   //
#define DDR_LED_2       DDRB    //
#define PIN_LED_2       7       //
/******************************************************************/
int Knopka_Staroe, Knopka_Novoe;
int Knopka_Star2, Knopka_Nov2;
/******************************************************************/
typedef struct{
   unsigned cur:   1;      // Текущее состояние
   unsigned prev:  1;      // Предыдущее состояние
   unsigned down:  1;      // Была нажата
   unsigned up:    1;      // Была отжата
}tButt;
volatile tButt  mButt_1 = {0,!ACT_BUTT_LEV,0,0};    // Объявляем структуру mButt_1 для нашей кнопки и иним её.

typedef struct{
   unsigned cur:   1;      // Текущее состояние
   unsigned prev:  1;      // Предыдущее состояние
   unsigned down:  1;      // Была нажата
   unsigned up:    1;      // Была отжата
}tButt2;
volatile tButt2  mButt_2 = {0,!ACT_BUTT_LEV_2,0,0};    // Объявляем структуру mButt_2 для нашей кнопки и иним её.
/******************************************************************/

/******************************************************************/
ISR (TIMER1_OVF_vect) {   s=3;   //interrupt [TIM1_OVF] void timer1_ovf_isr(void){ //TIMER1_OVF_vect_num
   static unsigned char cnt_ms_butt=20;    // Счётчик для формирования периода в 20 мс.
   TCNT1 -= 4000;          // Перезапускаем таймер на 1 мс.
   //----------//
   if(!--cnt_ms_butt){     // Формируем 20-ти миллисек. периоды
   cnt_ms_butt=20;
   mButt_1.cur = (PORT_BUTT_1&(1<<PIN_BUTT_1))!=0;                 // Считываем текущее значение вывода.
   // Дальше работаем с этим битом, т.к. порт может измениться в любой момент.
   if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
   mButt_1.down = 1;                                                   // Устанавливаем флаг down
   if((mButt_1.cur!=ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
   mButt_1.up = 1;                                                     // Устанавливаем флаг up
   mButt_1.prev=mButt_1.cur;                                       // Сохраняем текущее значение. Оно для следующего входа будет предыдущим

   mButt_2.cur = (PORT_BUTT_2&(1<<PIN_BUTT_2))!=0;                         // Считываем текущее значение вывода.
   if((mButt_2.cur==ACT_BUTT_LEV_2) && (mButt_2.prev!=ACT_BUTT_LEV_2))     // Если текущее значение - "нажата" и предыдущее - "не нажата"
   mButt_2.down = 1;                                                   // Устанавливаем флаг down
   if((mButt_2.cur!=ACT_BUTT_LEV_2) && (mButt_2.prev==ACT_BUTT_LEV_2))     // Если текущее значение - "не нажата" и предыдущее - "нажата"
   mButt_2.up = 1;                                                     // Устанавливаем флаг up
   mButt_2.prev=mButt_2.cur;
   }
//----------//
}
/******************************************************************/

ISR(INT1_vect)  //MINUS PIND3
{_delay_ms(200);
if (PIND3 == 0) //(PIND3 <= 3) работает (PIND3 <= 2,95) (PIND3 == 3)
      {s--;}
}

ISR(INT0_vect)  //PLUS PIND2
{_delay_ms(200);
if (PIND2 == 0) //(PIND2 == 2)(PIND2 >= 2,995) работает, а если (PIND2 >= 3) то не работает
      {s++;}
}

void shim_start()
{
   if (j==6)
   {goto jstop;
   }
//   ASSR=0x00;
//   // Установим биты COM1A1-COM1A0:0b10,означает сброс вывода канала A при сравнении Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode), for Fast PWM. page135
//   TCCR1A |= (1 << COM1A1)|(0 << COM1A0)|(0 << WGM11)|(1 << WGM10);
//   // Установим биты WGM13-10:0b0101, согласно таблице это будет режим - Fast PWM, 8-bit, где верхний предел счета задается битом ICR1. page136
//   TCCR1B |= (0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(0 << CS10);
//   // Битами CS12-10:0b100 задаем источник тактового сигнала для таймера МК, clkI/O/256 (From prescaler)=31250Hz. page137
//   TCNT1 = 0x00; // начальная установка счетчика
//   TIMSK1=0x00;
//   ICR1 = 0x20;  // задаем период ШИМ, здесь у нас число 255,
//   // по формуле  fPWM=fclk_I/O/N*(1+ICR1) вычисляем частоту ШИМ, она будет равна 8MHz/256(1+2)=10416Hz
//    // для FR3706 надо 50000Hz, irlm0030 надо 16666Hz<
//    OCR1A = 0x50; // начальный коэффициент заполнения ШИМ 0xC8=200, 0x50=1/3
   jstop:
   j=0;
}

int main(void)
{
      DDRC=0x3f;  //0b00111111 0-ввод 1-вывод
      PORTC=0x00; //
      PORTD=0xff; // 0b11111111 PORTD=0xff;
      DDRD=0x00; //0b00001100 DDRD=0x0C;
      
      DDRB=0xFF; //0b11000111 PB1(OC1A)-ШИМ DDRB=0xC7;
      PORTB=0x00; //PORTB=0x00;
   EICRA  =  (1<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00);   // настройка срабатывания прерываний The falling edge of INT1 generates an interrupt request
   PCICR  |= (1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);// разрешение прерываний PCINT23...16
   PCMSK2=0b11000000; //разрешаем прерывание pcint23 pcint22
   EIMSK=0b00000000; //разрешаем прерывание int0 и int1 - кнопка EIMSK=0b11000011;
   //MCUCR=0b00001111;// IVSEL, IVCE
   sei(); //Глобальное разрешение прерываний
      //Установка таймера0
   //TCCR0A |= (0 << COM1A1)|(0 << COM1A0)|(1 << WGM01)|(0 << WGM00); //биты COM Normal port operation, OC0A disconnected, WGM T/C in CTC mode
   //TCCR0B |= (0 << WGM02)|(0 << CS02)|(0 << CS01)|(1 << CS00); //биты CS fclk_I/O/1
   //TCNT0=0x00;
   //OCR0A=0x80;   
   //----------//
   //TCCR0A=0x00; //TCCR0=0x00;
//   TCCR0B=0x01; //TCCR0=0x00;
//   TCNT0=0x00;
   // Timer/Counter 1 initialization
   TCCR1A=0x00; //для Compare Output Mode, non-PWM COM1A1/COM1B1=0 COM1A0/COM1B0=0 Normal port operation, OC1A/OC1B disconnected.
   TCCR1B=0x01; //Waveform Generation Mode Bit Description WGM10-13=0 Normal //CS12-10=001 No prescaling
   TCNT1H=0x00;
   TCNT1L=0x00;
   ICR1H=0x00;
   ICR1L=0x00;
   //OCR1AH=0x00;
   //OCR1AL=0x00;
   OCR1BH=0x00; //OCR1B compared with the counter value (TCNT1)
   OCR1BL=0x00;
   // Timer/Counter 2 initialization
   //ASSR=0x00;
   //TCCR2=0x00; //TCCR2=0x00;
   //TCNT2=0x00;
   //OCR2=0x00; //OCR2=0x00;
   MCUCR=0x00;
   //TIMSK0=0x04; //TIMSK=0x04;
//   TIMSK1=0x04; //TIMSK=0x04; //OCIE1B=1
   //ACSR=0x80;
   //SFIOR=0x00;
   //----------//
   
    while(1)
    {      
Knopka_Staroe = (PIND&=(1<<3));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
   //_delay_ms(80);  // Пауза для подавления дребезга контактов.
   Knopka_Novoe = (PIND&=(1<<3));  //...считываем новое состояние кнопки.

   if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
   {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
      //_delay_ms(80);  // Пауза для подавления дребезга контактов.
      s--; 
   }
}
      
// Knopka_Star2 = (PIND&=(1<<2));  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
// if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
// {
//    //_delay_ms(80);  // Пауза для подавления дребезга контактов.
//    Knopka_Nov2 = (PIND&=(1<<2));  //...считываем новое состояние кнопки.
//
//    if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
//    {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
//       //_delay_ms(80);  // Пауза для подавления дребезга контактов.
//       s++;
//    }
// }      
      
      //if (PIND3 == 3) //(PIND3 == 3) работает если кнопка не нажата
    //{s=8;}
      //if (PIND2 == 2) //(PIND2 == 2) работает если кнопка не нажата
   //{s=8;}
      //----------//
      if(mButt_1.up){     // Если кнопка была нажата -> отжата
      mButt_1.up=0;                   // Сбрасываем флаг
      PORT_LED_1 ^=(1<<PIN_LED_1);    // Инвертируем светодиод №1
      s++;
      }
      //----------//
      if(mButt_1.down){   // Если кнопка была отжата -> нажата
      mButt_1.down=0;                 // Сбрасываем флаг
      PORT_LED_2 ^=(1<<PIN_LED_2);    // Инвертируем светодиод №2
      s++;
      }
      //----------//   
      //----------//
      if(mButt_2.up){     // Если кнопка была нажата -> отжата
      mButt_2.up=0;                   // Сбрасываем флаг
      PORT_LED_1 ^=(1<<PIN_LED_1);    // Инвертируем светодиод №1
      s--;
      }
      //----------//
      if(mButt_2.down){   // Если кнопка была отжата -> нажата
      mButt_2.down=0;                 // Сбрасываем флаг
      PORT_LED_2 ^=(1<<PIN_LED_2);    // Инвертируем светодиод №2
      s--;
      }
      //----------//   
              start:
              if (b == 1)
              {s=5;
                 FLAG &= ~ COUNTDOWN;
                 b++;
              }
              
              if (s > 9)
              s--;
              else if (s == 0)
              s++;
              if (FLAG == COUNTDOWN)
              {
                 //cli();
               char i = 0;
                 while (s > -1)
                 {
                    if (s > -1)
                    {
                       a = 5;
                       c = 5;
                       if (FLAG != COUNTDOWN)
                       {
                          goto start;
                       }
                       PORTB |= _BV(PB6); // чтобы мигала точка на индикаторе
                       _delay_ms(250);
                       PORTB &= ~_BV(PB6);
                       _delay_ms(250);
                    }
                    PORTC = digits[s];
                    PORTB = digita[s];
                    _delay_ms(500);
                    PORTB &= ~_BV(PB7); //Красный светодиод
                    _delay_ms(500);
                    PORTB |= _BV(PB7);
                    s--;
                    if (s == 0)
                    {
                       PORTC = digits[s];
                       PORTB = digita[s];                     
                     j=0;
                     shim_start();
                       PORTB &= ~_BV(PB2); //Зеленый светодиод
                       _delay_ms(250);
                       PORTB |= _BV(PB2);
                       _delay_ms(250);
                    }
                  i++;
                     if (i>=10)
                     {ICR1 = 0x00;
                     OCR1A = 0x00;}
                 }
                 sei();
                 FLAG &= ~ COUNTDOWN;
              }
              PORTC = digits[s];
              PORTB = digita[s];

    }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 10:57:15 
Вымогатель припоя

Карма: 22
Рейтинг сообщений: 114
Зарегистрирован: Пн июн 14, 2010 13:07:29
Сообщений: 630
Откуда: Жуковский
Рейтинг сообщения: 0
Цитата:
// Важна последовательность! Сперва подключаем PULL-UP резистор,
// и только потом настраиваем порт на ввод, иначе кнопка работать не будет.
Чушь несусветная. И "настраивать на ввод" необязательно. Там по включению итак нули.
Цитата:
Knopka_Staroe = (PIND&=(1<<3)); // Записываем старое состояние кнопки в переменную Knopka_Staroe.
Зачем там &= ?
Где _BV(), где (1<<PBx), где (1<<3). Опишите задачу. Составьте алгоритм. Очень сложно читать код.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 11:40:26 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
a_skr писал(а):
Цитата:
Knopka_Staroe = (PIND&=(1<<3)); // Записываем старое состояние кнопки в переменную Knopka_Staroe.
Зачем там &= ?
Где _BV(), где (1<<PBx), где (1<<3). Опишите задачу. Составьте алгоритм. Очень сложно читать код.

Как я понимаю (PIND&=(1<<3)) это чтение состояния третьего пина порта, в любом случае что-бы это ни-было функция в протеусе действительно считывает замыкание кнопки на землю и реагирует на это.

Задача уже писал, вот она:
При нажатии любой кнопки происходит увеличение или уменьшении значения на индикаторе на 1 (это работает, но не на таймере, а на векторах прерываний),
При нажатии и удержании обоих клавиш в течении 3сек. происходит запуск обратного отсчета (работает если отслеживать циклом while флаги в регистре EIFR).

Алгоритм:
1. Опрос кнопок
2. Замкнута 1якнопка goto3 else goto4
3. Увеличить значение на 1
4. Замкнута 2якнопка goto5 else goto6
5. Уменьшить значение на 1
6. Замкнуты обе кнопки и удерживаются в течении 3сек. goto7 else goto1
7. Запуск обратного отсчета

Остальной код работает. Постараюсь выкладывать код покомпактнее.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 12:02:43 
Вымогатель припоя

Карма: 22
Рейтинг сообщений: 114
Зарегистрирован: Пн июн 14, 2010 13:07:29
Сообщений: 630
Откуда: Жуковский
Рейтинг сообщения: 0
Цитата:
Как я понимаю (PIND&=(1<<3)) это чтение состояния третьего пина порта
Это не так. a = (PIND&=(1<<3)); соответствует следующему коду:
Код:
PIND = PIND & (1<<3); // - не имеет смысла, т.к. регистр PIND только на чтение
a = PIND; // - в "a" попадут все биты PIND
Правильные варианты:
Код:
a = PIND & (1<<3); // - в "a" будет или ноль или 8
a = PIND & (1<<3) ? 1 : 0; // - в "a" будет или ноль или 1
a = (PIND>>3) & 1; // - тоже самое, займет меньше кода


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 13:08:44 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4599
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Alexeyslav писал(а):
Это определение бита а НЕ ПОРТА, все правильно. PIND3 - константа, которую НАДО подставлять в сравнение вроде PORTD = (1<<PIND3)
Интересно, если это константа, зачем тогда в имени буква "D" ? Она (эта константа) как то привязана конкретно к этому порту ?
Глупое, на мой взгляд, имя для объявления константы-номера бита, малоинформативное. Я, например, увидев её, даже и не понял, что под ней может скрываться цифра 3. На первый взгляд, PIND3 - Это 3-ий пин порта D.
Где логика .... :roll:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 13:32:58 
Вымогатель припоя

Карма: 22
Рейтинг сообщений: 114
Зарегистрирован: Пн июн 14, 2010 13:07:29
Сообщений: 630
Откуда: Жуковский
Рейтинг сообщения: 0
Чисто гипотетически, вдруг выйдет контроллер, в котором какая-нибудь ножка PD8 будет адресоваться через бит 0 в регистре PINDH, и тогда логично объявить константы PIND8 и PD8, равные нулю... ;) а в порту C не будет ножки PC8, тогда константы PINC8 не будет и компилятор даст ошибку при ее использовании. ;)

PS. ну есть же контроллеры, в которых только порт B, например и не все 8 бит задействованы...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 13:35:53 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
В таком коде срабатывает первое if когда кнопка не нажата, а при нажатии кнопки, т.е. замыкании ее на землю второй if не срабатывает.

Код:
Knopka_Staroe = PIND3;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
   _delay_ms(80);  // Пауза для подавления дребезга контактов.
   Knopka_Novoe = PIND3;  //...считываем новое состояние кнопки.

   if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
   {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
      _delay_ms(80);  // Пауза для подавления дребезга контактов.
      s--;
   }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 13:45:18 
Вымогатель припоя

Карма: 22
Рейтинг сообщений: 114
Зарегистрирован: Пн июн 14, 2010 13:07:29
Сообщений: 630
Откуда: Жуковский
Рейтинг сообщения: 0
В этом коде вообще НЕТ опроса кнопок. "PIND3" - это просто "3". Выше дал "Правильные варианты" опроса.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт дек 13, 2013 13:58:30 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
a_skr спасибо, заработали обе кнопки, только три раза через раз срабатывают.
Код:
Knopka_Staroe = PIND & (1<<3) ? 1 : 0;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
   _delay_ms(80);  // Пауза для подавления дребезга контактов.
   Knopka_Novoe = PIND & (1<<3) ? 1 : 0;  //...считываем новое состояние кнопки.

   if (!Knopka_Novoe)  // Новое состояние кнопки должно быть равно 0 (нажата).
   {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
      _delay_ms(80);  // Пауза для подавления дребезга контактов.
      s--;
   }
}
   
Knopka_Star2 = PIND & (1<<2) ? 1 : 0;  // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Star2)  // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
   _delay_ms(80);  // Пауза для подавления дребезга контактов.
   Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;  //...считываем новое состояние кнопки.

   if (!Knopka_Nov2)  // Новое состояние кнопки должно быть равно 0 (нажата).
   {     // В этом случае падающий фронт сформирован и можно инвертировать пины.
      _delay_ms(80);  // Пауза для подавления дребезга контактов.
      s++;
   }
}   


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пн дек 16, 2013 09:51:00 
Прорезались зубы

Зарегистрирован: Вт мар 12, 2013 16:05:45
Сообщений: 219
Рейтинг сообщения: 0
Данный код в цикле while(1); работает раз через три, как сделать чтобы если нажата одна кнопка срабатывала одна команда, если другая то соответственно другая и стабильно. Прерывания отключены. Может дело в дэлэях, может есть способ их не использовать...

Спойлер
Код:
         Knopka_Staroe = PIND & (1<<3) ? 1 : 0;
         if (Knopka_Staroe) //кнопка не нажата тогда if=1
         {
            _delay_ms(20);
            Knopka_Novoe = PIND & (1<<3) ? 1 : 0;
            Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;
            if(!Knopka_Novoe && Knopka_Nov2) //кнопка нажата и кнопка не нажата тогда if=1
            {
               PORTB |= _BV(PB6); //точка на индикаторе загорается
               _delay_ms(100);
               s--;
            }
            PORTB &= ~_BV(PB6); //точка на индикаторе гаснет
         }

         Knopka_Star2 = PIND & (1<<2) ? 1 : 0;
         if (Knopka_Star2)
         {
            _delay_ms(20);
            Knopka_Novoe = PIND & (1<<3) ? 1 : 0;
            Knopka_Nov2 = PIND & (1<<2) ? 1 : 0;
            if(Knopka_Novoe && !Knopka_Nov2)
            {
               PORTB |= _BV(PB6); //точка на индикаторе загорается
               _delay_ms(100);
               s++;
            }
            PORTB &= ~_BV(PB6); //точка на индикаторе гаснет
         }


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Вт дек 17, 2013 00:47:04 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 106
Зарегистрирован: Ср фев 22, 2012 01:25:21
Сообщений: 882
Рейтинг сообщения: 0
Ды не изобретай велосипед... вот пару вариантов, глянь, может что подойдет...
http://asis-kbr.ru/forum/viewtopic.php?f=13&t=173


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Чт апр 03, 2014 14:26:33 
Потрогал лапой паяльник
Аватар пользователя

Карма: 4
Рейтинг сообщений: 13
Зарегистрирован: Пн апр 01, 2013 15:13:40
Сообщений: 343
Откуда: Москва
Рейтинг сообщения: 0
Добрый день, Коты! Получилась такая тема: остались свободными 2 ножки МК, которые как раз INT0 и INT1. И мне как раз нужно сделать 2 кнопки. И вот я думаю, что легче для программы, подключить библиотеку нажатия кнопок, в которой ловится 0 на ноге, потом заданное количество раз перепроверяется и даёт на выходе разрешение на выполнение кода. Или использовать внешнее прерывание, допустим, по спадающему фронту на ножках?

_________________
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите опросить кнопку
СообщениеДобавлено: Пт апр 04, 2014 00:38:40 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 106
Зарегистрирован: Ср фев 22, 2012 01:25:21
Сообщений: 882
Рейтинг сообщения: 3
Подключение через INT0 или INT1 оправдано только если надо выводить устройство из энергосберегающих режимов...
В других случаях лучше периодически (в прерывании) опрашивать линии кнопок.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 509 ]     ... , , , 8, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y