включение нагрузки 1 кнопкой без фиксации, на МК

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
sergo80zxc
Встал на лапы
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

включение нагрузки 1 кнопкой без фиксации, на МК

Сообщение sergo80zxc »

приветствую, не работает код в протеусе, может я что то сделал не так?







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

// ---------- Проверка разряда на наличие логической единицы (установки) с if------------------
//
//
// кнопка на PB0 , а светодиоды на  PB1
//
// переключение нагрузки при нажатии кнопки, не проверена в железе,
// в протеусе через раз работает
//
//
//
//
   #include <avr/io.h>
        #define F_CPU 1200000UL
   #include <util/delay.h>

//===================


     int main(void)

{

         DDRB  = 0b00000010;          // настраиваем  бит в1 на выход, остальные на вход
         PORTB = 0b11111101;           // подтягиваем резистороми биты которые на вход
      
        int i=0;                       //  объявляем переменную счетчик и обнуляем ее      

//===============
 

        while (PINB & (1<<PB0))        // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
                                       // При сбросе его начнет выполняться Код2.
         {

           
         }
              _delay_ms(1000);       // Код1; задержка 10 мс

                 i++;                 // Код2; кнопка нажата, добавляем 1  к переменной

//===============
 
         while (PINB & (1<<PB0))        // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
                                        // При сбросе его начнет выполняться Код2.
         {

         
         }
              _delay_ms(1000);        // Код1; задержка 10 мс

                 i++;                  // Код2; кнопка нажата, добавляем 1  к переменной

//===============
         while (PINB & (1<<PB0))        // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
                                        // При сбросе его начнет выполняться Код2.
         {

         
         }
              _delay_ms(1000);        // Код1; задержка 10 мс 

                 i++;                  // Код2; кнопка нажата, добавляем 1  к переменной

//===============


           if (i==3)                             //если i =3 ( при траекратном опросе кнопки было обнаружено нажатое состояние)
      
         {
             PORTB ^= (1<<PB1);                // инвертируем состояние пина PB1
            i=0;                              // сбросим счетчик         
         
           }
 
 
 
}

глаза боятся, а руки что то не делают))
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение ARV »

sergo80zxc писал(а):может я что то сделал не так?
всё :)

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

while (PINB & (1<<PB0))        // Код1 будет выполняться пока 0-й разряд регистра PINB установлен.
                                       // При сбросе его начнет выполняться Код2.
         {

           
         }
код для оператора while, который должен выполняться, должен находиться внутри фигурных скобок.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15542
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение BOB51 »

DDRB = 0b00000010;
PORTB = 0b11111101;
т.е.
PINB = 0b11111101
Ждем пока истина (true)
while (PINB & (1<<PB0))
НО....

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

PINB =   0b11111101
И (&)
1<<PB0 = 0b00000001

никогда истиной не станет
:roll:
Последний раз редактировалось BOB51 Ср апр 08, 2020 12:10:06, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение ARV »

BOB51 писал(а):никогда истиной не станет
фигню изволили сморозить :)))
1<<PB0 = 0b00000001

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

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15542
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение BOB51 »

согласен...
Зевнул
:oops:
Но результат даже при Вашем варианте = FALSE
8)
(см. выше исправленное)
У нас же по условию топикстартера PB1 есть выход в состоянии 0.
А я просмотрел только ситуацию в самом начале текста.
:roll:
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение ARV »

BOB51 писал(а):Но результат даже при Вашем варианте = FALSE
кiк тiк?!

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

DDRB  = 0b00000010; 
PORTB = 0b11111101;

настроили PB0 в режим входа с подтяжкой. если там кнопка на общий - то при ненажатой кнопке в PB0 будет 1

0b11111101 & 0b00000001 == 0b00000001 - не равно 0, значит, TRUE :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

_delay_ms(1000); // Код1; задержка 10 мс - это не 10 мс, а 1 с )
EDIT: и не код1 это у вас, а уже код, т.к. за скобкой.
Последний раз редактировалось NStorm Ср апр 08, 2020 14:01:43, всего редактировалось 1 раз.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15542
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение BOB51 »

