Обсуждаем контроллеры компании Atmel.
Ответить

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 15, 2017 11:07:10

2. переменная off обнуляется в тексте программы при каждом нажатии на любую кнопку.
А если кнопку не нажимаем долгое время, а "off" так и крутится постоянно - это нормально будет?
опять перепутал знак "=" и "=="
Для таких случаев приучи себя писать не "if( off == 2 )", а "if( 2 == off )".
На этапе компиляции сразу отследиться.

Re: Дисковый номеронабиратель и семисегментник

Пн ноя 20, 2017 17:51:36

2. переменная off обнуляется в тексте программы при каждом нажатии на любую кнопку.
А если кнопку не нажимаем долгое время, а "off" так и крутится постоянно - это нормально будет?


ну вроде я так понял что это не на что не влияет.)) или я не прав?

Добавлено after 8 hours 20 minutes 33 seconds:
Друзья, помогите пожалуйста. Стою на асфальте в лыжи обутый то ли лыжи не едут, то ли я стебанутый...

в общем, почти все работало. занимался отладкой уже на железе.... и тут как-то раз и перестало... вообще перестало..... то ли в проге где-то накосячил, то ли схему на макетке неправильно собрал...ТРИ атмеги не работают......у дочи др через 10 дней, боюсь, без вашей помощи не обойдусь....а еще плату травить....

теперь много буковок, кому лень читать ,я не обижусь, просто почти отчаялся....

1. шью китайским USBASP.
2. микруху ставлю в китайскую платочку с мин. обвязкой
СпойлерИзображение

3. МК пишется, верификация без ошибок. но на всех трех микрухак на PС4 почему-то всегда висит 0". Остальные подтяжки работают. если подключить кноки в соответствии со схемой, то мк на нажатие кнопок не реагирует.
3. не знаю могло ли повлиять, но несколько раз я вхерачивал питание в плату, когда был подключен разъем для программирования т.е. 5в с USB и 5в с БП.
5. пробовал сегодня записать эти же контроллеры программатором AUTOPROG, но изменений нет, купил новый МК, но еще не пробовал записать его.
6. если закоментить часть текста проги (условия где встречается PC4) и строчку "sei(); " то прога частично начинает работать.
Ну и самое интересное
7. в PROTEUS все работает как надо

