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

Обсуждаем контроллеры компании Atmel.
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=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"
      
}


СКРИШОТ В ПРОТЭУСЕ
Вложения
Протэус.png
(101.79 КБ) 421 скачивание
Ученье свет,а неученье - тьма... чуть свет и на работу ...
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

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

Сообщение CB1 »

В вашей схеме в Proteus кнопка может только отключить светодиоды и то на время пока она нажата. Вы подключили кнопку на вход Reset, при подаче логического 0 на данный вход происходит сброс микроконтроллера(все светодиоды погаснут), после отпускания кнопки программа начнет выполнятся заново. Для подключения кнопки нужно выделить ножку какого нибудь порта.
Все гениальное - просто
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

~=ieroglif=~ писал(а):Проблема состоит в том что написал я код для Атмеги 32 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
А проблема то в чём ? Вы описали хотелку, а не проблему.
Аватара пользователя
RS-7th
Открыл глаза
Сообщения: 58
Зарегистрирован: Чт ноя 27, 2008 15:36:53
Откуда: Одесса

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

Сообщение RS-7th »

у автора три видео про прерывания , даю первое ,а дальше сориентируетесь если будет полезное
https://youtu.be/OVdgEWHcuJQ?list=PL6787D9CDAB4A30DE
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

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


ЭТО кнопка сброса,а я хочу помимо этой кнопки поставить ещё одну которая будет просто зажигать все светодиоды,сделать некий переключатель на котором по нажатию меняется работа светодиодов то переливается как в программе по коду,то по нажатию кнопки просто всё загорается.
И кстати даже если зажмёшь кнопку reset то она просто потушит все светодиоды.
Ученье свет,а неученье - тьма... чуть свет и на работу ...
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

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


Ну так проблема и заключается в том ,что я не знаю как это сделать... :cry:
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

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

https://yandex.ru/search/?lr=2&msid=146 ... 0%B0%20avr :facepalm:
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

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

Сообщение Jack_A »

Наверно, засада в том, что все пины портов заняты. А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно - нужно было додуматься. И опрашивать ее раз 10 в секунду, переводя в состояние ввода.
Изображение
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

Jack_A писал(а):Наверно, засада в том, что все пины портов заняты. А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно - нужно было додуматься. И опрашивать ее раз 10 в секунду, переводя в состояние ввода.


И как мне это сделать ?
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

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

Сообщение Alkul »

~=ieroglif=~ писал(а):
Jack_A писал(а):А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно

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

Такую элементарную вещь не можете придумать? :facepalm:
Инициализируйте таймер на переполнение через 100 мс, внутри обработчика прерывания запомните текущее состояние соответствующего пина, переключите этот пин на вход, опросите пин, запомните состояние в переменной, переключите пин снова на выход, восстановите его исходное состояние и выходите из обработчика.
В основном цикле анализируйте значение переменной и принимайте решение в зависимости от того, нажата кнопка или нет.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15549
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

схемно - вот так
схемс.GIF
(3.79 КБ) 829 скачиваний

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

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

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

Сообщение CB1 »

Вот не плохие уроки по программированию AVR для начинающих http://forum.cxem.net/index.php?showtopic=136229
Помогают разобраться в азах программирования AVR
Все гениальное - просто
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=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;
         }
      
    }
}
Вложения
Протэус.png
(140.6 КБ) 402 скачивания
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение 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);
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

case 1:[/quote]а что должно произойти когда sw станет больше 7 ?


Проблему с 18 нажатиями на кнопку для переключения программы я решил благодаря подсказке с default (\ просто при написании про него забыл).СПАСИБО БОЛЬШОЕ...
Ученье свет,а неученье - тьма... чуть свет и на работу ...
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

Это к тому что проверять и условие и обратное ему бессмысленно. Разве что хотите поймать изменение в течение пары тактов, в чем я сомневаюсь.



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

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

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

Правильно ?
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение COKPOWEHEU »

Так у вас пропала вторая ветка. Она не нужна была? Скорее, что-то вроде такого.

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

if (!( PIND & (1 << PIND3))){ // если кнопка не нажата
  PORTA = 0b01010101;
}else{
  sw++;
}
С опросом кнопок во время выполнения анимаций разобрались?
~=ieroglif=~
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Пн авг 31, 2015 09:14:42

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

Сообщение ~=ieroglif=~ »

COKPOWEHEU писал(а):Так у вас пропала вторая ветка. Она не нужна была? Скорее, что-то вроде такого.

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

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



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

А вот с опросом во время анимации не могу пока додуматься . . .
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение 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. Идея в том, чтобы каждая задача выполнялась максимально быстро, зато вызывалась с примерно равными интервалами. Иными словами, каждый вызов будет отображать не всю анимацию, а только один кадр. А между кадрами, когда задача просто крутится в цикле и ждет, обрабатывались кнопки или что-то еще.
Ответить

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