Страница 1 из 1

Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 03:18:39
7seg
Всем здравствуйте.

Возник такой вопрос куда лучше писать энергонезависимую информацию, в моем примере это значение переменной нагрева + состояние вкл/выкл. Я читал что Сам EEPROM ограничен по записям. И где то натыкался на статейку что можно писать во флешь память самого мк.
Просто опыта по МК еще не имею вот и нехочу угробить мк постоянной перезаписью ЕЕПРОМ.
И еще есть вопросик как правильно организовать плавное включение ( увеличение value до save) ,save планирую писать в eeprom.

Код:
Спойлер

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

//***************************************************************************
//  Target(s)...: IDE: AVR AtmelStudio 6.2 MC:Attiny26L
//***************************************************************************
#define F_CPU   8000000          //Hz

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

//настройка параметров работы функций
#define BTN_LOCK_TIME		30					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		1000				/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/

//настройки портов
#define BTN_PORT			PORTB				/*порт чтения кнопок*/
#define BTN_DDR				DDRB
#define BTN_PIN				PINB

#define BTN_LINE_UP		(1<<4)				/*пины чтения кнопок*/
#define BTN_LINE_DN		(1<<3)
#define BTN_LINE_POWER	(1<<5)
//глобальные переменные
volatile uint8_t BtnFlags;//байт флагов нажатия кнопки
#define BTN_SHRT_UP			(1<<0)			/*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN			(1<<1)			/*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER		(1<<2)			/*бит короткого нажатия кнопки left*/
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
//-----------------------------------------------------------------------------------------------------------------------
#define  En_INT0      GIMSK|=(1<<6);
#define  Dis_INT0     GIMSK&=~(1<<6);     
volatile unsigned char fPower = 0;
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;
volatile unsigned char value = 0;

void init_io();
void segchar(unsigned char seg);
//Значения для открывания триака.
const unsigned char TRIAK[]PROGMEM = {
			160,156,155,154,150,148,146,144,142,140,
			139,137,135,131,129,127,125,123,122,120,
			119,118,117,116,115,114,113,112,111,110,
			109,108,107,106,105,104,103,102,101,100,
			99,98,97,96,95,94,93,92,91,90,
			89,88,87,86,85,84,83,82,81,80,
			79,78,77,76,75,74,73,72,71,70,
			69,68,67,66,65,64,63,62,61,60,
			59,58,57,56,55,54,53,52,51,50,
			49,48,47,45,43,41,40,37,35,33};
