Перейти к содержанию

MEGA8 опрос кнопок по таймеру


tifaso

Рекомендуемые сообщения

Уже достаточно долгое время пытаюсь понять как правильно сделать опрос кнопок по таймеру. Но из таймера нажатие кнопки отзывается один раз после запуска. Последующие разы кнопки не отзываются.

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

ISR(TIMER1_OVF_vect)
{
	if (~PINB & (1<<0))
	{
       PORTD = 0b00000000;
  	}
	if (~PINB & (1<<1))
	{
  		PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
  	}
}

int main(void)
{
	DDRB = 0b11111100;
	DDRC = 0b1111111;
	DDRD = 0b11111111;
	PORTB = 0b00000000;
	PORTC = 0b0000000;
	PORTD = 0b00000000;
	
	TIMSK |= (1<<2);
	TCCR1B = 0b00000001;
	TCNT1 = 32768;
	sei();
    while(1)
    {
    }
}   
      
  

Код всей программы копировать не стал так как он очень большой, но в таймере проверяется всего две кнопки. Возможно я тут не совсем верно записал код работы с таймером. Потому как я раньше просто с ним не сталкивался. Делаю на восьмой меге. Смотрел видеоуроки и делал по ним. 

Ссылка на комментарий
Поделиться на другие сайты

В прерывании по таймеру нужно только инкрементировать некую переменную (например intTimerVar). Таким образом эта переменная будет изменяться например каждую миллисекунду. Далее в бесконечном цикле главной программы смотрится - изменилась ли эта таймерная переменная intTaimerVar, и если изменилась, то значит время пришло - пора идти смотреть что там с кнопками - запустить функцию xxxGetButton(). 

Функция xxxGetButton()  должна строиться как конечный автомат для устранения дребезга. Ну и так далее...

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

@dasZebra Сделал всё так как ты и сказал, но ничего не изменилось. Всё тоже самое.

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char menu=1;
volatile unsigned char btn=1;
volatile unsigned char timer=0;

ISR(TIMER1_OVF_vect)
{
	timer=1;
}

GetButton()
{
	if (~PINB & (1<<0))
	{
		PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
		PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
		PORTD = 0b00000000;
		
		if (btn==1)
		{
			PORTB |= (1<<2);
			btn=1;
			menu=1;
		}
		if (btn==2)
		{
			PORTB |= (1<<2);
			btn=1;
			menu=1;
		}
		if (btn==3)
		{
			PORTB |= (1<<3);
			btn=2;
			menu=2;
		}
		if (btn==4)
		{
			PORTB |= (1<<4);
			btn=3;
			menu=3;
		}
		if (btn==5)
		{
			PORTB |= (1<<5);
			btn=4;
			menu=4;
		}
		if (btn==6)
		{
			PORTB |= (1<<6);
			btn=5;
			menu=5;
		}
		if (btn==7)
		{
			PORTB |= (1<<7);
			btn=6;
			menu=6;
		}
		if (btn==8)
		{
			PORTC |= (1<<0);
			btn=7;
			menu=7;
		}
		if (btn==9)
		{
			PORTC |= (1<<1);
			btn=8;
			menu=8;
		}
		if (btn==10)
		{
			PORTC |= (1<<2);
			btn=9;
			menu=9;
		}
		if (btn==11)
		{
			PORTC |= (1<<3);
			btn=10;
			menu=10;
		}
		timer=0;
	}
	if (~PINB & (1<<1))
	{
		PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
		PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
		PORTD = 0b00000000;
		
		if (btn==11)
		{
			PORTC |= (1<<4);
			btn=11;
			menu=11;
		}
		if (btn==10)
		{
			PORTC |= (1<<4);
			btn=11;
			menu=11;
		}
		if (btn==9)
		{
			PORTC |= (1<<3);
			btn=10;
			menu=10;
		}
		if (btn==8)
		{
			PORTC |= (1<<2);
			btn=9;
			menu=9;
		}
		if (btn==7)
		{
			PORTC |= (1<<1);
			btn=8;
			menu=8;
		}	
		if (btn==6)
		{
			PORTC |= (1<<0);
			btn=7;
			menu=7;
		}
		if (btn==5)
		{
			PORTB |= (1<<7);
			btn=6;
			menu=6;
		}
		if (btn==4)
		{
			PORTB |= (1<<6);
			btn=5;
			menu=5;
		}
		if (btn==3)
		{
			PORTB |= (1<<5);
			btn=4;
			menu=4;
		}
		if (btn==2)
		{
			PORTB |= (1<<4);
			btn=3;
			menu=3;
		}
		if (btn==1)
		{
            PORTB |= (1<<3);
            btn=2;
            menu=2;
		}
		timer=0;
	}
}