что я могу делать не так? ((

схема
СпойлерИзображение

текст программы(коменты могут не соответствовать из-за копипаста):
Спойлер#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
#include <util/delay.h>

volatile unsigned char off=0; //для выключения всего
unsigned char flag=0; //флаг нажатой кнопки светофора
unsigned char cifra=0; //для семисегментника
unsigned char svet=0; //для светофора
unsigned char vykl=0; //для выключателя
unsigned char rozetka=0; //для розетки
unsigned char sv=0;
unsigned char mag=0;
unsigned char SEGMENTE[] =
{// gfedcba
0b11111111,
0b11000000, // 0
0b11111001, // 1
0b10100100, // 2
0b10110000, // 3
0b10011001, // 4
0b10010010, // 5
0b10000010, // 6
0b11111000, // 7
0b10000000, // 8
0b10010000, // 9
};

ISR( TIMER1_OVF_vect )
{
off++;
if (8 == off)
{
PORTD &= ~(1<<6); //Выключить розетку (Вентилятор)
}
if (15 == off)
{
PORTA |= 1<<7; //погасить семисегментник
PORTB = 0b11111111; //погасить светофор
}
if (28 == off)
{
PORTD |= 1<<7;//выключить Свет
}
}

ISR (INT2_vect)
{
_delay_ms(50);
off=0;
cifra = TCNT0; //переменной присвоить значение счетчика
if (cifra>0 && cifra<11) // если цифра >0 и <10
{
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру
cifra=0; //обнулить переменную
}
else
{
if (11 == cifra) //если переменная равна 10
{
cifra=1; //обнулить переменную
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру 0
}
}
PORTA &= ~(1<<7);// зажечь семисегментник
cifra=0; //обнулить переменную
TCNT0 = 0;
}

int main(void)
{
DDRA = 0b11111111; // порты на выход
PORTA = 0b11111111; // подтягиваем к 1
DDRB = 0b11111010;
PORTB = 0b11111111; //подтягивем к 1
DDRC = 0b00000000;
PORTC = 0b11111111; // подтягиваем к 1
DDRD = 0b11000100;
PORTD = 0b10111011;

GICR |= (1<<INT2); //разрешить внешние прерывания инт2
MCUCSR |=(1<<ISC2);//по спадающему фронту INT2

TCNT0 = 0; //установка таймера в ноль
TCCR0 |=(1<<CS02)|(1<<CS01)|(1<<CS00); //таймер от внеш. источника по переднему фронту для номеронабирателя

TIMSK |=(1<<TOIE1); //таймер по переполнению
TCCR1B |=(1<<CS11)|(1<<CS10); //делитель 64
sei(); //разрешить общее прерывание


while (1)
{
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<0))) // если PC0 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<0)))
{
PORTB &= ~(1<<1); // Установить на PB1 = 0
PORTB |= 1<<3; // Установить на PB3 = 1
}
while (!(PINC & (1<<0)))
{
}
}
//----------
if (!(PINC & (1<<2)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<2)))
{
PORTB |= 1<<1;
PORTB &= ~(1<<3);
}
while (!(PINC & (1<<2)))
{
}
}
//----------
if (!(PINC & (1<<1)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<1)))
{
PORTB &= ~(1<<3);
PORTB &= ~(1<<1);
}
while (!(PINC & (1<<1)))
{
}
}
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<3))) // если PC0 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<3)))
{
PORTB &= ~(1<<4); // Установить на PB1 = 0
PORTB |= 1<<5; // Установить на PB3 = 1
}
while (!(PINC & (1<<3)))
{
}
}
//----------
if (!(PINC & (1<<5)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<5)))
{
PORTB |= 1<<4;
PORTB &= ~(1<<5);
}
while (!(PINC & (1<<5)))
{
}
}
//----------
if (!(PINC & (1<<4)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<4)))
{
PORTB &= ~(1<<4);
PORTB &= ~(1<<5);
}
while (!(PINC & (1<<4)))
{
}
}
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<6))) // если PC6 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<6)))
{
PORTB &= ~(1<<6); // Установить на PB6 = 0
PORTB |= 1<<7; // Установить на PB7 = 1
}
while ((!PINC & (1<<6)))
{
}
}
//----------
if (!(PIND & (1<<0)))
{
_delay_ms(50);
off=0;
if (!(PIND & (1<<0)))
{
PORTB |= 1<<6;
PORTB &= ~(1<<7);
}
while (!(PIND & (1<<0)))
{
}
}
//----------
if (!(PINC & (1<<7)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<7)))
{
PORTB &= ~(1<<6);
PORTB &= ~(1<<7);
}
while (!(PINC & (1<<7)))
{
}
}
//----------. ЗАМОК-----------------------------
if ((PINB & (1<<1)) && (!(PINB & (1<<3))) && (!(PINB & (1<<4))) && (!(PINB & (1<<5))) && (!(PINB & (1<<6))) && (PINB & (1<<7)))
{
PORTD |= 1<<2;
}
else
{
PORTD &= ~(1<<2);
}
//----------
if (!(PIND & (1<<1)))
{

if (0==rozetka)
{
off=0;
_delay_ms(50);
rozetka=1;
PORTD |= 1<<6;
}

}
else
{
PORTD &= ~(1<<6);
rozetka=0;
}
//---------- СВЕТА-------------
if (!(PIND & (1<<3)))
{
if (0==vykl)
{
off=0;
_delay_ms(50);
vykl=1;
PORTD &= ~(1<<7);
}

}
else
{
PORTD |= 1<<7;
vykl=0;
}
//---------- СВЕТОФОРА-------------------
if (!(PIND & (1<<4)))
{
off=0;
_delay_ms(50);
if (!(PIND & (1<<4)))
{
sv++; //переменной +1
switch (sv)
{
case 1: PORTB &= ~(1<<1);PORTB &= ~(1<<4);PORTB &= ~(1<<6);PORTB |= 1<<3;PORTB |= 1<<5;PORTB |= 1<<7; break;
case 2: PORTB &= ~(1<<1);PORTB &= ~(1<<4);PORTB &= ~(1<<6);PORTB &= ~(1<<3);PORTB &= ~(1<<5);PORTB &= ~(1<<7); break;
case 3: PORTB &= ~(1<<3);PORTB &= ~(1<<5);PORTB &= ~(1<<7);PORTB |= 1<<1;PORTB |= 1<<4;PORTB |= 1<<6;sv=0;break;
default: ;
}
}
while (!(PIND & (1<<4)))
{
}

}
//---------- ТЕЛЕФОНА------------------------------
if (!(PIND & (1<<5)))
{
off=0;
_delay_ms(50);
if (!(PIND & (1<<5)))
{
cifra++;
if (cifra>0 && cifra<11) // если цифра >0 и <10
{
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру
PORTA &= ~(1<<7);// зажечь семисегментник
}
else
{
if (11==cifra) //если переменная равна 10
{
cifra=1; //обнулить переменную
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру 0
PORTA &= ~(1<<7);// зажечь семисегментник
cifra=1;
}
}
}
while (!(PIND & (1<<5)))
{
}

}
}
}

