Страница 1 из 2

Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 10:20:30
~=ieroglif=~
Приветствую Всех читающих этот текст !!!
Есть небольшая проблема
Проблема состоит в том что написал я код для Атмеги 32 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
скрин схемы в протэусе прилагаю,а также код С++ написанный в AVR Studio.
Заранее благодарю
P.S.
Я новичок в этом деле,но готов учиться если кто то мне подскажет как ...


Код на С++

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

/*
 * AVRGCC1.c
 *
 * Created: 09.07.2016 2:06:01
 *  Author: ieroglif
 */
#include <util/delay.h>
#include <avr/io.h>


void DDR();        // ПРОТОТИП ФУНКЦИИ ВКЛЮЧЕНИЯ ВСЕХ ПОРТОВ НА ВЫВОД
void PORT_ALL();  // ПРОТОТИП ФУКЦИИ ВКЛЮЧЕНИЯ И ВЫКЛЮЧЕНИЯ ВСЕХ ПОРТОВ
void PORT_for();  // ПРОТОТИП ФУКЦИИ ЦИКЛА for()
void PORT_ACBD(); // ПРОТОТИП ФУНКЦИИ ПЕРЕКЛЮЧЕНИЯ ПОРТОВ A => C => B => D

int main(void)
{
   
      DDR();
   
      while(1) // БЕСКОНЕЧНЫЙ ЦИКЛ
      {
         PORT_ALL();
         PORT_for();   
      }      
      
}               

void DDR()
{
   DDRA = 0b11111111; // ВКЛЮЧЕНИЕ ПОРТА "A" НА ВЫВОД
   DDRB = 0b11111111; // ВКЛЮЧЕНИЕ ПОРТА "B" НА ВЫВОД
   DDRC = 0b11111111; // ВКЛЮЧЕНИЕ ПОРТА "C" НА ВЫВОД
   DDRD = 0b11111111; // ВКЛЮЧЕНИЕ ПОРТА "D" НА ВЫВОД   
}
void PORT_ALL()
{
      PORTA = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "A"
      PORTB = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "B"
      PORTC = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "C"
      PORTD = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "D"
                  
      _delay_ms(500); // ПАУЗА В 500 МИЛЛИСЕКУНД
                     
      PORTA = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "A"
      PORTB = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "B"
      PORTC = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "C"
      PORTD = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "D"
}   
void PORT_for()
{
   int PORT[9] = {0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000,0b00000000};

               for (int i = 0; i < 9; i++)
               {
                  PORTA = PORT[i];
                  _delay_ms(135);            
               }
               PORT_ALL();
               PORT_ACBD();
                  for (int i = 0; i < 9; i++)
                  {
                     PORTB = PORT[i];
                     _delay_ms(135);
                  }
                  PORT_ALL();
                  PORT_ACBD();
                     for (int i = 0; i < 9; i++)
                     {
                        PORTC = PORT[i];
                        _delay_ms(135);
                     }
                     PORT_ALL();
                     PORT_ACBD();
                        for (int i = 0; i < 9; i++)
                        {
                           PORTD = PORT[i];
                           _delay_ms(135);
                        }
         
}   
void PORT_ACBD()
{
      PORTA = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "A"
      _delay_ms(250); // ПАУЗА В 500 МИЛЛИСЕКУНД
      PORTA = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "A"
      
      PORTC = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "C"
      _delay_ms(250); // ПАУЗА В 500 МИЛЛИСЕКУНД
      PORTC = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "C"
      
      PORTB = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "B"
      _delay_ms(250); // ПАУЗА В 500 МИЛЛИСЕКУНД
      PORTB = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "B"
      
      PORTD = 0b11111111; // ВКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "D"
        _delay_ms(250); // ПАУЗА В 500 МИЛЛИСЕКУНД
      PORTD = 0b00000000; // ВЫКЛЮЧЕНИЕ ВСЕХ НОЖЕК ПОРТА "D"
      
}


