tifaso Опубликовано 27 ноября, 2020 Поделиться Опубликовано 27 ноября, 2020 Уже достаточно долгое время пытаюсь понять как правильно сделать опрос кнопок по таймеру. Но из таймера нажатие кнопки отзывается один раз после запуска. Последующие разы кнопки не отзываются. #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) { } } Код всей программы копировать не стал так как он очень большой, но в таймере проверяется всего две кнопки. Возможно я тут не совсем верно записал код работы с таймером. Потому как я раньше просто с ним не сталкивался. Делаю на восьмой меге. Смотрел видеоуроки и делал по ним. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 27 ноября, 2020 Поделиться Опубликовано 27 ноября, 2020 В прерывании по таймеру нужно только инкрементировать некую переменную (например intTimerVar). Таким образом эта переменная будет изменяться например каждую миллисекунду. Далее в бесконечном цикле главной программы смотрится - изменилась ли эта таймерная переменная intTaimerVar, и если изменилась, то значит время пришло - пора идти смотреть что там с кнопками - запустить функцию xxxGetButton(). Функция xxxGetButton() должна строиться как конечный автомат для устранения дребезга. Ну и так далее... 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
tifaso Опубликовано 27 ноября, 2020 Автор Поделиться Опубликовано 27 ноября, 2020 @dasZebra Понятно сейчас попробую сделать. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
tifaso Опубликовано 27 ноября, 2020 Автор Поделиться Опубликовано 27 ноября, 2020 (изменено) @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); } } } Вот он код прошивки на этот раз весь. Изменено 27 ноября, 2020 пользователем tifaso 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 27 ноября, 2020 Поделиться Опубликовано 27 ноября, 2020 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. таким образом ничего не путается, не накладывается, не глючит, не тупит, легко масштабируется и тдю и тп как то так вобщем. Вобщем алгоритм этот был придуман наверно неким Цезарем, который был Гай Июлий и называется - "разделяй и влавствуй" */ } } 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 27 ноября, 2020 Автор Поделиться Опубликовано 27 ноября, 2020 @dasZebra Всё это как то выглядит сильно сложно, но я попробую завтра разобраться. Сейчас уже время позднее (12 ночи). 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 27 ноября, 2020 Поделиться Опубликовано 27 ноября, 2020 (изменено) 11 минут назад, tifaso сказал: @dasZebra Сейчас уже время позднее (12 ночи). 12? Офигеть.... у меня 18.30 Кривовато да, но не сложно. Изменено 27 ноября, 2020 пользователем dasZebra 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 Ну с таймером вроде бы разобрался, но это пока не совсем ясно. Чего то я тут запутался в построении кода кнопок может кто подскажет. Мне нужно сделать переключение одной кнопкой влево, а второй вправо. То есть сделать шаговый переключатель по менюшке светодиодом отображается индикация в какой точке я нахожусь. 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; } Я думал как то так, но оно не работает. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
mr_Kuzmich Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 Я бы делал это иначе - читал значение портов и двигал бы эти значения туда-сюда, попутно следя за флагами нуля и переноса. ЗЫ: А вот выражение if (btn==1) btn=1; мне вообще не понятно =( -1 Телеграмм канал для кладоискателей @ReviewdetectorChannel Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 (изменено) @mr_Kuzmich Чего то я не понял как это читать значение портов? Слишком это непонятно. Я даже не могу представить как это будет в коде. Там же проверяется нажатие кнопки и меняется переменная. Но почему оно не срабатывает я вообще не понимаю. Изменено 28 ноября, 2020 пользователем tifaso 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 1 час назад, tifaso сказал: . Но почему оно не срабатывает я вообще не понимаю. Упрости: у тебя есть ОДНА КНОПКА и ОДИН светодиод. Начал кнопку -светодиод включился. Нажал еще раз - выключился. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 (изменено) Нет ты не понял. У меня есть 2 кнопки и 11 светодиодов. Допустим на данный момент светит 4 светодиод нажимая одну кнопку четвёртый светодиод гаснет и включается 3 светодиод, а если нажать на другую кнопку, тогда четвёртый светодиод также гаснет и включается уже пятый светодиод. У меня уже всё это распаяно и подготовлено нужно только прошивку дописать в микросхему. Переделывать всё это очень сложно и долго. Изменено 28 ноября, 2020 пользователем tifaso 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Beliy_voron Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 Берешь переменную, например некую "i" и в начале инициализации задаешь ей некое значение, то значение которое является начальным для порядкового значения свечения светодиода. Значение этой переменной проверяешь в основном цикле и если оно изменилось, то изменяешь и вывод свечения светодиодов, например через "case" или же через "портянку " кода. К примеру при включении устройства начальное значение i=4; идет проверка этого значения и засвечивается светодиод номер четыре (все остальные гаснут). Этот цикл повторяется до тех пор пока программу не прервет прерывания от кнопок с помощью таймера. Или от одной кнопки или от другой. В подпрограмме прерывания с одной кнопки инкрементируем (увеличиваем на единицу) значение "i" , а в другой декрементируем значение "i". Таким образом по завершении подпрограммы прерывания переменная "i" обретет новое значения, в следствии чего основной код зажжет следующий (или предыдущий) светодиод. Такое решение "в лоб" является всего лишь алгоритмом. Его можно упростить вплоть до бинарных сдвигов в регистре порта, записи значения переменной "i" в флешь память МК (для запоминания последнего значения переменной и возврата к нему после включения устройства) , проверку значения действующего пина порта , но сложность понимания кода тогда увеличится. Есть ли смысл? Я делал одноразовое устройство на Mega8 в котором использовались два семисегментники и две кнопки по такому алгоритму. По нажатию на одну из них значение табло увеличивалось, а второй уменьшалось. Если подержать дольше то скорость изменения чисел увеличивалась (сделано для удобства). Основной код выполнял выдачу ШИМ генерацию на силовой транзистор. Проект был сделан для управления двигателем подачи проволоки в сварочном аппарате. Если заменить семисегментные индикаторы на светодиоды, то выйдет аналог необходимой тебе программы. 2 "Мы все учились понемногу, чему-нибудь и как-нибудь...") Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 @Beliy_voron Я сейчас вроде всё так и сделал, но оно хоть ты тресни ни в какую не работает. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 (изменено) 1 час назад, tifaso сказал: Переделывать всё это очень сложно и долго. Не надо ничего переделывать. Пусть все остается все надо. Просто для того что бы все хорошо разобраться, нужно свести задачу к минимальнвм функциональным единицам. Прошивку изменяешь последовательно. То есть сначала просто мигаешь светодиодом. Если все ок, мигаешь светодиодами "по кругу". Потом задецствуешь кнопку. Потом задействуешь другую. То есть от элементарного к простому, от простого к более сложному, и т.д. Изменено 28 ноября, 2020 пользователем dasZebra 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Beliy_voron Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 Самое главное в этой каше понять что такое прерывание и как оно работает. Как только удастся сделать подпрограмму прерывания (фактически программную или вообще аппаратную) тогда все пойдет как по маслу. А для этого нужно подключить таймер и в таймере каждые несколько десятков (сотен) микросекунд проверять - а не нажата ли наша кнопка? Обычно она не нажата и все гуд. Но только она нажалась, тогда надо что бы: и вся программа останавливается и исполняется то что в прерывании. А в прерывании у нас изменяется переменная. Ну изменилась и Бог с ней. Прерывание окончилось. Главный цикл снова запустился. Но в главном цикле уже наша переменная используется и уже измененная. Значит цикл будет работать по другому алгоритму, а по какому Вы уже напишете сами согласно Ваших нужд. 0 "Мы все учились понемногу, чему-нибудь и как-нибудь...") Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 (изменено) Прерывания я сделал они у меня работают проверил светодиодом. Тут скорей косяк именно с переключателем. Причем когда нажимаешь кнопку даже заметно что какие то действия выполняются, но я понял по какой то причине не происходит смены значений переменной при нажатии. Вот это до меня сейчас дошло и весь косяк в этом. Может я неверно переменную обьявил? Переменная 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); } } } Изменено 28 ноября, 2020 пользователем tifaso 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
dasZebra Опубликовано 28 ноября, 2020 Поделиться Опубликовано 28 ноября, 2020 2 часа назад, Beliy_voron сказал: А для этого нужно подключить таймер и в таймере каждые несколько десятков (сотен) микросекунд проверять - а не нажата ли наша кнопка? Обычно она не нажата и все гуд. Но только она нажалась, тогда надо что бы: и вся программа останавливается и исполняется то что в прерывании. Не надо так делать. 1 час назад, tifaso сказал: Весь код на данный момент: Ты думаешь кому то захочется изучать твой код? На вскидку: - в прерывании должно быть только инкрементирование переменной. В бесконечном цикле не должно быть никаких задержек. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 28 ноября, 2020 Автор Поделиться Опубликовано 28 ноября, 2020 2 часа назад, Beliy_voron сказал: Самое главное в этой каше понять что такое прерывание и как оно работает. Как только удастся сделать подпрограмму прерывания (фактически программную или вообще аппаратную) тогда все пойдет как по маслу. А для этого нужно подключить таймер и в таймере каждые несколько десятков (сотен) микросекунд проверять - а не нажата ли наша кнопка? Обычно она не нажата и все гуд. Но только она нажалась, тогда надо что бы: и вся программа останавливается и исполняется то что в прерывании. А в прерывании у нас изменяется переменная. Ну изменилась и Бог с ней. Прерывание окончилось. Главный цикл снова запустился. Но в главном цикле уже наша переменная используется и уже измененная. Значит цикл будет работать по другому алгоритму, а по какому Вы уже напишете сами согласно Ваших нужд. Согласен в принцепи так я всё и построил в своей программе и всё бы ничего работает но не работают только строки переключения переменной btn--; и btn++; никак только не пойму почему? Остальное же всё срабатывает так как и должно быть. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 29 ноября, 2020 Автор Поделиться Опубликовано 29 ноября, 2020 Замучился уже искать решение как сделать? Объявлял уже и переменные по разному, но либо не работает либо вообще в ошибку вылетает. Ни хочет он почему то из таймера переменную уменьшать либо прибавлять и сами строки переписывал по другому, но ничего не меняется. Так я и не могу сообразить как из таймера изменить значения переменной. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Beliy_voron Опубликовано 29 ноября, 2020 Поделиться Опубликовано 29 ноября, 2020 Попробуй вот этот файлик залить button.hex 0 "Мы все учились понемногу, чему-нибудь и как-нибудь...") Ссылка на комментарий Поделиться на другие сайты Поделиться
tifaso Опубликовано 29 ноября, 2020 Автор Поделиться Опубликовано 29 ноября, 2020 Можно код посмотреть? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Beliy_voron Опубликовано 29 ноября, 2020 Поделиться Опубликовано 29 ноября, 2020 Работает? 0 "Мы все учились понемногу, чему-нибудь и как-нибудь...") Ссылка на комментарий Поделиться на другие сайты Поделиться
IMXO Опубликовано 29 ноября, 2020 Поделиться Опубликовано 29 ноября, 2020 а смысл? Вы же все равно пользуетесь своим бредо генератором не взирая на то что вам пишут. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Beliy_voron Опубликовано 29 ноября, 2020 Поделиться Опубликовано 29 ноября, 2020 В принципе... если ресурсы МК больше не под что не будут заняты и не ограничиваясь памятью МК и если не лезть в дебри профессионального программирования, то код @tifaso будет работать. Туго конечно, но если бы его залить в реальное устройство и показать публике, то большинство не поняло бы что там на каждом моменте delay. 0 "Мы все учились понемногу, чему-нибудь и как-нибудь...") Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.