Re: Дисковый номеронабиратель и семисегментник

Пн ноя 20, 2017 20:11:04

ну вроде я так понял что это не на что не влияет.)) или я не прав?
Угу, если "не влияет" означает постоянные периодические срабатывания
PORTA |= 1<<7; //погасить семисегментник
PORTB = 0b11111111; //погасить светофор
PORTD |= 1<<7;//выключить Свет

вообще перестало..... то ли в проге где-то накосячил,
Именно для таких случаев придумана "система контроля версий" или хотя бы ежедневные бекапы проекта - чтобы всегда можно было откатиться на шаг назад или до прошлого рабочего состояния.
ТРИ атмеги не работают......
Не вижу кварца у атмеги. Правильно ли она сконфигурирована (FUSE) на работу от внутреннего RC-генератора?
Подано ли питание не только на VCC, но и на AVCC?

Какая у тебя стоит ATMEGA? На схеме фиг разглядишь, по распиновке смахивает на DIP-40 корпус Atmaga32 или 8535.
Если Аtmega32, то на PC2-PC5 висит JTAG. Смотри FUSE-бит "JTAGEN" - по умолчанию он активен. "Default Value 0 (programmed, JTAG enabled)"
6. если закоментить часть текста проги (условия где встречается PC4) и строчку "sei(); " то прога частично начинает работать.
А если только прерывания не разрешать - начинает "частично работать"?

ISR (INT2_vect)
{
_delay_ms(50);
Как я уже говорил - не люблю повторяться. (с)
Но, на кой хрен в прерывании задержка?! :shock:
Попробовать PB0 и PB2 подтянуть резистором снаружи, всё же может внутренней подтяжки не хватать.
Это, кстати, и к PC4 относится - если подключить внешнюю подтяжку, там будет "1"? При условии, что там точно нет JTAG.

Re: Дисковый номеронабиратель и семисегментник

Вт ноя 21, 2017 12:56:44

mas123 писал(а):Угу, если "не влияет" означает постоянные периодические срабатывания
Цитата:
PORTA |= 1<<7; //погасить семисегментник
PORTB = 0b11111111; //погасить светофор
PORTD |= 1<<7;//выключить Свет
Я понял о чем Вы говорите, но не пойму что Вы этим хотите сказать. Физически же ничего не будет происходить. крутится и крутится эта переменная... что-то нажали ---> прошло время ---> "PORTB = 0b11111111" --> все погасло , мы ничего не делаем и через время произошло тоже самое,т.е. как было погашено так и осталось. Если Вы имеете ввиду что это не по фэншую, тогда надо переделывать алгоритм, чтоб как-то счетчик останавливался на время простоя, на это у меня ума не хватает). максиму что можно от меня добиться это добавить условие в прерывание типо:
if (<все включено>)
{<все выключить>;}
else
{}
Если так правильнее то сделаю, только скажите))
mas123 писал(а):Именно для таких случаев придумана "система контроля версий" или хотя бы ежедневные бекапы проекта - чтобы всегда можно было откатиться на шаг назад или до прошлого рабочего состояния.
Обязательно учту на будущее!
mas123 писал(а):Не вижу кварца у атмеги. Правильно ли она сконфигурирована (FUSE) на работу от внутреннего RC-генератора?
Подано ли питание не только на VCC, но и на AVCC?