СКРИШОТ В ПРОТЭУСЕ

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 11:14:45
CB1
В вашей схеме в Proteus кнопка может только отключить светодиоды и то на время пока она нажата. Вы подключили кнопку на вход Reset, при подаче логического 0 на данный вход происходит сброс микроконтроллера(все светодиоды погаснут), после отпускания кнопки программа начнет выполнятся заново. Для подключения кнопки нужно выделить ножку какого нибудь порта.

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 11:51:45
Аlex
~=ieroglif=~ писал(а):Проблема состоит в том что написал я код для Атмеги 32 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
А проблема то в чём ? Вы описали хотелку, а не проблему.

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 12:38:02
RS-7th
у автора три видео про прерывания , даю первое ,а дальше сориентируетесь если будет полезное
https://youtu.be/OVdgEWHcuJQ?list=PL6787D9CDAB4A30DE

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 14:18:15
~=ieroglif=~
CB1 писал(а):В вашей схеме в Proteus кнопка может только отключить светодиоды и то на время пока она нажата. Вы подключили кнопку на вход Reset, при подаче логического 0 на данный вход происходит сброс микроконтроллера(все светодиоды погаснут), после отпускания кнопки программа начнет выполнятся заново. Для подключения кнопки нужно выделить ножку какого нибудь порта.


ЭТО кнопка сброса,а я хочу помимо этой кнопки поставить ещё одну которая будет просто зажигать все светодиоды,сделать некий переключатель на котором по нажатию меняется работа светодиодов то переливается как в программе по коду,то по нажатию кнопки просто всё загорается.
И кстати даже если зажмёшь кнопку reset то она просто потушит все светодиоды.

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 14:20:28
~=ieroglif=~
Аlex писал(а):
~=ieroglif=~ писал(а):Проблема состоит в том что написал я код для Атмеги 32 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
А проблема то в чём ? Вы описали хотелку, а не проблему.


Ну так проблема и заключается в том ,что я не знаю как это сделать... :cry:

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 14:26:53
Аlex
~=ieroglif=~ писал(а):Ну так проблема и заключается в том ,что я не знаю как это сделать...
Вы не знаете как опросить ПИН микроконтроллера ?

https://yandex.ru/search/?lr=2&msid=146 ... 0%B0%20avr :facepalm:

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 16:58:40
Jack_A
Наверно, засада в том, что все пины портов заняты. А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно - нужно было додуматься. И опрашивать ее раз 10 в секунду, переводя в состояние ввода.

Re: Помогите подключить кнопку

Добавлено: Вс июл 24, 2016 21:25:30
~=ieroglif=~
Jack_A писал(а):Наверно, засада в том, что все пины портов заняты. А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно - нужно было додуматься. И опрашивать ее раз 10 в секунду, переводя в состояние ввода.


И как мне это сделать ?

Re: Помогите подключить кнопку

Добавлено: Пн июл 25, 2016 05:29:34
Alkul
~=ieroglif=~ писал(а):
Jack_A писал(а):А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно

И как мне это сделать ?

Такую элементарную вещь не можете придумать? :facepalm:
Инициализируйте таймер на переполнение через 100 мс, внутри обработчика прерывания запомните текущее состояние соответствующего пина, переключите этот пин на вход, опросите пин, запомните состояние в переменной, переключите пин снова на выход, восстановите его исходное состояние и выходите из обработчика.
В основном цикле анализируйте значение переменной и принимайте решение в зависимости от того, нажата кнопка или нет.

Re: Помогите подключить кнопку

Добавлено: Пн июл 25, 2016 09:31:10
BOB51
схемно - вот так
схемс.GIF
(3.79 КБ) 829 скачиваний

программно - на свое усмотрение.
8)

Re: Помогите подключить кнопку

Добавлено: Пн июл 25, 2016 09:40:15
ARV
BOB51 писал(а):схемно - вот так
Изображение
так делать нельзя!
во всяком случае для первоначальной схемы, где каждый пин МК задействован под отдельный светодиод (честно говоря, я так и не понял, в чем фишка применения матриц... но раз надо, значит, надо).

Re: Помогите подключить кнопку

Добавлено: Пн июл 25, 2016 20:20:03
CB1
Вот не плохие уроки по программированию AVR для начинающих http://forum.cxem.net/index.php?showtopic=136229
Помогают разобраться в азах программирования AVR