int main(void)
{
	DDRB = 0b11111100;
	DDRC = 0b1111111;
	DDRD = 0b11111111;
	PORTB = 0b00000000;
	PORTC = 0b0000000;
	PORTD = 0b00000000;
	
	TIMSK |= (1<<2);
	TCCR1B = 0b00000001;
	TCNT1 = 54613;
	sei();
	
    while(1)
    {
		if (timer==1)
		{
			GetButton();
		}
		
        if (menu==1)
        {
	        PORTD |= (1<<0);
	        PORTD &= ~((1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<1);
	        PORTD &= ~((1<<0)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<2);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<4);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<5);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<6);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5));
	        _delay_ms(300);
        }
        if (menu==2)
        {
	        PORTD |= (1<<0);
	        _delay_ms(300);
	        PORTD |= (1<<1);
	        _delay_ms(300);
	        PORTD |= (1<<2);
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD |= (1<<4);
	        _delay_ms(300);
	        PORTD |= (1<<5);
	        _delay_ms(300);
	        PORTD |= (1<<6);
	        _delay_ms(300);
	        PORTD &= ~(1<<0);
	        _delay_ms(300);
	        PORTD &= ~(1<<1);
	        _delay_ms(300);
	        PORTD &= ~(1<<2);
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
	        _delay_ms(300);
	        PORTD &= ~(1<<4);
	        _delay_ms(300);
	        PORTD &= ~(1<<5);
	        _delay_ms(300);
	        PORTD &= ~(1<<6);
        }
        if (menu==3)
        {
	        PORTD |= ((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD |= ((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD |= ((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD &= ~((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD &= ~((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD &= ~((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
	        _delay_ms(300);
        }
        if (menu==4)
        {
	        PORTD |= ((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD |= ((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD &= ~((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD &= ~((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD |= ((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD &= ~((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
        }
    }
}

Вот он код прошивки на этот раз весь.

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

2 часа назад, tifaso сказал:

Вот он код прошивки на этот раз весь.

Большая портянка. Во первых нельзя пихать делай в бесконечный цикл. Во вторых.... 

вот погляди просто кнопки   (там правда косяк - 8ми битный счетчик, ну да ладно):

/*
 * Atmega32  Buttons
 */ 

/* 8ми битный счетчик: нужно использовать для коротких отсчетов. */
#define F_CPU 8000000UL       // Частота кварца
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//----------------------------------------

#define PIN_BUTTONS (PIND&=(1<<7)) && (PIND&=(1<<6)) && (PIND&=(1<<5)) && (PIND&=(1<<4)) && (PIND&=(1<<3))  // сюда подключены кнопки
// так же нужно бы определить порт
 
unsigned char char_sys_20ms_beat=0;                // Системный таймер 
unsigned char DelayReadBUTTON=6 , DelayClickBUTTON =3;   // Стартовые значения задержек для процессов
char charNumberClickBUTTON=0;                    // Номер нажатой кнопки

ISR (TIMER0_COMP_vect)                            // Вектор прерывания первого 8ми битного таймера
{
    cli();
    /* прерывание будет вызываться каждые 4 ms но ТРЕБУЕТСЯ каждые 20 ms*/
    static char chat_timer1_inkrement =0; 
    TCNT0 = 0;
    chat_timer1_inkrement++;        //прерывание увеличивает внутрений подсчетчик
    if (chat_timer1_inkrement > 4)  // и когда он добирается до 5ти то обнуляется увеличивая int_sys_20ms_beat каждые 0.02 сек
     {
        chat_timer1_inkrement = 0;
         char_sys_20ms_beat++;       // вот оно
     }
    sei();
}

char Delay_8bit_count(unsigned char Delay_1)    // расчитывает значение для 8мити битного таймера, с которым должен совпасть системый таймер
{
    unsigned char newDelay=0;                   // локальная переменная 
    newDelay = char_sys_20ms_beat + Delay_1;   // новое значение
    return newDelay;
}


char ReadBUTTONs(void)                          // BUTTONs ЧТЕНИЕ СОСТОЯНИЯ
{
    static char steps=0;   // переменная, запоминающая состояние автомата 
     char ret_BUTTON=0;
    switch (steps)
    {
        case 0:
        {
            if (PIN_BUTTONS) {return ret_BUTTON;}  
            steps=1;    
        }
        case 1:
        {
            if (PIN_BUTTONS) {return ret_BUTTON;}  
            steps = 2;
        }
        case 3:
        {
            if (PIN_BUTTONS) { steps = 0; return ret_BUTTON; }  
                if (!(PIND&=(1<<7)))  { ret_BUTTON = 1;  steps = 0; return ret_BUTTON; }
                if (!(PIND&=(1<<6)))  { ret_BUTTON = 2;  steps = 0; return ret_BUTTON; }
                if (!(PIND&=(1<<5)))  { ret_BUTTON = 3;  steps = 0; return ret_BUTTON; }
                if (!(PIND&=(1<<4)))  { ret_BUTTON = 4;  steps = 0; return ret_BUTTON; }
                if (!(PIND&=(1<<3)))  { ret_BUTTON = 5;  steps = 0; return ret_BUTTON; }
        }
    default: return ret_BUTTON;
    }
}
void ButtonClickProcessings(void)              // Buttons РЕАКЦИЯ
{
    if (!charNumberClickBUTTON) 
    {
        return;
    }
    if (charNumberClickBUTTON == 1)
    {
        // вызвать какую нужно функцию, что бы выполнить что нужно
        // или выставить ФЛАГ, что бы нужная функция выполнила что нужно
        charNumberClickBUTTON = 0;
        return;
    }
    if (charNumberClickBUTTON == 2)
    {
        // вызвать какую нужно функцию, что бы выполнить что нужно
        // или выставить ФЛАГ, что бы нужная функция выполнила что нужно
        charNumberClickBUTTON = 0;
        return;
    }
    if (charNumberClickBUTTON == 3 )
    {
        // вызвать какую нужно функцию, что бы выполнить что нужно
        // или выставить ФЛАГ, что бы нужная функция выполнила что нужно
        charNumberClickBUTTON = 0;
        return;
    }
    if (charNumberClickBUTTON == 4)
    {
        // вызвать какую нужно функцию, что бы выполнить что нужно
        // или выставить ФЛАГ, что бы нужная функция выполнила что нужно
        charNumberClickBUTTON = 0;
        return;
    }
    if (charNumberClickBUTTON == 5)
    {
        // вызвать какую нужно функцию, что бы выполнить что нужно
        // или выставить ФЛАГ, что бы нужная функция выполнила что нужно
        charNumberClickBUTTON = 0;
        LCD_PrintStr1();
        return;
    }
    
}
int main(void)
{

/*Инициализация первого 8ми биттный таймер*/
 TCCR0=(1<<CS02);            // делитель на 256: 8 000 000/256=31250 => 1/31250=0.000032 сек
 TIMSK|=(1<<OCIE0);            // добавляет в общий для всех таймеров регистр разрешение прерывания по стравнению с OCR0
 OCR0 = 0x7D;                //  0.000032сек х 125 прерывание будет происходить каждые 4ms (0.004)
/*Конец инициализации первого 8ми битного таймера*/

  
 /*К данному порту подключены кнопки*/
PORTD=0;  //  порт глушится в Z состояние - прописать в дефайн
  
sei();              //Разрешение прерываний
/* Внимание!!! функцию delay() (например для задания задержек при инициализации перефирии) можно использовать только до этого места */    
    while(1)
    {
           
        //Считывание нажатия кнопок =>
        if (DelayReadBUTTON == char_sys_20ms_beat)     // Вызов функции через заданный интервал
        {
            DelayReadBUTTON =  Delay_8bit_count(8);    // Расчет значения следующего вызова
             charNumberClickBUTTON= ReadBUTTONs();     // Чтение кнопок
         }
        
        if (DelayClickBUTTON == char_sys_20ms_beat)    // Вызов функции через заданный интервал
        {
            DelayClickBUTTON =  Delay_8bit_count(3);   // Расчет значения следующего вызова
            ButtonClickProcessings();                  // Выполнение нажатия кнопки
        } 
        
        /*Как это работает:
        С заданным интервалом  запускается функция ReadBUTTONs() чтения состояния порта, 
        которая выполняется за три шага (), и если до третьего шага дошло (антидребезг), то она вывешивает номер нажатой кнопки
        
        Параллельно, со своим интервалом запускается функция чтения переменной, в которуу записывается номер нажатой кнопки,
        и если обнаруживается значение, то вызывается нужная функция или наример переменной написатьхyйнаэкране присваивается 1
        
        Параллельно, со своим интервалом запускается функция, которая смотрит, а не равна ли единице переменная написатьхyйнаэкране
        и если равна, то функция выводит на экране заветный Hello World.
        
        таким образом ничего не путается, не накладывается, не глючит, не тупит, легко масштабируется и тдю и тп
        
        как то так вобщем. Вобщем алгоритм этот был придуман наверно неким Цезарем, который был Гай Июлий и называется
         - "разделяй и влавствуй"
           
        
        */
        
    }
}

 

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

11 минут назад, tifaso сказал:

@dasZebra Сейчас уже время позднее (12 ночи). 

12? Офигеть.... у меня 18.30:D

 

Кривовато да, но не сложно. 

Изменено пользователем dasZebra
Ссылка на комментарий
Поделиться на другие сайты

Ну с таймером вроде бы разобрался, но это пока не совсем ясно. Чего то я тут запутался в построении кода кнопок может кто подскажет. Мне нужно сделать переключение одной кнопкой влево, а второй вправо. То есть сделать шаговый переключатель по менюшке светодиодом отображается индикация в какой точке я нахожусь.

	if (~PINB & (1<<0))
	{
		PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
		PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
		PORTD = 0b00000000;
		btn--;
		if (btn==0)
		{
			btn=1;
		}
	}
	if (~PINB & (1<<1))
	{
		PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
		PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
		PORTD = 0b00000000;
		btn++;
		if (btn==12)
		{
			btn==11;
		}
	}

	if (btn==11)
	{
		PORTC |= (1<<4);
		btn=11;
		menu=11;
	}
	if (btn==10)
	{
		PORTC |= (1<<3);
		btn=10;
		menu=10;
	}
	if (btn==9)
	{
		PORTC |= (1<<2);
		btn=9;
		menu=9;
	}
	if (btn==8)
	{
		PORTC |= (1<<1);
		btn=8;
		menu=8;
	}
	if (btn==7)
	{
		PORTC |= (1<<0);
		btn=7;
		menu=7;
	}
	if (btn==6)
	{
		PORTB |= (1<<7);
		btn=6;
		menu=6;
	}
	if (btn==5)
	{
		PORTB |= (1<<6);
		btn=5;
		menu=5;
	}
	if (btn==4)
	{
		PORTB |= (1<<5);
		btn=4;
		menu=4;
	}
	if (btn==3)
	{
		PORTB |= (1<<4);
		btn=3;
		menu=3;
	}
	if (btn==2)
	{
		PORTB |= (1<<3);
		btn=2;
		menu=2;
	}
	if (btn==1)
	{
		PORTB |= (1<<2);
		btn=1;
		menu=1;
	}

Я думал как то так, но оно не работает. 

Ссылка на комментарий
Поделиться на другие сайты

Я бы делал это иначе - читал значение портов и двигал бы эти значения туда-сюда, попутно следя за флагами нуля и переноса.

ЗЫ: А вот выражение if (btn==1) btn=1; мне вообще не понятно =(

Телеграмм канал для кладоискателей @ReviewdetectorChannel

Ссылка на комментарий
Поделиться на другие сайты

@mr_Kuzmich Чего то я не понял как это читать значение портов? Слишком это непонятно. Я даже не могу представить как это будет в коде. Там же проверяется нажатие кнопки и меняется переменная. Но почему оно не срабатывает я вообще не понимаю.

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

1 час назад, tifaso сказал:

. Но почему оно не срабатывает я вообще не понимаю.

Упрости: у тебя есть ОДНА КНОПКА и ОДИН светодиод. Начал кнопку -светодиод включился. Нажал еще раз - выключился. 

 

Ссылка на комментарий
Поделиться на другие сайты

Нет ты не понял. У меня есть 2 кнопки и 11 светодиодов. Допустим на данный момент светит 4 светодиод нажимая одну кнопку четвёртый светодиод гаснет и включается 3 светодиод, а если нажать на другую кнопку, тогда четвёртый светодиод также гаснет и включается уже пятый светодиод. У меня уже всё это распаяно и подготовлено нужно только прошивку дописать в микросхему. Переделывать всё это очень сложно и долго. 

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

Берешь переменную, например некую "i"  и  в начале инициализации  задаешь ей некое  значение, то значение которое является начальным для порядкового значения свечения светодиода. Значение этой переменной проверяешь в основном цикле и если оно изменилось, то изменяешь и вывод свечения светодиодов, например через "case" или же через "портянку " кода. К примеру при включении устройства начальное значение 

i=4; 

идет проверка этого значения и засвечивается светодиод номер четыре (все остальные гаснут). 

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

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

Есть ли смысл?

Я делал одноразовое устройство на Mega8 в котором использовались два семисегментники и две кнопки по такому алгоритму.  По нажатию на одну из них значение табло увеличивалось, а второй уменьшалось. Если подержать дольше то скорость изменения  чисел увеличивалась (сделано для удобства). Основной код выполнял выдачу ШИМ генерацию на силовой транзистор. Проект был сделан для управления двигателем подачи проволоки в сварочном аппарате. 

Если заменить семисегментные индикаторы на светодиоды, то выйдет аналог необходимой тебе программы.  

"Мы все учились понемногу, чему-нибудь и как-нибудь...")

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, tifaso сказал:

Переделывать всё это очень сложно и долго. 

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

То есть сначала просто мигаешь светодиодом. Если все ок, мигаешь светодиодами "по кругу". Потом задецствуешь кнопку. Потом задействуешь другую. То есть от элементарного к простому, от простого к более сложному, и т.д.

Изменено пользователем dasZebra
Ссылка на комментарий
Поделиться на другие сайты

Самое главное в этой каше понять что такое прерывание и как оно работает. Как только удастся сделать подпрограмму прерывания (фактически программную или вообще аппаратную) тогда все пойдет как по маслу. 

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

и вся программа останавливается и исполняется то что в прерывании. 

А в прерывании у нас изменяется переменная. Ну изменилась и Бог с ней. Прерывание окончилось. Главный цикл снова запустился. Но в главном цикле уже наша переменная используется и уже  измененная. Значит цикл будет работать по другому алгоритму, а по какому Вы уже напишете сами согласно Ваших нужд. 

"Мы все учились понемногу, чему-нибудь и как-нибудь...")

Ссылка на комментарий
Поделиться на другие сайты

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

Переменная btn и есть стартовая переменная которая управляет переключателем

Весь код на данный момент:

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char menu=1;
volatile unsigned char btn=1;

ISR(TIMER1_OVF_vect)
{
    	if (~PINB & (1<<0))
    	{
	    	PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
	    	PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
	    	PORTD = 0b00000000;
	    	btn--;
	    	if (btn==0)
	    	{
		    	btn=1;
	    	}
    	}
    	if (~PINB & (1<<1))
    	{
	    	PORTB &= ~((1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7));
	    	PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4));
	    	PORTD = 0b00000000;
	    	btn++;
	    	if (btn==12)
	    	{
		    	btn=11;
	    	}
    	}	
}

int main(void)
{
	DDRB = 0b11111100;
	DDRC = 0b1111111;
	DDRD = 0b11111111;
	PORTB = 0b00000000;
	PORTC = 0b0000000;
	PORTD = 0b00000000;
	
	TIMSK |= (1<<2);
	TCCR1B = 0b00000001;
	TCNT1 = 54613;
	sei();
	
    while(1)
    {
    	if (btn==11)
    	{
    		PORTC |= (1<<4);
    		menu=11;
    	}
    	if (btn==10)
    	{
    		PORTC |= (1<<3);
    		menu=10;
    	}
    	if (btn==9)
    	{
    		PORTC |= (1<<2);
    		menu=9;
    	}
    	if (btn==8)
    	{
    		PORTC |= (1<<1);
    		menu=8;
    	}
    	if (btn==7)
    	{
    		PORTC |= (1<<0);
    		menu=7;
    	}
    	if (btn==6)
    	{
    		PORTB |= (1<<7);
    		menu=6;
    	}
    	if (btn==5)
    	{
    		PORTB |= (1<<6);
    		menu=5;
    	}
    	if (btn==4)
    	{
    		PORTB |= (1<<5);
    		menu=4;
    	}
    	if (btn==3)
    	{
    		PORTB |= (1<<4);
    		menu=3;
    	}
    	if (btn==2)
    	{
    		PORTB |= (1<<3);
    		menu=2;
    	}
    	if (btn==1)
    	{
    		PORTB |= (1<<2);
    		menu=1;
    	}		
		
        if (menu==1)
        {
	        PORTD |= (1<<0);
	        PORTD &= ~((1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<1);
	        PORTD &= ~((1<<0)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<2);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<4);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<5)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<5);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<6));
	        _delay_ms(300);
	        PORTD |= (1<<6);
	        PORTD &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5));
	        _delay_ms(300);
        }
        if (menu==2)
        {
	        PORTD |= (1<<0);
	        _delay_ms(300);
	        PORTD |= (1<<1);
	        _delay_ms(300);
	        PORTD |= (1<<2);
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD |= (1<<4);
	        _delay_ms(300);
	        PORTD |= (1<<5);
	        _delay_ms(300);
	        PORTD |= (1<<6);
	        _delay_ms(300);
	        PORTD &= ~(1<<0);
	        _delay_ms(300);
	        PORTD &= ~(1<<1);
	        _delay_ms(300);
	        PORTD &= ~(1<<2);
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
	        _delay_ms(300);
	        PORTD &= ~(1<<4);
	        _delay_ms(300);
	        PORTD &= ~(1<<5);
	        _delay_ms(300);
	        PORTD &= ~(1<<6);
        }
        if (menu==3)
        {
	        PORTD |= ((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD |= ((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD |= ((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD &= ~((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD &= ~((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD &= ~((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
	        _delay_ms(300);
        }
        if (menu==4)
        {
	        PORTD |= ((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD |= ((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD &= ~((1<<0)|(1<<6));
	        _delay_ms(300);
	        PORTD &= ~((1<<2)|(1<<4));
	        _delay_ms(300);
	        PORTD |= ((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD |= (1<<3);
	        _delay_ms(300);
	        PORTD &= ~((1<<1)|(1<<5));
	        _delay_ms(300);
	        PORTD &= ~(1<<3);
        }
    }
}

 

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Beliy_voron сказал:

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

и вся программа останавливается и исполняется то что в прерывании. 

Не надо так делать. 

 

1 час назад, tifaso сказал:

Весь код на данный момент:

Ты думаешь кому то захочется изучать твой код? 

На вскидку: 

- в прерывании должно быть только инкрементирование переменной.

В бесконечном цикле не должно быть никаких задержек. 

 

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Beliy_voron сказал:

Самое главное в этой каше понять что такое прерывание и как оно работает. Как только удастся сделать подпрограмму прерывания (фактически программную или вообще аппаратную) тогда все пойдет как по маслу. 

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

и вся программа останавливается и исполняется то что в прерывании. 

А в прерывании у нас изменяется переменная. Ну изменилась и Бог с ней. Прерывание окончилось. Главный цикл снова запустился. Но в главном цикле уже наша переменная используется и уже  измененная. Значит цикл будет работать по другому алгоритму, а по какому Вы уже напишете сами согласно Ваших нужд. 

Согласен в принцепи так я всё и построил в своей программе и всё бы ничего работает но не работают только строки переключения переменной btn--; и btn++; никак только не пойму почему? Остальное же всё срабатывает так как и должно быть.

Ссылка на комментарий
Поделиться на другие сайты

Замучился уже искать решение как сделать? Объявлял уже и переменные по разному, но либо не работает либо вообще в ошибку вылетает. Ни хочет он почему то из таймера переменную уменьшать либо прибавлять и сами строки переписывал по другому, но ничего не меняется. Так я и не могу сообразить как из таймера изменить значения переменной.

Ссылка на комментарий
Поделиться на другие сайты

В принципе... если ресурсы МК больше не под что не будут заняты и не ограничиваясь памятью МК и если не лезть в дебри профессионального программирования, то код @tifaso  будет работать. Туго конечно, но если бы его залить в реальное устройство и показать публике, то большинство не поняло бы что там на каждом моменте delay. :)

"Мы все учились понемногу, чему-нибудь и как-нибудь...")

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...