Какая у тебя стоит ATMEGA? На схеме фиг разглядишь, по распиновке смахивает на DIP-40 корпус Atmaga32 или 8535.
Если Аtmega32, то на PC2-PC5 висит JTAG. Смотри FUSE-бит "JTAGEN" - по умолчанию он активен. "Default Value 0 (programmed, JTAG enabled)"
Atmega16. работает от внутреннего кварца
Вы ЧЕЛОВЕК! Спасибо огромное! действительно проблемы была в FUSE, галочка JTAG... в самом начале я её убирал, и настройки сохранились, а потом начал работать на другом компе и там прога с фьюзами по умолчанию и галочка стоит((((( в общем как Вы и написали.

mas123 писал(а):Hiperboloyd писал(а):
ISR (INT2_vect)
{
_delay_ms(50);
Как я уже говорил - не люблю повторяться. (с)
Убрал!

Всё вроде заработало! еще раз огромное спасибо!
если объясните первый вопрос, по поводу выключения и переменной off, как там лучше сделать - будет очень здорово), ну а если надоело ковыряться моей фигне, ничего страшного!

Re: Дисковый номеронабиратель и семисегментник

Вт ноя 21, 2017 14:41:24

можно вместо: off ;
написать: off =(~off)? 1:0;
если офф не 0xff к нему прибавится 1, иначе 0.
так переменная дойдёт до 255 и там и останется. т.е. в условие сброса надо вписать 254 а не 255.

Re: Дисковый номеронабиратель и семисегментник

Вт ноя 21, 2017 16:20:40

Физически же ничего не будет происходить. крутится и крутится эта переменная...
Если вначале включается что-то из серии "погасить по таймеру", а лишь потом обнуляется "off", то возможна ситуация мгновенного выключения включенного, т.к. таймер "сработал".
тогда надо переделывать алгоритм, чтоб как-то счетчик останавливался на время простоя, на это у меня ума не хватает). максиму что можно от меня добиться это добавить условие в прерывание типо:
Один из вариантов решения - принять какое-то значение "off" как "остановлено".
Например, если off == 255, то в прерывании эту переменную не увеличивать.
В значение 255 переводить в прерывании, когда отработают все "выключено". А то и само оно до этого значения добежит и остановится.

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 22, 2017 14:24:21

Hiperboloyd писал(а):можно вместо: off ;
написать: off =(~off)? 1:0;
если офф не 0xff к нему прибавится 1, иначе 0.
так переменная дойдёт до 255 и там и останется. т.е. в условие сброса надо вписать 254 а не 255.
спасибо, но это кажется сложновато для меня
mas123 писал(а):Один из вариантов решения - принять какое-то значение "off" как "остановлено".
Например, если off == 255, то в прерывании эту переменную не увеличивать.
В значение 255 переводить в прерывании, когда отработают все "выключено". А то и само оно до этого значения добежит и остановится.
чтобы off постоянно не крутилось, можно просто добавить условие:
СпойлерISR( TIMER1_OVF_vect )
{
if ( off < 29)
{
off++;
if (8 == off)
{
PORTD &= ~(1<<6); //Выключить розетку (Вентилятор)
}
if (15 == off)
{
PORTA |= 1<<7; //погасить семисегментник
PORTB = 0b11111111; //погасить светофор
}
if (28 == off)
{
PORTD |= 1<<7;//выключить Свет
}
}

}
но я так понимаю это не решит проблему:
mas123 писал(а): возможна ситуация мгновенного выключения включенного, т.к. таймер "сработал".

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 22, 2017 14:30:02

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

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 22, 2017 17:28:40

блин, я забыл что сайт "плюсы" съедает :(
вместо off++;
off+=(~off)? 1:0;
скобки и вопрос это сокращённая запись ветвления, читается так: если в скобках истина, то выражение берётся до двоеточия, если ложно — после. ~ - инверсия побитовая (0xff обернётся в 0x00 и даст ложь, всё остальное даст истину. получаем -если офф!=255 выражение будет 1, и её прибавим к офф иначе прибавим 0.

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 22, 2017 18:41:19

чтобы off постоянно не крутилось, можно просто добавить условие:
if ( off < 29)
...
А теперь найди 33 разницы с моим вариантом "255 - это значение стоп". :))
но я так понимаю это не решит проблему:
Почему же? Решит.
При обнуление таймера после установки "включить" - "off" будет наращиваться, а когда дотикает до нужного значения - выключит.
Зато можно быть уверенным, что в момент установки "включить" таймер не сработает "вот-вот" на отключение.

Re: Дисковый номеронабиратель и семисегментник

Ср ноя 22, 2017 21:03:28

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

Здравствуйте, в общем все готово, цель достигнута и моя первая программа работает в допустимых пределах(для детской игрушки). Последняя проблема возникла «все перестало работать», я выложил текст всей программы, но ребята подсказали , что дело во фьюзах. Так же Сделали некоторые замечания. Т.к. Я решил что си - это интересно, то попросил объяснить, как что исправить, вот в принципе и все))

Добавлено after 2 minutes 54 seconds:
блин, я забыл что сайт "плюсы" съедает :(
вместо off++;
off+=(~off)? 1:0;
скобки и вопрос это сокращённая запись ветвления, читается так: если в скобках истина, то выражение берётся до двоеточия, если ложно — после. ~ - инверсия побитовая (0xff обернётся в 0x00 и даст ложь, всё остальное даст истину. получаем -если офф!=255 выражение будет 1, и её прибавим к офф иначе прибавим 0.

Примерно понял, очень интересный вариант, обязательно попробую. Спасибо, Вам!

Добавлено after 4 minutes 32 seconds:
mas123 писал(а):Почему же? Решит.
При обнуление таймера после установки "включить" - "off" будет наращиваться, а когда дотикает до нужного значения - выключит.
Зато можно быть уверенным, что в момент установки "включить" таймер не сработает "вот-вот" на отключение.
Ну значит со спокойной душой травлю плату! Ещё раз большое спасибо за поддержку и Советы

Re: Дисковый номеронабиратель и семисегментник

Пт дек 08, 2017 10:41:22

Спасибо ВСЕМ большое. Дочке понравилось!
замок пока не ставил - рановато. позже программа будет немного переделана и из светофора появится кодовый замок для синей двери.
выключатель зажигает свет в домики и синий LED в окне вентилятора. Розетка включает сам вентилятор. телефон - просто цифры.
Вот такая штука получилась:
СпойлерИзображение ИзображениеИзображениеИзображениеИзображениеИзображениеИзображениеИзображениеИзображение

Re: Дисковый номеронабиратель и семисегментник

Пт дек 08, 2017 18:28:54

Прикольно получилось)) А ты молодец. Не все тут могут похвастаться законченным устройством))
Кстати.. можно добавить ещё кучу функций.. так сказать на будущее..))