ОЙ, МЛИН!...
:o
"все что не нуль - true"...
А мня чегось заклинило на "все единицы"!...
:facepalm:
Довел Вирь подлый...(и "меры противодействия")...
:twisted:
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

Вот как надо примерно:

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

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1200000UL

int main(void) {
  DDRB = 0b00000010;
  PORTB = 0b11111101;
  int i = 0;
  while (1) { // не забываем делать всё в цикле, иначе прога отработет один раз
    while (PINB & (1 << PB0)) {} // ждем бесконечно пока пин в высоком уровне
    while (!(PINB & (1 << PB0))) { // пока пин в низком, начинаем считать антидребезг
      i++;
      delay_ms(1); // ждем 1 мс
      if (i > 30)  // если насчитали 30 мс,
        break;     // выходим из цикла антидребезга
    }
    if (i >= 30) {         // если ранее дождались антидребезга в 30 мс,
      PORTB ^= (1 << PB1); // то переключаем порт
      i = 0;               // и сбрасываем счетчик
    } else
      i = 0;               // а если не дожались, всё-равно надо обнулить переменную,
                           // иначе дребезг рано или поздно переключит нагрузку
  }
}


И не забывайте, что в протеусе дребезга не бывает.
Вообще это реализация обычного Т-триггера. Тут и МК не нужен, а примеров реализаций тонна на чем угодно.
Аватара пользователя
sergo80zxc
Встал на лапы
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение sergo80zxc »

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

//
//включение и отключение нагрузки тактовой кнопкой
//
//

#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>


int main(void)
{
     DDRB = 0b00000010;
     PORTB = 0b11111101;

     int i = 0;

    while (1)                             // не забываем делать всё в цикле, иначе прога отработет один раз
 {             

       while (PINB & (1 << PB0)) {}       // ждем бесконечно пока пин в высоком уровне

       while (!(PINB & (1 << PB0)))       // пока пин в низком, начинаем считать антидребезг     
     {
             i++;
             _delay_ms(10);               // ждем 1 мс


        if (i > 30)                       // если насчитали 30 мс,

        break;                            // выходим из цикла антидребезга
      }
        if (i >= 30)                      // если ранее дождались антидребезга в 30 мс,
       {
           PORTB ^= (1 << PB1);           // то переключаем порт
           i = 0;                         // и сбрасываем счетчик
       } 
        else
           i = 0;                         // а если не дожались, всё-равно надо обнулить переменную,
                                          // иначе дребезг рано или поздно переключит нагрузку
 }
}



код работает в протеусе если вовремя руку от кнопки убирать, если держать ее нажатой, то лед моргает, по ходу надо организовывать отслеживание отпускания кнопки?
глаза боятся, а руки что то не делают))
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

Добавьте после переключения порта и i = 0 код ожидания отпускания кнопки тогда:
while (!(PINB & (1 << PB0)));
Аватара пользователя
sergo80zxc
Встал на лапы
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение sergo80zxc »

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

//
//включение и отключение нагрузки тактовой кнопкой
//
//

#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>


int main(void)
{
     DDRB = 0b00000010;
     PORTB = 0b11111101;

     int i = 0;

    while (1)                             // не забываем делать всё в цикле, иначе прога отработет один раз
 {   
           
// ----------

       while (PINB & (1 << PB0)) {}       // ------Ожидание сброса бита с while. ждем бесконечно пока пин в высоком уровне
                                          // Код1 будет выполняться пока 0-й разряд регистра PINВ установлен. При сбросе его начнет выполняться Код2.
                                          // Код1 пустой цикл, Код2 в данном случае переход к следующему оператору

       while (!(PINB & (1 << PB0)))       // ------Ожидание установки бита с while.  пока пин в низком, начинаем считать антидребезг
     {                                   //

             i++;
             _delay_ms(1);               // ждем 1 мс


        if (i > 30)                       // если насчитали 30 мс,

        break;                            // выходим из цикла антидребезга
      }
        if (i >= 30)                      // если ранее дождались антидребезга в 30 мс,
       {

           i = 0;                         //  сбрасываем счетчик

            while (!(PINB & (1 << PB0)));   // и ждем когда кнопку отпустят крутясь в пустом цикле
           {

           }

           PORTB ^= (1 << PB1);           // дождались отпускания кнопки  и переключаем порт
       }


// ----------                                       // иначе дребезг рано или поздно переключит нагрузку
 }
}




