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

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 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 КБ) 422 скачивания
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Реклама
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

Сообщение CB1 »

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

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

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

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

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

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

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

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

Аlex писал(а):
~=ieroglif=~ писал(а):Проблема состоит в том что написал я код для Атмеги 32 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
А проблема то в чём ? Вы описали хотелку, а не проблему.
Ну так проблема и заключается в том ,что я не знаю как это сделать... :cry:
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

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

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

Сообщение Jack_A »

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

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

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

Сообщение Alkul »

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

Сообщение BOB51 »

схемно - вот так
схемс.GIF
(3.79 КБ) 835 скачиваний
программно - на свое усмотрение.
8)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

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

Сообщение CB1 »

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

Сообщение ~=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 раз для переключения первой программы. Весь код и скриншот эмуляции в Протэусе прилагаю. Заранее благодарю всех не равнодушных.[/b]

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

/*
 * 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 КБ) 403 скачивания
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

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

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


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

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

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



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

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

  while(1)
    {
		 if (PIND & (1 << PIND3))	
			  {
				sw++;
			  }
			
			switch (sw)
			{			
			case 1: .............	
Правильно ?
Ученье свет,а неученье - тьма... чуть свет и на работу ...
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

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

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

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

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

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

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

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

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

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

Сообщение 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»