Re: Дисковый номеронабиратель и семисегментник

Вт дек 19, 2017 22:19:35

Прикольно получилось)) А ты молодец. Не все тут могут похвастаться законченным устройством))
Кстати.. можно добавить ещё кучу функций.. так сказать на будущее..))

Спасибо) я думал про кучу функций, но признаться домик мне поднадоел) как дочь подрастет подключу электрозамок и думаю на этом покончить) для меня это был превосходный опыт работы с деревом и МК. ребятам за помощь я очень благодарен!

Re: Дисковый номеронабиратель и семисегментник

Вт дек 19, 2017 22:47:04

Hiperboloyd - отлично! Я тоже делал дочке бизиборд, но он без электронных приблуд, все в кучу не стал мешать.
Хочу сделать второй бизик и как раз электронный.. Скажу спасибо за схему и програмку с подробностями ;)

Re: Дисковый номеронабиратель и семисегментник

Ср дек 04, 2019 21:05:55

Hiperboloyd - отлично! Я тоже делал дочке бизиборд, но он без электронных приблуд, все в кучу не стал мешать.
Хочу сделать второй бизик и как раз электронный.. Скажу спасибо за схему и програмку с подробностями ;)


Вероятнее всего уже поздно! но для будущих поколений , так сказать, выложу.