заработало) спасибо
глаза боятся, а руки что то не делают))
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

Незначительный нюанс - скобки { } после while ... ; лишние.
Либо while (!(PINB & (1 << PB0)));, либо while (!(PINB & (1 << PB0))) { }.
Это в общем-то одно и тоже в данном случае, но в других случаях сами себя запутаете.
OKF
Это не хвост, это антенна
Сообщения: 1384
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение OKF »

)) Либо while (!(PINB & 1<<0));
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

OKF, плохой пример использовать магические числа.
А вообще есть специальные макросы loop_until_bit_is_set(PINB, PB0);
Аватара пользователя
sergo80zxc
Встал на лапы
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение sergo80zxc »

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

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

//
//включение и отключение нагрузки тактовой кнопкой
//
//

#include <avr/io.h>
#define F_CPU 1200000UL
#include <util/delay.h>


int main(void)
{
     DDRB = 0b00000010;
     PORTB = 0b11111101;

     int i = 0;

    while (1)                             // не забываем делать всё в цикле, иначе прога отработет один раз
 {   
           
// ----------

       while (PINB & (1 << PB0)) {}       // ------Ожидание сброса бита с while. ждем бесконечно пока пин в высоком уровне
                                          // Код1 будет выполняться пока 0-й разряд регистра PINВ установлен. При сбросе его начнет выполняться Код2.
                                          // Код1 пустой цикл, Код2 в данном случае переход к следующему оператору

       while (!(PINB & (1 << PB0)))       // ------Ожидание установки бита с while.  пока пин в низком, начинаем считать антидребезг
     {                                   //

             i++;
             _delay_ms(1);               // ждем 1 мс


        if (i > 30)                       // если насчитали 30 мс,

        break;                            // выходим из цикла антидребезга
      }
        if (i >= 30)                      // если ранее дождались антидребезга в 30 мс,
       {

           i = 0;                         //  сбрасываем счетчик

            while (!(PINB & (1 << PB0)))   // и ждем когда кнопку отпустят крутясь в пустом цикле
           {

           }

           PORTB ^= (1 << PB1);           // дождались отпускания кнопки  и переключаем порт
       }


// ----------                                       // иначе дребезг рано или поздно переключит нагрузку
 }
}
глаза боятся, а руки что то не делают))
OKF
Это не хвост, это антенна
Сообщения: 1384
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение OKF »

OKF, плохой пример использовать магические числа.
А вообще есть специальные макросы loop_until_bit_is_set(PINB, PB0);

Да, но PB0 ничем не лучше.) Тогда уж нужно было обозвать логичным именем.
Макросы libc иногда более долгочитаемы, как этом например.) И для таких простых вещей лишние.

Добавлено after 2 minutes 48 seconds:
Тогда уж лучше свои: while (!pin(KEY));
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение NStorm »

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

Функции и циклы. В общем-то это у вас и так используется уже. Вызов _delay_ms(1); и есть вызов функции, которая встроена в библиотеку AVR просто. Можете свою функцию написать и вызывать её.
Циклы - у вас while (...) используется. Он зацикливает действия внутри { } пока выполняется условие в ( ).

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

       while (!(PINB & (1 << PB0)))       // ------Ожидание установки бита с while.  пока пин в низком, начинаем считать антидребезг
     {                                   //
             i++;
             _delay_ms(1);               // ждем 1 мс
        if (i > 30)                       // если насчитали 30 мс,
        break;                            // выходим из цикла антидребезга
      }