Re: Помогите подключить кнопку

Добавлено: Вс июл 31, 2016 09:30:16
~=ieroglif=~
Короче говоря,преодолевая все мучения и соблазны бросить это дело,я всё таки как то и что то написал. Есть кое какие проблемы,если не трудно подскажите как их исправить.
1 - где то здесь есть то,что не даёт переключить программу сразу,а приходится именно поймать момент когда заканчивается одна тут же нажимаешь и только после этого срабатывает кнопка и переключается программа.

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

if (!( PIND & (1 << PIND3))) // если кнопка не нажата
      {
         PORTA = 0b01010101;   
      }
   
         else if (PIND & (1 << PIND3))   
           {
            sw++;
           }
         
         switch (sw)
         {         
         case 1:   
               for (int i = 0; i < 4; i++)
               {
                  PORTA=array[i];
                  _delay_ms(250);
               };break;


2 - Проблема в том ,что почему то в этом месте приходится нажимать два раза для переключения программы

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

      
         case 4:
               PORTA = 0b01000001;   
               _delay_ms(250);break;
         
         case 5:
               PORTA = 0b00010001;
               _delay_ms(250);


3 - После всех семи case почему то загораются все светодиоды и надо нажать ровно 18 раз для переключения первой программы. Весь код и скриншот эмуляции в Протэусе прилагаю. Заранее благодарю всех не равнодушных.



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

/*
 * AVRGCC2.c
 *
 * Created: 26.07.2016 23:40:50
 *  Author: ieroglif
 */

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

int main(void)
{
      int sw=0;
      int array[4]={0b00000001,0b00000100,0b00010000,0b01000000}; // мигание 1,3,5,7 светодиодами
      int yarra[4]={0b01000000,0b00010000,0b00000100,0b00000001}; // мигание 7,5,3,1 светодиодами
   
   
      DDRA = 0b01010101;
      DDRB = 0b00000000;
      DDRC = 0b00000000;
      DDRD = 0b00000000;
      
      PORTA = 0b00000000;
      PORTB = 0b00000000;
      PORTC = 0b00000000;
      PORTD = 0b00000000;
      
    while(1)
    {
      
      if (!( PIND & (1 << PIND3))) // если кнопка не нажата
      {
         PORTA = 0b01010101;   
      }
   
         else if (PIND & (1 << PIND3))   
           {
            sw++;
           }
         
         switch (sw)
         {         
         case 1:   
               for (int i = 0; i < 4; i++)
               {
                  PORTA=array[i];
                  _delay_ms(250);
               };break;
            
         case 2:
               for (int i = 0; i < 4; i++)
               {
                  PORTA=yarra[i];
                  _delay_ms(250);
               };break;
            
         case 3:      
               PORTA = 0b00010100;
               _delay_ms(250);break;
               
         case 4:
               PORTA = 0b01000001;   
               _delay_ms(250);break;
         
         case 5:
               PORTA = 0b00010001;
               _delay_ms(250);
               
         case 6:
               PORTA = 0b01010000;      
               _delay_ms(250);break;
               
         case 7:
               PORTA = 0b00000101;      
               _delay_ms(250);break;
         }
      
    }
}

Re: Помогите подключить кнопку

Добавлено: Вс июл 31, 2016 11:09:37
COKPOWEHEU
if (!( PIND & (1 << PIND3))) // если кнопка не нажата
{
PORTA = 0b01010101;
}

else if (PIND & (1 << PIND3))
{
sw++;
}

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

if( !var ){
//какой-то код
}else if( var ){
//какой-то другой код
}else{
//а вот тут чистый PROFIT
}
Это к тому что проверять и условие и обратное ему бессмысленно. Разве что хотите поймать изменение в течение пары тактов, в чем я сомневаюсь.
switch (sw)
{
case 1:
а что должно произойти когда sw станет больше 7 ?
1 - где то здесь есть то,что не даёт переключить программу сразу,а приходится именно поймать момент когда заканчивается одна тут же нажимаешь и только после этого срабатывает кнопка и переключается программа.
Можете проверять кнопку по прерыванию таймера. Разумеется, переменную sw придется делать глобальной (и, разумеется, volatile). Либо организовать методом конечного автомата.

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

void mode_1(){
  static unsigned char num = 0;
  PORTA = array[ num ];
  num++;
  if( num > 4 )num=0;
}
...
switch(sw){
  case 0: mode_1(); break;
  case 1: ...
  default: sw=0;
}
_delay_ms(100);

Re: Помогите подключить кнопку

Добавлено: Вс июл 31, 2016 22:09:50
~=ieroglif=~
case 1:[/quote]а что должно произойти когда sw станет больше 7 ?


Проблему с 18 нажатиями на кнопку для переключения программы я решил благодаря подсказке с default (\ просто при написании про него забыл).СПАСИБО БОЛЬШОЕ...

Re: Помогите подключить кнопку

Добавлено: Вс июл 31, 2016 22:18:57
~=ieroglif=~
Это к тому что проверять и условие и обратное ему бессмысленно. Разве что хотите поймать изменение в течение пары тактов, в чем я сомневаюсь.



Удалил опять же по Вашему совету(если конечно я Вас правильно понял) первую проверку

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

  while(1)
    {
       if (PIND & (1 << PIND3))   
           {
            sw++;
           }
         
         switch (sw)
         {         
         case 1: .............   

Правильно ?

Re: Помогите подключить кнопку

Добавлено: Вс июл 31, 2016 23:00:28
COKPOWEHEU
Так у вас пропала вторая ветка. Она не нужна была? Скорее, что-то вроде такого.

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

if (!( PIND & (1 << PIND3))){ // если кнопка не нажата
  PORTA = 0b01010101;
}else{
  sw++;
}
С опросом кнопок во время выполнения анимаций разобрались?

Re: Помогите подключить кнопку

Добавлено: Пн авг 01, 2016 11:24:29
~=ieroglif=~
COKPOWEHEU писал(а):Так у вас пропала вторая ветка. Она не нужна была? Скорее, что-то вроде такого.

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

if (!( PIND & (1 << PIND3))){ // если кнопка не нажата
  PORTA = 0b01010101;
}else{
  sw++;
}
С опросом кнопок во время выполнения анимаций разобрались?



Думаю,что не нужна,если не прав,то объясните пожалуйста почему.

А вот с опросом во время анимации не могу пока додуматься . . .

Re: Помогите подключить кнопку

Добавлено: Пн авг 01, 2016 16:31:47
COKPOWEHEU
Думаю,что не нужна,если не прав,то объясните пожалуйста почему.
оО Мне-то откуда знать, нужна или нет, это же ваш алгоритм.
А вот с опросом во время анимации не могу пока додуматься
Попробую объяснить. Первый вариант самый простой - опрос по прерыванию таймера. То есть, например, 10 раз в секунду возникает прерывание. Независимо от того, чем контроллер занимался до этого, он прыгает на обработчик. В нем проверяется нажата ли кнопка, если нажата - увеличиваете переменную.
Второй способ чуть сложнее и напоминает работу операционной системы. Процедуре выделяется квант времени, после чего она должна вернуть управление основному циклу. Через небольшое время ей выделяется еще квант и так далее. В вашей задаче заморачиваться строгим выдерживанием интервалов не нужно, поэтому хватит общего делея. Поясню на примере:

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

char step = 0; //глобальная переменная нагляднее
void task_1(){
  PORTB = arr[step];
  step++;
}
...
while(1){
  update_kbd();
  switch(sw){
    case 1: task_1(); break;
    case 2: task_2(); break;
...
    case N: task_N(); break;
    default: sw=0;
  };
  _delay_ms(100);
}
При каждом проходе цикла сначала вызывается update_kbd(), то есть обработка клавиатуры, и одна из задач task_1() ... task_N() в зависимость от переменной sw. Идея в том, чтобы каждая задача выполнялась максимально быстро, зато вызывалась с примерно равными интервалами. Иными словами, каждый вызов будет отображать не всю анимацию, а только один кадр. А между кадрами, когда задача просто крутится в цикле и ждет, обрабатывались кнопки или что-то еще.