Прошу прощения что так прервал всё. на работе ноут озяб. что-то восстановилось. что-то с флешек собрал, что-то дома было. в итоге не смог найти окончательный вариант и забыл/забил.
но вот что-то копался и кажется это оно. В протеусе все работает, кроме таймера автоматического выключения, но так и было, в железе всё норм.

Повторяю: Вероятно это последний вариант, но возможно и нет. Это означает что могут быть ошибки. в Протеусе вроде работает.
Спойлер#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
#include <util/delay.h>

volatile unsigned char off=0; //для выключения всего
unsigned char flag=0; //флаг нажатой кнопки светофора
unsigned char cifra=0; //для семисегментника
unsigned char cifrakn=0; //для токо чтоб кн.тел. работала не с нуля
unsigned char svet=0; //для светофора
unsigned char vykl=0; //для выключателя
unsigned char rozetka=0; //для розетки
unsigned char sv=0;
unsigned char mag=0;
unsigned char SEGMENTE[] =
{// gfedcba
0b11111111,
0b11000000, // 0
0b11111001, // 1
0b10100100, // 2
0b10110000, // 3
0b10011001, // 4
0b10010010, // 5
0b10000010, // 6
0b11111000, // 7
0b10000000, // 8
0b10010000, // 9
};

ISR( TIMER1_OVF_vect )
{
if ( off < 29)
{
off++;
if (8 == off)
{
PORTD &= ~(1<<6); //Выключить розетку (Вентилятор)
}
if (15 == off)
{
PORTA |= 1<<7; //погасить семисегментник
PORTB = 0b11111111; //погасить светофор
}
if (28 == off)
{
PORTD |= 1<<0;//выключить Свет
}
}

}

ISR (INT2_vect)
{

_delay_ms(50);
off=0;
cifra = TCNT0; //переменной присвоить значение счетчика
if (cifra>0 && cifra<11) // если цифра >0 и <10
{
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру
cifrakn=cifra;
cifra=0; //обнулить переменную
}
else
{
if (11 == cifra) //если переменная равна 10
{
cifra=1; //обнулить переменную
PORTA = SEGMENTE[cifra]; //вывести на семисегментник цифру 0
}
}
PORTA &= ~(1<<7);// зажечь семисегментник
//cifra=0; //обнулить переменную ВРОДЕ БЕЗ ЭТОГО РАБОТАЕТ
TCNT0 = 0;
}