Соб-но участок внутри { } повторяется пока соблюдается условие (!(PINB & (1 << PB0))), т.е. на пине низкий уровень. Или же пока i не станет больше 30, тогда оператор break прерывает цикл.
Почитайте про циклы на C - for, do, while. Вот, например: https://prog-cpp.ru/c-cycles/
PS: Несмотря на то, что в C тоже есть goto - использовать его в большинстве случаев моветон. Почти ни в одной готовой программе вы его не найдете. Написать всегда можно без него, а реально он почти никогда не нужен.

Добавлено after 5 minutes 31 second:
Да, но PB0 ничем не лучше.) Тогда уж нужно было обозвать логичным именем.

В данном случае понятно дело мало значимо. Просто дурную привычку так можно привить и потом я вижу тут кучу кода, когда народ во регистры периферии пишет HEX-магию, вместо читаемых сдвигов с макросами.
Аватара пользователя
sergo80zxc
Встал на лапы
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение sergo80zxc »

попробовал на таймере это же сделать, что то не полуучается, не работает код, вроде все логично, товарищи пушистые есть мысли?


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

/* 
 *
 * АТИНИ13
 *пример настройки прерывания по таймеру Т0
 *
 * 
 *
 *грамотно организована программа мигания светодиода  на прерывании, не расходует основные ресурсы МК в
 *
 *
 *
 */
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1200000UL



int main(void)
{
     DDRB  = 0b11111110;         // бит РВ0 конфигурируем как вход
     PORTB = 0b00000001;         // входы подтянем





  TIMSK0  = 0b00000010;         //бит РВ1(TOIE0) устанавливаем в 1, разрешения прерывания по переполнению таймера /счетчика Т0 
  TCCR0A  = 0b00000000;         //биты РВ0(WGM00) и РВ1(WGM01) сбрасываем в 0,  настройка режима Normal 
  TCCR0B  = 0b00000011;         //настраиваем предделитель на 64 (биты  CS02=0,CS01=1,CS00=1) ,   бит В3(WGM02) сбрасываем в 0,настройка режима Normal
  GTCCR   = 0b00000001;          //бит РВ0(PSR10) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
 
  sei();                        //Разрешить прерывания



  while(1)
  {
                    //Основной цикл программы, он пуст, так как вся работа в прерывании
  }
}



//----------

 ISR(TIM0_OVF_vect)  //обработчик прерывания по таймеру Т0
{

   volatile int i = 0;                 //  объявляем переменную счетчик и обнуляем ее
   volatile int k = 0;                 //  объявляем переменную счетчик и обнуляем ее



         if (PINB & (1<<PB0))             // Если нулевой разряд порта D установлен, то выполняется (Код1). В противном случае, выполняется (Код2).
         {
             k++;                         // (Код1) пин PB0 установлен(кнопка не нажата) прибавим 1 к переменной счетчику                
        }
      
         else
        {
               i++;                         // (Код2) пин PB0 сброшен(кнопка нажата) прибавим 1 к переменной счетчику           
         }   
//----------

        if (i>=3  )                    // если счетчик больше или равен 3 то,  кнопка нажата  была при всех опросах,
       {

           if (k>=3  )
          {
   
            PORTB ^= (1<<PB1);           // инвертируем состояние пина PB1

              i = 0;                 // 
              k = 0;                 // 

          }
   
 
 

       } 
   
         



           



}
 
глаза боятся, а руки что то не делают))
OKF
Это не хвост, это антенна
Сообщения: 1384
Зарегистрирован: Вт июн 07, 2011 08:03:18

Re: включение нагрузки 1 кнопкой без фиксаци

Сообщение OKF »

В данном случае понятно дело мало значимо. Просто дурную привычку так можно привить и потом я вижу тут кучу кода, когда народ во регистры периферии пишет HEX-магию, вместо читаемых сдвигов с макросами.

Да, согласен. Я даже стараюсь на машине при манёвре ВСЕГДА включать поворот. Пусть даже рядом никого нет, ну или я заезжаю там во двор. Вроде бы ерунда, но рефлексы должны присутствовать.)))
Ответить

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