//-----------------------------------------------------------------------------------------------------------------------			
//настройка внешнего прерывния INT0
void int0_init( void )
{
	//настраиваем на срабатывание INT0 по переднему фронту
	MCUCR |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	En_INT0
}
 //-----------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_CMPA_vect)
{ 
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
}
//-----------------------------------------------------------------------------------------------------------------------
//функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//подтяжка вкл
}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения данных о нажатии кнопок
char BtnGet (void)
{
	cli();
	char temp = BtnFlags;
	BtnFlags = 0;
	sei();
	return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
	static unsigned char BtnLockBit;			//ащелка (защита от дребезга)
	static unsigned char BtnLockCoun;			//счетчик защелки (защита от дребезга)
	static unsigned char BtnLongCoun;			//счетчик длинного нажатия
	static unsigned char BtnLastState;			//последнее состояние кнопок перед отпусканием

	char mask = 0;
	if (! (BTN_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;;

	if (mask){									//опрос состояния кнопки
		if (BtnLockCoun < (BTN_LOCK_TIME/10)){	//клавиша нажата
			BtnLockCoun++;
			return;								//защелка еще не дощитала - возврат
		}
		BtnLastState = mask;
		BtnLockBit =1;							//нажатие зафиксировано
		if (BtnLongCoun >= (BTN_LONG_TIME/10))
		return;								//возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
		if (++BtnLongCoun >= (BTN_LONG_TIME/10))
		BtnFlags |= (BtnLastState<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
//-----------------------------------------------------------------------------------------------------------------------

//Прерывания по инт0 от синхра импулса
static unsigned char count = 0;
ISR(INT0_vect)
{
	if (fPower==1)
	{
	OCR1A = pgm_read_byte(&(TRIAK[value]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;
	//зажигаем следующий разр§д
	if (count == 0)
	{
		if (data2>0) //гасим старший разряд , если он == 0 .
		{
			segchar(data2);
			PORTB &= ~(1<<2);
		}
		else
		{
			PORTB |=(1<<PB2);
		}
	}
	if (count == 1)
	{
		segchar(data1);
		PORTB &= ~(1<<0);
	}
	count++;
	if (count == 2) {count = 0;}
	}
	else
	{
	OCR1A = pgm_read_byte(&(TRIAK[0]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;		
	}
	BtnExe();
}

int main(void)
{
	unsigned char save=0;
	init_io();
	sei();
	int0_init();
	BtnInit();
	while(1)
	{
		char BtnMask = BtnGet ();
		//одиночное нажатие +
		if ((BtnMask == BTN_SHRT_UP) & (value < 99))     
		{
			value++;
		}
		//одиночное нажатие -
		if ((BtnMask == BTN_SHRT_DN) & (value > 0))
		{
			value--;
		}
		//одиночное нажатие Power
		if (BtnMask == BTN_SHRT_POWER)
		{
			if (fPower==0)
			{
				value=save;
			}
			if (fPower==1)
			{
				save=value;
				value=0;
			}
			fPower++;
			if (fPower==2)
			{
				fPower=0;
			}
		}
		//Удержание +
		if ((BtnMask == BTN_LONG_UP) & (value < 99))
		{
			while ((!(PINB&0b00010000))& (value < 99))
			{
				value++;
				_delay_ms(100);
			}
		}
		//Удержание -
		if ((BtnMask == BTN_LONG_DN) & (value > 0))
		{
			while ((!(PINB&0b00001000))& (value > 0))
			{
				value--;
				_delay_ms(100);
			}
		}
	}
	return 0;
}

//Коды сегментов
void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTA = 0b01111100; break;
		case 2: PORTA = 0b10000100; break;
		case 3: PORTA = 0b01000100; break;
		case 4: PORTA = 0b01101000; break;
		case 5: PORTA = 0b01000010; break;
		case 6: PORTA = 0b00000010; break;
		case 7: PORTA = 0b01110100; break;
		case 8: PORTA = 0b00000000; break;
		case 9: PORTA = 0b01000000; break;
		case 0: PORTA = 0b00010000; break;
	}
}

void init_io()
{
	//порт, к которому подкл. сегменты
	PORTA = 0xff;
	DDRA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
	//Иницилизация прерываний по совпадению Т1.
	TIMSK |=(1<<OCIE1A);
	TCCR1B |=/*(1<<CTC1)*/(0<<CS10)|(1<<CS11)|(0<<CS12)|(1<<CS13);   
	OCR1A=0xFF;
}
Всех с праздником всемирного дня электросвязи и информационного общества. :beer:

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 04:27:32
Z_h_e
7seg писал(а): Я читал что Сам EEPROM ограничен по записям. И где то натыкался на статейку что можно писать во флешь память самого мк.
Лучше читать ДШ или хотя бы сверять их со статьями.
Изображение
Для того чтобы записать байт во Флеш придется стереть всю страницу.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 04:43:00
Demiurg
Алгоритм работы с EEPROM: при включении, сбросе считываются значения в ОЗУ и работаем с данными в ОЗУ. Один пин мк отдаем по контроль питания, как только пропало питание скидываем данные в EEPROM. Такой алгоритм подразумевает использование ионистора либо конденсаторы большой емкости на бп. Следует учитывать, что запись одного байта в EEPROM длится 8 мс.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 05:16:57
7seg
А при записи в ЕЕПРОМ мк входит в ожидание как при _delay или программа выполняется дальше ?

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 06:59:57
ARV
Программа выполняется дальше, но если до окончания цикла записи вы вдруг решите снова что-то записать, можете похерить данные в EEPROM.
А вообще: почему бы вам не читать даташит?
Ну и обязательно пользуйтесь библиотечными функциями, они хотя бы гарантируют, что цикл записи не будет прерван (но снова напомню, что документацию читать надо, ибо эти функции не рассчитаны на применение и в прерываниях, и в главном цикле).

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 07:28:21
Z_h_e
ARV писал(а):ибо эти функции не рассчитаны на применение и в прерываниях, и в главном цикле).
А где ж их использовать то тогда? :))
ARV писал(а):обязательно пользуйтесь библиотечными функциями
Это совет только для тех кто ДШ не читает. Операция записи в ЕЕПРОМ несложная.

7seg, напишите парочку несложных проектов на ассемблере. Это даст понимание МК. И ДШ тут совсем придется читать. :)

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 07:47:30
ARV
Z_h_e писал(а):А где ж их использовать то тогда?
и там и там - означает одновременно :) т.е. только в прерываниях или только в главном цикле - пожалуйста, ну а сразу всюду - это надо быть хорошим программистом, тогда тоже можно.

короче - не реентерабельные они, кто в курсе, что это значит, тот поймет, а остальным просто лучше не мешать в кучу оба способа.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 08:36:16
Z_h_e
Не понял что Вы имели ввиду одновременное использование. Хотя я и тут не вижу проблемы. В прерывпниях их не использовал. Интересно, эти функции учитывают что в обработчтке не надо трогать маску глобального разрешения прерываний.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 09:00:48
ARV
Z_h_e писал(а):Хотя я и тут не вижу проблемы
а когда умеешь что-то делать, проблем обычно и не бывает. они бывают, когда не умеешь.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 09:31:19
Z_h_e
Только что попробовал использовать функцию eeprom_write_byte((uint8_t*)0,0); в прерывании и поглядеть во что скомпилировалось (AS6). Код конечно сильно избыточен, есть команды которые совсем непонятно зачем включены (избыточность это отдельная тема). Я хотел проверить, не включит ли эта функция прерывания после запрета. Все нормально в этом плане, функция сохраняет SREG, только затем идет запрет, а после команды записи восстановление SREG.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 10:36:34
ARV
Да ведь дело не в том, что прерывание или избыточность, а в том, что функции работают со статическими счетчиками и вспомогательными переменными, что может нарушить их работу, если во время работы "первой" функции записи произойдет прерывание, внутри которого эта же функция будет вызвана повторно, это нарушит работу "первой" функции.

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

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 11:08:17
7seg
Чет пока лажа с еепром пока что получается. правильно ли я пытаюсь работать с еепром можете подсказать ?

код:
Спойлер

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

//***************************************************************************
//  Author(s)...: Плотников Андрей Игоревич
//  Target(s)...: IDE: AVR AtmelStudio 6.2 MC:Attiny26L
//  Data........: 15.05.17
//***************************************************************************
#define F_CPU   8000000          //Hz

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
//FOR EEPROM
uint16_t my_var=0;
uint16_t eeprom_data EEMEM;
uint16_t eeprom_read_word (const uint16_t *__p); //- прочитать слово (2 байта)
void eeprom_write_word (uint16_t *__p, uint16_t __value); //- запись слова (2 байта)

//настройка параметров работы функций
#define BTN_LOCK_TIME		30					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		1000				/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/

//настройки портов
#define BTN_PORT			PORTB				/*порт чтения кнопок*/
#define BTN_DDR				DDRB
#define BTN_PIN				PINB

#define BTN_LINE_UP		(1<<4)				/*пины чтения кнопок*/
#define BTN_LINE_DN		(1<<3)
#define BTN_LINE_POWER	(1<<5)
//глобальные переменные
volatile uint8_t BtnFlags;//байт флагов нажатия кнопки
#define BTN_SHRT_UP			(1<<0)			/*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN			(1<<1)			/*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER		(1<<2)			/*бит короткого нажатия кнопки left*/
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
//-----------------------------------------------------------------------------------------------------------------------
#define  En_INT0      GIMSK|= (1<<6);
#define  Dis_INT0     GIMSK&= ~(1<<6);   

volatile unsigned char save=0;  
volatile unsigned char fPower = 0;
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;
volatile unsigned char value = 0;

void init_io();
void segchar(unsigned char seg);
//Значения для открывания триака.
const unsigned char TRIAK[]PROGMEM = {
			160,156,155,154,150,148,146,144,142,140,
			139,137,135,131,129,127,125,123,122,120,
			119,118,117,116,115,114,113,112,111,110,
			109,108,107,106,105,104,103,102,101,100,
			99,98,97,96,95,94,93,92,91,90,
			89,88,87,86,85,84,83,82,81,80,
			79,78,77,76,75,74,73,72,71,70,
			69,68,67,66,65,64,63,62,61,60,
			59,58,57,56,55,54,53,52,51,50,
			49,48,47,45,43,41,40,37,35,33};
//-----------------------------------------------------------------------------------------------------------------------			
//настройка внешнего прерывния INT0
void int0_init( void )
{
	//настраиваем на срабатывание INT0 по переднему фронту
	MCUCR |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	En_INT0
}
 //-----------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_CMPA_vect)
{ 
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
}
//-----------------------------------------------------------------------------------------------------------------------
//функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//подтяжка вкл
}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения данных о нажатии кнопок
char BtnGet (void)
{
	cli();
	char temp = BtnFlags;
	BtnFlags = 0;
	sei();
	return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
	static unsigned char BtnLockBit;			//ащелка (защита от дребезга)
	static unsigned char BtnLockCoun;			//счетчик защелки (защита от дребезга)
	static unsigned char BtnLongCoun;			//счетчик длинного нажатия
	static unsigned char BtnLastState;			//последнее состояние кнопок перед отпусканием

	char mask = 0;
	if (! (BTN_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;;

	if (mask){									//опрос состояния кнопки
		if (BtnLockCoun < (BTN_LOCK_TIME/10)){	//клавиша нажата
			BtnLockCoun++;
			return;								//защелка еще не дощитала - возврат
		}
		BtnLastState = mask;
		BtnLockBit =1;							//нажатие зафиксировано
		if (BtnLongCoun >= (BTN_LONG_TIME/10))
		return;								//возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
		if (++BtnLongCoun >= (BTN_LONG_TIME/10))
		BtnFlags |= (BtnLastState<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
//-----------------------------------------------------------------------------------------------------------------------
//Прерывания по ИНТ0 от синхра импулса
static unsigned char count = 0;
static unsigned char time_eeprom = 0;
ISR(INT0_vect)
{
	if (fPower==1)
	{
	OCR1A = pgm_read_byte(&(TRIAK[value]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;
	//зажигаем следующий разр§д
	if (count == 0)
	{
		if (data2>0) //гасим старший разряд , если он == 0 .
		{
			segchar(data2);
			PORTB &= ~(1<<2);
		}
		else
		{
			PORTB |=(1<<PB2);
		}
	}
	if (count == 1)
	{
		segchar(data1);
		PORTB &= ~(1<<0);
	}
	count++;
	if (count == 2) {count = 0;}
	}
	else
	{
	OCR1A = pgm_read_byte(&(TRIAK[0]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;		
	}
	if (time_eeprom==9){
		if (!(save==value))
		{
			my_var=value;
			eeprom_write_word (&eeprom_data, my_var);
		}
	}
	if (time_eeprom==10){time_eeprom=0;}
	BtnExe();
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
int main(void)
{
	//читаем байт из eeprom
	my_var = eeprom_read_word(&eeprom_data);
	_delay_ms(1000);
	save=my_var;
	init_io();
	sei();
	int0_init();
	BtnInit();
	unsigned char OneEn=0;
	while(1)
	{
		char BtnMask = BtnGet ();
		//одиночное нажатие +
		if ((BtnMask == BTN_SHRT_UP) & (value < 99))     
		{
			value++;
		}
		//одиночное нажатие -
		if ((BtnMask == BTN_SHRT_DN) & (value > 0))
		{
			value--;
		}
		//одиночное нажатие Power
		if (BtnMask == BTN_SHRT_POWER)
		{
			if (fPower==0)
			{
				value=save;
				//OneEn=0;
			}
			if (fPower==1)
			{
				save=value;
				value=0;
				OneEn=0;
			}
			if (fPower==2)
			{
				fPower=0;
				//OneEn=0;
			}
			fPower++;
		}
		//Удержание +
		if ((BtnMask == BTN_LONG_UP) & (value < 99))
		{
			while ((!(PINB&0b00010000))& (value < 99))
			{
				value++;
				_delay_ms(100);
			}
		}
		//Удержание -
		if ((BtnMask == BTN_LONG_DN) & (value > 0))
		{
			while ((!(PINB&0b00001000))& (value > 0))
			{
				value--;
				_delay_ms(100);
			}
		}
		if ((fPower==1)&(OneEn==0))
		{
			while ((value<save)& (value < 99))
			{
				value++;
				_delay_ms(100);
			}
		}
		if (value==save)
		{
			OneEn=1;
		}
	}
	return 0;
}
//-----------------------------------------------------------------------------------------------------------------------
//Коды сегментов
void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTA = 0b01111100; break;
		case 2: PORTA = 0b10000100; break;
		case 3: PORTA = 0b01000100; break;
		case 4: PORTA = 0b01101000; break;
		case 5: PORTA = 0b01000010; break;
		case 6: PORTA = 0b00000010; break;
		case 7: PORTA = 0b01110100; break;
		case 8: PORTA = 0b00000000; break;
		case 9: PORTA = 0b01000000; break;
		case 0: PORTA = 0b00010000; break;
	}
}
//-----------------------------------------------------------------------------------------------------------------------
void init_io()
{
	//порт, к которому подкл. сегменты
	PORTA = 0xff;
	DDRA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
	//Иницилизация прерываний по совпадению Т1.
	TIMSK |=(1<<OCIE1A);
	TCCR1B |=/*(1<<CTC1)*/(0<<CS10)|(1<<CS11)|(0<<CS12)|(1<<CS13);   
	OCR1A=0xFF;
}

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 11:14:54
ARV
В простыне кода разбираться влом, но настоятельно рекомендую применять вместо eeprom_write_xxxx функции eeprom_update_xxxx
Последние функции проверяют содержимое ячеек на совпадение и не перезаписывают те, которые в этом не нуждаются, чем повышают ресурс EEPROM.
В остальном их действие аналогично.

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 11:41:38
7seg
eeprom_write_xxxx заменил на eeprom_update_xxxx )

Добавлено after 12 minutes 20 seconds:
вроде бы получилось работает, но не совсем гладко, иногда сохраняет на 1 меньше почему то )) и плавное повышение яркости не робит . буду дальше разбираться.
Спойлер

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

//***************************************************************************
//  Target(s)...: IDE: AVR AtmelStudio 6.2 MC:Attiny26L
//***************************************************************************
#define F_CPU   8000000          //Hz

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
//FOR EEPROM
uint16_t my_var=0;
uint16_t eeprom_data EEMEM;
uint16_t eeprom_read_word (const uint16_t *__p); //- прочитать слово (2 байта)
void eeprom_write_word (uint16_t *__p, uint16_t __value); //- запись слова (2 байта)
void eeprom_update_word (uint16_t *__p, uint16_t __value);

//настройка параметров работы функций
#define BTN_LOCK_TIME		30					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		1000				/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/

//настройки портов
#define BTN_PORT			PORTB				/*порт чтения кнопок*/
#define BTN_DDR				DDRB
#define BTN_PIN				PINB

#define BTN_LINE_UP		(1<<4)				/*пины чтения кнопок*/
#define BTN_LINE_DN		(1<<3)
#define BTN_LINE_POWER	(1<<5)
//глобальные переменные
volatile uint8_t BtnFlags;//байт флагов нажатия кнопки
#define BTN_SHRT_UP			(1<<0)			/*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN			(1<<1)			/*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER		(1<<2)			/*бит короткого нажатия кнопки left*/
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
//-----------------------------------------------------------------------------------------------------------------------
#define  En_INT0      GIMSK|= (1<<6);
#define  Dis_INT0     GIMSK&= ~(1<<6);   
volatile unsigned char save=0;  
volatile unsigned char fPower = 0;
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;
volatile unsigned char value = 0;

void init_io();
void segchar(unsigned char seg);
//Значения для открывания триака.
const unsigned char TRIAK[]PROGMEM = {
			160,156,155,154,150,148,146,144,142,140,
			139,137,135,131,129,127,125,123,122,120,
			119,118,117,116,115,114,113,112,111,110,
			109,108,107,106,105,104,103,102,101,100,
			99,98,97,96,95,94,93,92,91,90,
			89,88,87,86,85,84,83,82,81,80,
			79,78,77,76,75,74,73,72,71,70,
			69,68,67,66,65,64,63,62,61,60,
			59,58,57,56,55,54,53,52,51,50,
			49,48,47,45,43,41,40,37,35,33};
//-----------------------------------------------------------------------------------------------------------------------			
//настройка внешнего прерывния INT0
void int0_init( void )
{
	//настраиваем на срабатывание INT0 по переднему фронту
	MCUCR |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	En_INT0
}
 //-----------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_CMPA_vect)
{ 
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
		PORTB |= (1<<1);
		_delay_us(9);
		PORTB &= ~(1<<1);
		_delay_us(1);
}
//-----------------------------------------------------------------------------------------------------------------------
//функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//подтяжка вкл
}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения данных о нажатии кнопок
char BtnGet (void)
{
	cli();
	char temp = BtnFlags;
	BtnFlags = 0;
	sei();
	return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
	static unsigned char BtnLockBit;			//ащелка (защита от дребезга)
	static unsigned char BtnLockCoun;			//счетчик защелки (защита от дребезга)
	static unsigned char BtnLongCoun;			//счетчик длинного нажатия
	static unsigned char BtnLastState;			//последнее состояние кнопок перед отпусканием

	char mask = 0;
	if (! (BTN_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;;

	if (mask){									//опрос состояния кнопки
		if (BtnLockCoun < (BTN_LOCK_TIME/10)){	//клавиша нажата
			BtnLockCoun++;
			return;								//защелка еще не дощитала - возврат
		}
		BtnLastState = mask;
		BtnLockBit =1;							//нажатие зафиксировано
		if (BtnLongCoun >= (BTN_LONG_TIME/10))
		return;								//возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
		if (++BtnLongCoun >= (BTN_LONG_TIME/10))
		BtnFlags |= (BtnLastState<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
//-----------------------------------------------------------------------------------------------------------------------
//Прерывания по ИНТ0 от синхра импулса
static unsigned char count = 0;
static unsigned char time_eeprom = 0;
ISR(INT0_vect)
{
	if (fPower==1)
	{
	time_eeprom++;
	OCR1A = pgm_read_byte(&(TRIAK[value]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;
	//зажигаем следующий разр§д
	if (count == 0)
	{
		if (data2>0) //гасим старший разряд , если он == 0 .
		{
			segchar(data2);
			PORTB &= ~(1<<2);
		}
		else
		{
			PORTB |=(1<<PB2);
		}
	}
	if (count == 1)
	{
		segchar(data1);
		PORTB &= ~(1<<0);
	}
	count++;
	if (count == 2) {count = 0;}
	}
	else
	{
	OCR1A = pgm_read_byte(&(TRIAK[0]));
	TCNT1 = 0;
	data1 = value % 10;
	data2= value/10;
	//гасим оба разр§да
	PORTB |=(1<<PB0);
	PORTB |=(1<<PB2);
	PORTA = 0b11111110;		
	}
	BtnExe();
	if (time_eeprom==9){
		if (!(save==value))
		{
			my_var=value;
			eeprom_update_word (&eeprom_data, my_var);
		}
	}
	if (time_eeprom==10){time_eeprom=0;}
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
int main(void)
{
	//читаем байт из eeprom
	my_var = eeprom_read_word(&eeprom_data);
	_delay_ms(1000);
	init_io();
	sei();
	int0_init();
	BtnInit();
	unsigned char OneEn=0;
	save=my_var;
	while(1)
	{
		char BtnMask = BtnGet ();
		//одиночное нажатие +
		if ((BtnMask == BTN_SHRT_UP) & (value < 99))     
		{
			value++;
		}
		//одиночное нажатие -
		if ((BtnMask == BTN_SHRT_DN) & (value > 0))
		{
			value--;
		}
		//одиночное нажатие Power
		if (BtnMask == BTN_SHRT_POWER)
		{
			if (fPower==0)
			{
				value=save;
			}
			if (fPower==1)
			{
				save=value;
				value=0;
				OneEn=0;
			}
			if (fPower==2)
			{
				fPower=0;
			}
			fPower++;
		}
		//Удержание +
		if ((BtnMask == BTN_LONG_UP) & (value < 99))
		{
			while ((!(PINB&0b00010000))& (value < 99))
			{
				value++;
				_delay_ms(100);
			}
		}
		//Удержание -
		if ((BtnMask == BTN_LONG_DN) & (value > 0))
		{
			while ((!(PINB&0b00001000))& (value > 0))
			{
				value--;
				_delay_ms(100);
			}
		}
		if ((fPower==1)&(OneEn==0))
		{
			while ((value<save)& (value < 99))
			{
				value++;
				_delay_ms(100);
			}
		}
		if (value==save)
		{
			OneEn=1;
		}
	}
	return 0;
}
//-----------------------------------------------------------------------------------------------------------------------
//Коды сегментов
void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTA = 0b01111100; break;
		case 2: PORTA = 0b10000100; break;
		case 3: PORTA = 0b01000100; break;
		case 4: PORTA = 0b01101000; break;
		case 5: PORTA = 0b01000010; break;
		case 6: PORTA = 0b00000010; break;
		case 7: PORTA = 0b01110100; break;
		case 8: PORTA = 0b00000000; break;
		case 9: PORTA = 0b01000000; break;
		case 0: PORTA = 0b00010000; break;
	}
}
//-----------------------------------------------------------------------------------------------------------------------
void init_io()
{
	//порт, к которому подкл. сегменты
	PORTA = 0xff;
	DDRA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
	//Иницилизация прерываний по совпадению Т1.
	TIMSK |=(1<<OCIE1A);
	TCCR1B |=/*(1<<CTC1)*/(0<<CS10)|(1<<CS11)|(0<<CS12)|(1<<CS13);   
	OCR1A=0xFF;
}
Добавлено after 9 minutes 20 seconds:
Да и вроде помаргивание на лампе наблюдается (

Re: Запись\Чтение EEPROM или flash.

Добавлено: Ср май 17, 2017 11:44:13
ARV
Вы идеологически неверно делаете сохранение.
Зачем в таймере?!

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

Re: Запись\Чтение EEPROM или flash.

Добавлено: Пт май 19, 2017 11:36:47
7seg
Уважаемые знатоки всем спасибо за советы) мой первый проект готов. 8)
Отдельное спасибо участникам форума: ARV. Z_h_e.

И по традиции сделал сам поделись с остальными (мб поможет новичкам) .100% правильность работы программы не гарантирую использовать на свой страх и риск. :)

Также принимается всевозможная критика по коду и алгоритму работы.
Спойлер

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

//***************************************************************************
//  Target(s)...: IDE: AVR AtmelStudio 6.2 MC:Attiny26L
//  Data........: 19.05.17
//***************************************************************************
#define F_CPU   8000000          //Hz
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
//-----------------------------------------------------------------------------------------------------------------------
volatile unsigned char timer_save=0;
volatile unsigned char savePower=0;
volatile unsigned char saveValue=0;
volatile unsigned char fBtPower=1; // Состояние  кнопки 
volatile unsigned char fPower = 0;
//EEPROM
uint16_t power_var = 0;
uint16_t value_var = 0;
uint16_t eeprom_power EEMEM;
uint16_t eeprom_value EEMEM;
//-----------------------------------------------------------------------------------------------------------------------
//настройка параметров работы функций
#define BTN_LOCK_TIME		20					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		1000				/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT			PORTB			
#define BTN_DDR				DDRB
#define BTN_PIN				PINB
/*пины чтения кнопок*/
#define BTN_LINE_UP		(1<<4)			
#define BTN_LINE_DN		(1<<3)
#define BTN_LINE_POWER	(1<<5)
//глобальные переменные
volatile uint8_t BtnFlags;									//байт флагов нажатия кнопки
#define BTN_SHRT_UP			(1<<0)			/*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN			(1<<1)			/*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER		(1<<2)			/*бит короткого нажатия кнопки POWER */
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
//-----------------------------------------------------------------------------------------------------------------------
#define  En_INT0      GIMSK|= (1<<6);
#define  Dis_INT0     GIMSK&= ~(1<<6);
//-----------------------------------------------------------------------------------------------------------------------
volatile unsigned char data1 = 0;	//Младший разряд индикатора 
volatile unsigned char data2 = 0;	//Старший разряд индикатора
volatile unsigned char cValue = 0;	//Значения нагрева лампы от 0 до 99
//-----------------------------------------------------------------------------------------------------------------------
static void init_io();
static void segchar(unsigned char seg);
//Значения для срабатывание триака.
const unsigned char TRIAK[]PROGMEM = {
	160,156,155,154,150,148,146,144,142,140,
	139,137,135,131,129,127,125,123,122,120,
	119,118,117,116,115,114,113,112,111,110,
	109,108,107,106,105,104,103,102,101,100,
	99,98,97,96,95,94,93,92,91,90,
	89,88,87,86,85,84,83,82,81,80,
	79,78,77,76,75,74,73,72,71,70,
	69,68,67,66,65,64,63,62,61,60,
	59,58,57,56,55,54,53,52,51,50,
	49,48,47,45,43,41,40,37,35,33};
//-----------------------------------------------------------------------------------------------------------------------
ISR(TIMER1_CMPA_vect)
{
	cli();
	PORTB |= (1<<1);
	_delay_us(9);
	PORTB &= ~(1<<1);
	_delay_us(1);
	PORTB |= (1<<1);
	_delay_us(9);
	PORTB &= ~(1<<1);
	sei();
}
//-----------------------------------------------------------------------------------------------------------------------
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER);//подтяжка вкл
}
//-----------------------------------------------------------------------------------------------------------------------
//Функция чтения данных о нажатии кнопок
char BtnGet (void)
{
	cli();
	char temp = BtnFlags;
	BtnFlags = 0;
	sei();
	return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
	static unsigned char BtnLockBit;				//ащелка (защита от дребезга)
	static unsigned char BtnLockCoun;			//счетчик защелки (защита от дребезга)
	static unsigned char BtnLongCoun;			//счетчик длинного нажатия
	static unsigned char BtnLastState;			//последнее состояние кнопок перед отпусканием

	char mask = 0;
	if (! (BTN_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;;

	if (mask){									//опрос состояния кнопки
		if (BtnLockCoun < (BTN_LOCK_TIME/10)){	//клавиша нажата
			BtnLockCoun++;
			return;								//защелка еще не дощитала - возврат
		}
		BtnLastState = mask;
		BtnLockBit =1;							//нажатие зафиксировано
		if (BtnLongCoun >= (BTN_LONG_TIME/10))
		return;								//возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
		if (++BtnLongCoun >= (BTN_LONG_TIME/10))
		BtnFlags |= (BtnLastState<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
//-----------------------------------------------------------------------------------------------------------------------
//Прерывания по ИНТ0 от синхра импулса
volatile unsigned char count = 0;
ISR(INT0_vect)
{
	if (fPower==1)
	{
		data1 = cValue % 10;
		data2= cValue/10;
		OCR1A = pgm_read_byte(&(TRIAK[cValue]));
		TCNT1 = 0;
		//гасим оба разряда
		PORTB |=(1<<PB0);
		PORTB |=(1<<PB2);
		PORTA = 0b11111110;
		//зажигаем следующий разряд
		if (count == 0)
		{
			if (data2>0) //Пропускаем старший разряд , если он == 0 .
			{
				segchar(data2);
				PORTB &= ~(1<<2);
			}
			else
			{
				PORTB |=(1<<PB2);
			}
		}
		if (count == 1)
		{
			segchar(data1);
			PORTB &= ~(1<<0);
		}
		count++;
		if (count == 2) {count = 0;}
	}
	else
	{
		PORTB |=(1<<PB0);
		PORTB |=(1<<PB2);
		PORTA = 0b11111110;
		OCR1A = pgm_read_byte(&(TRIAK[0]));
		TCNT1 = 0;
	}
	BtnExe();
}
//-----------------------------------------------------------------------------------------------------------------------
int main(void)
{
	//читаем байт из eeprom
	 value_var= eeprom_read_word(&eeprom_value);
	_delay_ms(100);
	power_var=eeprom_read_word(&eeprom_power);
	_delay_ms(100);
	fBtPower=power_var;
	if (fBtPower==2)
	{
		fPower=1;
	}
	if (fBtPower==1)
	{
		fPower=0;
	}
	saveValue=value_var;
	init_io();
	BtnInit();
	unsigned char OneEn=0;
	_delay_ms(800);
	sei();
	while(1)
	{
		if (OneEn==0)
		{
			OneEn=1;
		}
		if ((fPower == 1)&(OneEn==1))
		{
			while ((cValue<saveValue)& (cValue < 99))
			{
				cValue++;
				_delay_ms(100);
			}
			OneEn=2;
		}
		char BtnMask = BtnGet ();
		//одиночное нажатие +
		if ((BtnMask == BTN_SHRT_UP) & (cValue < 99)&(fPower==1))
		{
			cValue++;
			saveValue=cValue;
			value_var=saveValue;
			eeprom_update_word (&eeprom_value, value_var);
		}		
		//одиночное нажатие -
		if ((BtnMask == BTN_SHRT_DN) & (cValue > 0)&(fPower==1))
		{
			cValue--;
			saveValue=cValue;
			value_var=saveValue;
			eeprom_update_word (&eeprom_value, value_var);
		}			
		
		//одиночное нажатие Power
		if (BtnMask == BTN_SHRT_POWER)
		{
			fBtPower++;
			if (fBtPower==2) 
			{
				fPower=1;
				savePower=fBtPower;
			}
			if (fBtPower==3)
			{
				OneEn=1;
				cValue=0;
				savePower=(fBtPower-2);
				fPower=0;
			}
			if (fBtPower==3)
			{
				fBtPower=1;
			}
			power_var=savePower;
			eeprom_update_word (&eeprom_power, power_var);
		}
		//Удержание +
		if ((BtnMask == BTN_LONG_UP) & (cValue < 99)&(fPower==1))
		{
			while ((!(PINB&0b00010000))& (cValue < 99))
			{
				cValue++;
				_delay_ms(100);
			}
			saveValue=cValue;
			value_var=saveValue;
			eeprom_update_word (&eeprom_value, value_var);
		}
		//Удержание -
		if ((BtnMask == BTN_LONG_DN) & (cValue > 0)&(fPower==1))
		{
			while ((!(PINB&0b00001000))& (cValue > 0))
			{
				cValue--;
				_delay_ms(100);
				saveValue=cValue;
				value_var=saveValue;
				eeprom_update_word (&eeprom_value, value_var);
			}
		}
	}
	return 0;
}
//-----------------------------------------------------------------------------------------------------------------------
//Функция включения сегментов + кодировка.
static void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTA = 0b01111100; break;
		case 2: PORTA = 0b10000100; break;
		case 3: PORTA = 0b01000100; break;
		case 4: PORTA = 0b01101000; break;
		case 5: PORTA = 0b01000010; break;
		case 6: PORTA = 0b00000010; break;
		case 7: PORTA = 0b01110100; break;
		case 8: PORTA = 0b00000000; break;
		case 9: PORTA = 0b01000000; break;
		case 0: PORTA = 0b00010000; break;
	}
}
//-----------------------------------------------------------------------------------------------------------------------
static void init_io()
{
	//порт, к которому подкл. сегменты
	PORTA = 0xff;
	DDRA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
	//Иницилизация прерываний по совпадению Т1.
	TIMSK |=(1<<OCIE1A);
	TCCR1B |=/*(1<<CTC1)*/(0<<CS10)|(1<<CS11)|(0<<CS12)|(1<<CS13);
	OCR1A=0xFF;
	//настраиваем на срабатывание INT0 по переднему фронту
	MCUCR |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	En_INT0
}