Страница 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 по включению светодиодов,но хотел бы поставить туда кнопку которая по нажатию будет просто зажигать все светодиоды одновременно.
А проблема то в чём ? Вы описали хотелку, а не проблему.
Ну так проблема и заключается в том ,что я не знаю как это сделать...
Re: Помогите подключить кнопку
Добавлено: Вс июл 24, 2016 14:26:53
Аlex
~=ieroglif=~ писал(а):Ну так проблема и заключается в том ,что я не знаю как это сделать...
Вы не знаете как опросить ПИН микроконтроллера ?
https://yandex.ru/search/?lr=2&msid=146 ... 0%B0%20avr 
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 писал(а):А что периодически одну из пин можно использовать для ввода, при этом на горении светодиодов это будет незаметно
И как мне это сделать ?
Такую элементарную вещь не можете придумать?
Инициализируйте таймер на переполнение через 100 мс, внутри обработчика прерывания запомните текущее состояние соответствующего пина, переключите этот пин на вход, опросите пин, запомните состояние в переменной, переключите пин снова на выход, восстановите его исходное состояние и выходите из обработчика.
В основном цикле анализируйте значение переменной и принимайте решение в зависимости от того, нажата кнопка или нет.
Re: Помогите подключить кнопку
Добавлено: Пн июл 25, 2016 09:31:10
BOB51
схемно - вот так
программно - на свое усмотрение.

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 раз для переключения первой программы. Весь код и скриншот эмуляции в Протэусе прилагаю. Заранее благодарю всех не равнодушных.[/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;
}
}
}
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. Идея в том, чтобы каждая задача выполнялась максимально быстро, зато вызывалась с примерно равными интервалами. Иными словами, каждый вызов будет отображать не всю анимацию, а только один кадр. А между кадрами, когда задача просто крутится в цикле и ждет, обрабатывались кнопки или что-то еще.