int main(void)
{
DDRA = 0b11111111; // порты на выход
PORTA = 0b11111111; // подтягиваем к 1
DDRB = 0b11111010;
PORTB = 0b11111111; //подтягивем к 1
DDRC = 0b00000000;
PORTC = 0b11111111; // подтягиваем к 1
DDRD = 0b11100001;
PORTD = 0b10011111;

GICR |= (1<<INT2); //разрешить внешние прерывания инт2
MCUCSR |=(1<<ISC2);//по спадающему фронту INT2

TCNT0 = 0; //установка таймера в ноль
TCCR0 |=(1<<CS02)|(1<<CS01)|(1<<CS00); //таймер от внеш. источника по переднему фронту для номеронабирателя

TIMSK |=(1<<TOIE1); //таймер по переполнению
TCCR1B |=(1<<CS11)|(1<<CS10); //делитель 64
sei(); //разрешить общее прерывание


while (1)
{
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<0))) // если PC0 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<0)))
{
PORTB &= ~(1<<1); // Установить на PB1 = 0
PORTB |= 1<<3; // Установить на PB3 = 1
}
while (!(PINC & (1<<0)))
{
}
}
//----------
if (!(PINC & (1<<2)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<2)))
{
PORTB |= 1<<1;
PORTB &= ~(1<<3);
}
while (!(PINC & (1<<2)))
{
}
}
//----------
if (!(PINC & (1<<1)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<1)))
{
PORTB &= ~(1<<3);
PORTB &= ~(1<<1);
}
while (!(PINC & (1<<1)))
{
}
}
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<3))) // если PC0 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<3)))
{
PORTB &= ~(1<<4); // Установить на PB1 = 0
PORTB |= 1<<5; // Установить на PB3 = 1
}
while (!(PINC & (1<<3)))
{
}
}
//----------
if (!(PINC & (1<<5)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<5)))
{
PORTB |= 1<<4;
PORTB &= ~(1<<5);
}
while (!(PINC & (1<<5)))
{
}
}
//----------
if (!(PINC & (1<<4)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<4)))
{
PORTB &= ~(1<<4);
PORTB &= ~(1<<5);
}
while (!(PINC & (1<<4)))
{
}
}
//---------- ТРИ КНОПКИ--------------------------------------------------
if (!(PINC & (1<<6))) // если PC6 = не 1 тк "!" перед условием
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<6)))
{
PORTB &= ~(1<<6); // Установить на PB6 = 0
PORTB |= 1<<7; // Установить на PB7 = 1
}
while ((!PINC & (1<<6)))
{
}
}
//----------
if (!(PIND & (1<<7)))
{
_delay_ms(50);
off=0;
if (!(PIND & (1<<7)))
{
PORTB |= 1<<6;
PORTB &= ~(1<<7);
}
while (!(PIND & (1<<7)))
{
}
}
//----------
if (!(PINC & (1<<7)))
{
_delay_ms(50);
off=0;
if (!(PINC & (1<<7)))
{
PORTB &= ~(1<<6);
PORTB &= ~(1<<7);
}
while (!(PINC & (1<<7)))
{
}
}
//----------. ЗАМОК-----------------------------
if ((PINB & (1<<3)) && (!(PINB & (1<<1))) && (!(PINB & (1<<4))) && (!(PINB & (1<<5))) && (!(PINB & (1<<7))) && (PINB & (1<<6)))
{
PORTD |= 1<<5;
}
else
{
PORTD &= ~(1<<5);
}
//----------
if (!(PIND & (1<<1)))
{

if (0==rozetka)
{
off=0;
_delay_ms(50);
rozetka=1;
PORTD |= 1<<6;
}

}
else
{
PORTD &= ~(1<<6);
rozetka=0;
}
//---------- СВЕТА-------------
if (!(PIND & (1<<2)))
{
if (0==vykl)
{
off=0;
_delay_ms(50);
vykl=1;
PORTD &= ~(1<<0);
}

}
else
{
PORTD |= 1<<0;
vykl=0;
}
//---------- СВЕТОФОРА-------------------
if (!(PIND & (1<<4)))
{
off=0;
_delay_ms(50);
if (!(PIND & (1<<4)))
{
sv++; //переменной +1
switch (sv)
{
case 1: PORTB &= ~(1<<1);PORTB &= ~(1<<4);PORTB &= ~(1<<6);PORTB |= 1<<3;PORTB |= 1<<5;PORTB |= 1<<7; break;
case 2: PORTB &= ~(1<<1);PORTB &= ~(1<<4);PORTB &= ~(1<<6);PORTB &= ~(1<<3);PORTB &= ~(1<<5);PORTB &= ~(1<<7); break;
case 3: PORTB &= ~(1<<3);PORTB &= ~(1<<5);PORTB &= ~(1<<7);PORTB |= 1<<1;PORTB |= 1<<4;PORTB |= 1<<6;sv=0;break;
default: ;
}
}
while (!(PIND & (1<<4)))
{
}

}
//---------- ТЕЛЕФОНА------------------------------
if (!(PIND & (1<<3)))
{
off=0;
_delay_ms(50);
if (!(PIND & (1<<3)))
{
cifrakn++;
if (cifrakn>0 && cifrakn<11) // если цифра >0 и <10
{
PORTA = SEGMENTE[cifrakn]; //вывести на семисегментник цифру
PORTA &= ~(1<<7);// зажечь семисегментник
}
else
{
if (11==cifrakn) //если переменная равна 10
{
cifrakn=1; //обнулить переменную
PORTA = SEGMENTE[cifrakn]; //вывести на семисегментник цифру 0
PORTA &= ~(1<<7);// зажечь семисегментник
cifrakn=1;
}
}
}
while (!(PIND & (1<<3)))
{
}

}
}
}


Схема с небольшими пояснениями
СпойлерИзображение
Ответить