9-ти битный UART

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Сообщение sergo80zxc »

Здравия вам товарищи коты) Возник вопрос при изучении 9 битного варта. Смысл такой, написал программу для двух мк 168 меги, в программе они обмениваются по варту бегущими огнями (посылки 9 бит). При получении посылки сначала считываются три бита ошибок варта (FE0, DOR0, UPE0) и каждый бит выводится на свой пин индикации (светодиоды), ну и сами 9 бит посылки выводятся на порт индикации, засада в том, по принятию посылки, где установлен 9-ый бит возникает ошибка кадрирования (FE0) , как только принимается следующая посылка с нулевым значением 9-го бита флаг ошибки кадрирования сбрасывается, почему так?
ниже исходник для обоих мк, в исходнике в коментах все подробно написано

Спойлер

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

/*                            ------ асинхронный  (9-N-1) ------ РАБОТАЕТ --- но есть нюанс ошибки кадрирования (FE0)-------
 * GccApplication57.c
 *                            -----  прога для равноправных МК -------------- индикация битов ошибок (FE0, DOR0, UPE0) модуля USART0 --------
 * Created: 02.06.2021 15:45:07
 * Author : Admin
 */ 


// задача-организовать поочередную отправку и прием 9-ти битной посылки циклически (полудуплекс) и опросить все биты ошибок (FE0, DOR0, UPE0) модуля USART0,
// затем значение каждого бита из 3 вывести на свой пин индикации и конечно же на индикацию вывести 9 бит посылки
//
// в программе мы изучаем 9-и битный режим передачи и хотим наблюдать на светодиодах есть ли ошибки модуля USART0 и также саму посылку хотим видеть на светодиодах,
// для этого под ошибки модуля USART0 назначим такие светодиоды 
//  (PORTD7) ---- значение (FE0)  ----- Флаг ошибки кадрирования
//  (PORTD6) ---- значение (DOR0) ----- Флаг переполнения
//  (PORTD5) ---- значение (UPE0) ----- Флаг ошибки контроля четности
//  (PORTD3) -------------------------- значение 9-го бита принятой посылки 
//  (PORTB ) -------------------------- 8 младших битов принятой посылки
//
// прога работает так, в суперцикле по прерыванию системного таймера отправляем байты бегущего огонька другому мк не читая принятые взамен байты,
// затем по прерыванию завершение приема мы получаем 9-ти битную посылку и выводим все полученые биты на светодиодную индикацию (9 битов посылка и 3 бита ошибок)
// получается у нас 9-и битный бегущий огонек и почему то в момент получения установленого 9-го бита у нас зажигается ошибка кадрирования бит (FE0), затем
// когда в следующей посылке 9-ый бит сброшен сбрасывается и ошибка
//
//
//
// частота ядра 1 МГц ,  скорость = 2400 бит/с   при   UBRR = 25  и  U2X0 = 0   таблица даташит,  но мы по формуле в дефайнах вычислим (UBRR)
// асинхронный USART0  ----------------------------  (UMSEL10=0, UMSEL00=0)
// отключена проверка на четность и нечетность ----- (UPM01=0, UPM00=0)
// 1 стоп, 9 data, без проверки четности, асинхронный  (9-N-1)


#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL              // тактовая частота МК

#define BAUD 2400                    // BAUD — скорость передачи, бит/с;
#define MYUBRR F_CPU/16/BAUD-1       // РАСЧЕТ (UBRR) ПО ИЗВЕСТНОЙ СКОРОСТИ ------


//--------------------------------------------------  ПОРТ ИНДИКАЦИИ ---------------------------------------------------------------------------
#define PORT_LED    PORTB
#define DDR_LED     DDRB

volatile uint8_t sis_taimer =0;     // переменная системного таймера

//----------------------------------------------------------------------------------------------------------------------------------------------------
void TIMER0_init(void)          // инициализация  модуля таймера Т0 режим СТС прерывание и сброс по совпадению с содержимым регистра (OCR0A)
{
	TIMSK0 = 0b00000010;        // бит РВ1(OCIE0A) устанавливаем в 1, разрешения прерывания по совпадению блока А таймера /счетчика Т0
	TCCR0A = 0b00000010;        // биты (WGM02,WGM00) сбрасываем в 0, (WGM01) установим в 1 настройка ------- режима СТС
	TCCR0B = 0b00000010;        // настраиваем предделитель на 8 (биты  CS02=0,CS01=1,CS00=0),бит В3(WGM02) сбрасываем в 0
	OCR0A  = 100;               // запишем 100 в регистр сравнения (OCR0A) блока А
	GTCCR  = 0b00000001;        // бит РВ0(PSRSYNC) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)

}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------
void USART0_Init_9_N_1( unsigned int ubrr)        // инициализация приемопередатчика USART0.
{
	UBRR0H = (uint8_t)(ubrr>>8);                  // сместив двух байтовый (ubrr) 8 раз вправо мы впишем в одно байтовый регистр (UBRR0H) старший байт
	UBRR0L = (uint8_t)ubrr;                       // запишем рассчитанное в дефайнах число в младший одно байтовый регистр скорости (UBRR0L)
	UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0)|(1<<UCSZ02);   // разрешаем работу модуля передатчика и приемника, разрешение прерывания по завершении приема
	UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);             // 1 стоп-бит, размер слова 9 бит	(9-N-1)
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------------

void USART_Transmit( uint16_t data )       // передаем 9 битный символ так - помещаем 9-тый бит в (TXB80), а затем записываем младшие 8 битов в (UDR0)
{
	while ( !( UCSR0A & (1<<UDRE0)) );     // ожидаем опустошение приемного регистра	
	if ( data & 0x0100 )                   // проверяем 9 по счету бит переменной (data), если этот бит = 1, то выполняется  выражение в скобках
	{
		UCSR0B |= (1<<TXB80);              // устанавливаем  9 по счету бит передачи (TXB80) в 1
	}
	else                                   // иначе 9 по счету бит переменной (data) не равен 1, то есть = 0, то выполняется  выражение в скобках
	{
		UCSR0B &= ~(1<<TXB80);             // сбрасываем  9 по счету бит передачи (TXB80) в 0
	}
	    UDR0 = data;                       // отправляем оставшиеся 8 бит в регистр данных
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t USART_Receive( void )                 // прием 9-ти битной посылки в режиме (9-N-1). выдаем из функции через ретурн 2-х байтное слово
{  	                                           //                                             8-0-ой разряд ---------------------- младший байт посылки                               
	                                           //                                             9-ой разряд   ---  бит  (RXB80)   -- 9 бит посылки
	                                           //                                             10-ый разряд  ---  бит  (UPE0)    -- Флаг ошибки контроля четности
	                                           //	                                          11-ой разряд  ---  бит  (DOR0)    -- Флаг переполнения
	                                           //	                                          12-ий разряд  ---  бит  (FE0)     -- Флаг ошибки кадрирования
    while ( !(UCSR0A & (1<<RXC0)) );           // ожидаем завершения приема (  ПРИМЕНЯЕМ ЭТУ СТРОКУ, ЕСЛИ ФУНКЦИЯ РАБОТАЕТ НЕ В ПРЕРЫВАНИИ ПО ЗАВЕРШЕНИЮ ПРИЕМА)											   
											   
	uint8_t status, resh, resl, err_stat;      // объявим переменные

	status = UCSR0A;                           // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0)
	resh = UCSR0B;                             // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 бит (RXB80)
	resl = UDR0;                               // считываем полученый 8 битный байт данных из регистра данных (UDR0)
	
	status = (status >> 1) & 0x0E;             // сместим байт (status) на одну позицию вправо, тем самым бит (UPE0) со 2-го разряда перейдет в 1-ой, бит (DOR0) с 3-го
	                                           // во 2-ый, бит (FE0) с 4-го в 3-ой, затем на байт  набросим маску 0x0E и все разряды обнулятся кроме 1,2,3 в которых 
		                                       // теперь наши статусные биты (FE0, DOR0, UPE0)
	
	if (resh & 0x02)                           // проверяем 1 разряд переменной (resh) он же (RXB80) , если этот бит = 1, то выполняется выражение в скобках
	{
	   status |= (1<<0);                       // установить в 1 нулевой разряд переменной (status), остальные биты не трогаем        
	}
    else                                       // иначе если 1 бит переменной (resh) равен 0 , то выполняется выражение в скобках
	{
	   status &= ~(1<<0);                      // сбросить в 0  нулевой разряд  переменной (status), остальные биты не трогаем 
	}	
                                               // теперь в переменной (status) у нас биты:    0-ой разряд   ---  бит  (RXB80)
                                               //                                             1-ый разряд   ---  бит  (UPE0)
                                               //	                                          2-ой разряд   ---  бит  (DOR0)
                                               //	                                          3-ий разряд   ---  бит  (FE0)     
	
	return ((status << 8) | resl);             // сместим байт (status) в старший байт двухбайтового слова и получится такая картина--   
                                               //                                             9-ой разряд   ---  бит  (RXB80)   -- 9 бит посылки
                                               //                                             10-ый разряд  ---  бит  (UPE0)    -- Флаг ошибки контроля четности
                                               //	                                          11-ой разряд  ---  бит  (DOR0)    -- Флаг переполнения
                                               //	                                          12-ий разряд  ---  бит  (FE0)     -- Флаг ошибки кадрирования	                          	                                             	                                         	
	                                           // а в восемь остальных младших бит поместим значение из (UDR0)
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------

uint16_t running_light(void)      // ф-ия передает в вызывающюю ф-ию бегущий огонек (при каждом вызове в переданом 9-и битном слове еденица смещается на разряд влево)
{                                 // примерно так- сначала 0b000000001, при следующем вызове 0b000000010, потом 0b000000100 и так по 0b100000000 и все заново
	uint16_t data = 0;            // создаем и задаем значение  переменной (data),
	static uint8_t a = 0;         // создаем и задаем значение  статической переменной (a), она у нас будет номером бита в нашем байте данных (data)
	
	if (a>8) a=0;                 // защита от переполнения, как только (а) станет = 9 она обнулится , что бы не вылезти за размер 9 битного символа
	data = (1 << a);              // установка еденицы в бит (а) байта (data) с затиранием остальных битов, например было (0b000000001) потом стало (0b000000010)
	a++ ; 	                      // инкрементируем наш номер бита в 9-ти битном слове)))
	return (data);                // передаем в вызывающюю функцию наш байт
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------
ISR(USART_RX_vect)                   // прерывание по завершению приема
{
	
	uint16_t in_data = 0 ;              // в это двухбайтовое слово будем получать данные от другого МК
	in_data = USART_Receive();          // получим в (in_data)	нашу 9 битную посылку и статус ошибок модуля  USART0
	
	uint8_t  x_low  = in_data & 0xff;   // обнуляем старший байт двухбайтового слова и остается значение младшего байта, которое запишем в (x_low)
	uint8_t  x_high = (in_data >> 8);   // сдвигаем старший байт в младший байт двухбайтового слова и записываем в (x_high)

	if (x_high & 0x01)                  // проверяем 0-ой разряд переменной x_high (там у нас значение 9 бита), если этот разряд = 1, то выполним выражение в скобках
	{
		PORTD |= (1<<PORTD3);           // зажгем светодиод на пине (PORTD3)   
	}
	else                                // иначе если нулевой разряд = 0 , то выполним выражение в скобках
	{
		PORTD &= ~(1<<PORTD3);          // погасим  светодиод на пине (PORTD3)
	}	
	
	if (x_high & 0x02)                  // проверяем 1-ой разряд переменной x_high (там у нас значение (UPE0)), если этот разряд = 1, то выполним выражение в скобках
	{
		PORTD |= (1<<PORTD5);           // зажгем светодиод на пине (PORTD5)   
	}
	else                                // иначе если 1-ый разряд = 0 , то выполним выражение в скобках
	{
		PORTD &= ~(1<<PORTD5);          // погасим  светодиод на пине (PORTD5) 
	}	
	
	if (x_high & 0x04)                  // проверяем 2-ой разряд переменной x_high (там у нас значение (DOR0)), если этот разряд = 1, то выполним выражение в скобках
	{
		PORTD |= (1<<PORTD6);           // зажгем светодиод на пине (PORTD6)
	}
	else                                // иначе если 2-ой разряд = 0 , то выполним выражение в скобках
	{
		PORTD &= ~(1<<PORTD6);          // погасим  светодиод на пине (PORTD6)
	}	
	
	if (x_high & 0x01)                  // проверяем 3-ий разряд переменной x_high (там у нас значение (FE0)), если этот разряд = 1, то выполним выражение в скобках
	{
		PORTD |= (1<<PORTD7);           // зажгем светодиод на пине (PORTD7)
	}
	else                                // иначе если 3-ий разряд = 0 , то выполним выражение в скобках
	{
		PORTD &= ~(1<<PORTD7);          // погасим  светодиод на пине (PORTD7)
	}	
	
	
	
	    PORT_LED = x_low;               // принятый младший байт выведем в порт индикации		
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
ISR(TIMER0_COMPA_vect)               // прерывание по совпадению блока А таймера  Т0
{
	
	sis_taimer ++;                   // инкрементируем  системный таймер
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

int main(void)
{
	DDRD |= (1<<DDD7)|(1<<DDD6)|(1<<DDD5)|(1<<DDD3); // конфигурируем пины DDD7,DDD6,DDD5 и DDD3 на выход, на них будут 9 бит посылки и три бита ошибок ВАРТа
	DDR_LED  =  0b11111111;              // на выход ( на нем наши индикаторные светоды)
	TIMER0_init ();                      // инициализация и настройка модуля таймера Т0
	USART0_Init_9_N_1(MYUBRR);           // передаем рассчитанное значение скорости (MYUBRR) в блок инициализации  USART0
	uint16_t out_data = 0 ;              // двухбайтовый символ для отправки другому мк по USART0
	sei();
	
	while (1)
	{
		
	  if (sis_taimer == 100)             // системный таймер
	  {
		out_data = running_light();      // бегущий огонек загоняем в переменную на отправку другому МК
		USART_Transmit (out_data);       // отправляем байт другому мк
		sis_taimer =0;                   // сбросим таймер и ждем следующего тика системного таймера
			
	  }
	}
}

глаза боятся, а руки что то не делают))
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Сообщение sergo80zxc »

Не у кого нет никаких мыслей по этому поводу?
глаза боятся, а руки что то не делают))
Реклама
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

Не у кого нет никаких мыслей по этому поводу.
Видимо UART больше никто не использует (устарело).
Есть куча других интерфейсов и протоколов.
схема_1.jpg
(196.87 КБ) 161 скачивание
:tea:
Встал на лапы
Аватара пользователя
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Сообщение sergo80zxc »

roman.com, что то не могу себе представить, что UART не используется)))
сама программа работает, отправляет принимает, биты не теряются, просто хочу выяснить я где то схалтурил или такая особенность у микроконтроллеров атмеловских?
ну еще правда в даташите на 168 мегу приводится такая функция приема посылки о 9 битах

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

unsigned int USART_Receive( void )                     // Получим статус и 9-й бит, затем данные из буфера приемника
{
     unsigned char status, resh, resl;                 // объявим переменные
                                                     
     while ( !(UCSR0A & (1<<RXC0)) );                  // ожидаем завершения приема (получение данных)

     status = UCSR0A;                                  // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0)
     resh = UCSR0B;                                    // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 по счету бит (RXB80)
     resl = UDR0;                                      // считываем полученный 8 битный байт данных из регистра данных (UDR0)
                                                    
     if ( status & (1<<FE0)|(1<<DOR0)|(1<<UPE0) )      // проверяем установлены ли биты (FE0, DOR0, UPE0), если хоть один бит установлен, то выполняем код в скобках
     {                                                  
          return -1;                                   // ошибка приемопередачи модуля USART0 
     }     
                                                
	resh = (resh >> 1) & 0x01;                     // сместим байт (resh) на одну позицию вправо, тем самым бит принимаемых данных (RXB80) с 1 позиции в байте перейдет на 0 позицию,
	                                               // затем затем на этот байт  набросим маску 0x01 и все разряды обнулятся кроме нулевого разряда, в нем будет значение бита (RXB80)

    return ((resh << 8) | resl);                       // сместим бит (RXB80) в 9 по счету бит, а в восемь остальных младших бит поместим значение из (UDR0)

}
как может быть return -1 ? там же на выходе unsigned int? не понимаю....
короче я переделал эту функцию как по моему пониманию она должна работать

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

uint16_t USART_Receive( void )                 // прием 9-ти битной посылки в режиме (9-N-1). выдаем из функции через ретурн 2-х байтное слово
{  	                                           //                                             8-0-ой разряд ---------------------- младший байт посылки                               
	                                           //                                             9-ой разряд   ---  бит  (RXB80)   -- 9 бит посылки
	                                           //                                             10-ый разряд  ---  бит  (UPE0)    -- Флаг ошибки контроля четности
	                                           //	                                          11-ой разряд  ---  бит  (DOR0)    -- Флаг переполнения
	                                           //	                                          12-ий разряд  ---  бит  (FE0)     -- Флаг ошибки кадрирования
    while ( !(UCSR0A & (1<<RXC0)) );           // ожидаем завершения приема (  ПРИМЕНЯЕМ ЭТУ СТРОКУ, ЕСЛИ ФУНКЦИЯ РАБОТАЕТ НЕ В ПРЕРЫВАНИИ ПО ЗАВЕРШЕНИЮ ПРИЕМА)											   
											   
	uint8_t status, resh, resl, err_stat;      // объявим переменные

	status = UCSR0A;                           // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0)
	resh = UCSR0B;                             // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 бит (RXB80)
	resl = UDR0;                               // считываем полученый 8 битный байт данных из регистра данных (UDR0)
	
	status = (status >> 1) & 0x0E;             // сместим байт (status) на одну позицию вправо, тем самым бит (UPE0) со 2-го разряда перейдет в 1-ой, бит (DOR0) с 3-го
	                                           // во 2-ый, бит (FE0) с 4-го в 3-ой, затем на байт  набросим маску 0x0E и все разряды обнулятся кроме 1,2,3 в которых 
		                                       // теперь наши статусные биты (FE0, DOR0, UPE0)
	
	if (resh & 0x02)                           // проверяем 1 разряд переменной (resh) он же (RXB80) , если этот бит = 1, то выполняется выражение в скобках
	{
	   status |= (1<<0);                       // установить в 1 нулевой разряд переменной (status), остальные биты не трогаем        
	}
    else                                       // иначе если 1 бит переменной (resh) равен 0 , то выполняется выражение в скобках
	{
	   status &= ~(1<<0);                      // сбросить в 0  нулевой разряд  переменной (status), остальные биты не трогаем 
	}	
                                               // теперь в переменной (status) у нас биты:    0-ой разряд   ---  бит  (RXB80)
                                               //                                             1-ый разряд   ---  бит  (UPE0)
                                               //	                                          2-ой разряд   ---  бит  (DOR0)
                                               //	                                          3-ий разряд   ---  бит  (FE0)     
	
	return ((status << 8) | resl);             // сместим байт (status) в старший байт двухбайтового слова и получится такая картина--   
                                               //                                             9-ой разряд   ---  бит  (RXB80)   -- 9 бит посылки
                                               //                                             10-ый разряд  ---  бит  (UPE0)    -- Флаг ошибки контроля четности
                                               //	                                          11-ой разряд  ---  бит  (DOR0)    -- Флаг переполнения
                                               //	                                          12-ий разряд  ---  бит  (FE0)     -- Флаг ошибки кадрирования	                          	                                             	                                         	
	                                           // а в восемь остальных младших бит поместим значение из (UDR0)

может дело в этом? мне правда интересно разобраться в чем тут дело , товарищи полосатые кто обладает знанием подсобите?
глаза боятся, а руки что то не делают))
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

Сообщение B@R5uk »

На си писал очень давно и не под AVR. Поэтому не особо вникал в код. Плюс не совсем понятно поставлена вами задача, которую вы пытаетесь решить; и совершенно непонятно, какие действия вы проделывали, чтобы проверить, что вы хотя бы отправляете правильный сигнал по UART. И да, вы не привели схему вашего устройства.

Попытаюсь помочь экстрасенсорно. Для начала перепроверьте все ваши инициализации. Откройте даташит на МК (оригинал) и пройдитесь по всем управляющим регистрам и явно определите инициализируемые значения для ВСЕХ регистров UART (даже для казалось бы не используемых). Ни в коем случае не доверяйте указанным в даташите значениям по умолчанию, иногда они бывают другими, я лично на это натыкался.

Про логику вашей программы я ничего сказать не могу. Для проверки сигнала вы можете сделать следующее. Выставите скорость UART такой, чтобы длительность импульсов переключения была достаточно низкочастотной. Подключите через подходящий делитель на резисторах выход UART к звуковому входу компьютера и запишите сигнал в каком-нибудь аудиоредакторе (например, Sony Sound Forge). Внимательно изучите записанный сигнал и убедитесь, что в сигнале правильная последовательность импульсов правильной длины. Важно заметить, что иногда звуковые карты (особенно при записи через микрофонный вход, а не через линейный) инвертируют фазу сигнала. Это тоже надо проверить. Если у вас есть супернавороченный цифровой осциллограф, позволяющий записать сигнал, а потом изучить его в своё удовольствие со всеми подробностями — тем лучше.

Приведённый вами код совершенно неудобочитаем. Если хотите, чтобы кто-то в него серьёзно повникал, отредактируйте его так, чтобы не было переносов комментариев через строчку. Рекомендую включить в вашем редакторе кода ограничение в 80 символов (стандартная величина), и не выпускать код за это значение. Если в настройках нет ничего подобного, то можно прикинуть величину и уменьшить окно редактирования, так чтобы его размер указывал вам ограничение.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Сообщение sergo80zxc »

B@R5uk, дело в том, что в авр студии и в нотепаде код с комментариями как раз четнко в строчку со всеми пробелами и отступами, сюда вставляю и тут с переносами и тд.. В Notepad++ или в авр студии можно его открыть, чтоб аккуратным он был. это не устройство, просто тупо две 168 атмеги пересылают по 9-ти битному варту бегущий огонек, биты и байты не пропускаются, логическим анализатором в железе смотрю и на светодиодах индикации тоже вижу правильную последовательность бегущего огонька на обоих мк. задача простая, в железе проверить и изучить работу аппаратного варта на атмеге 168р. в протеусе тоже самое поведение

сишный файл прилагаю
Вложения
main.c
(14.39 КБ) 99 скачиваний
глаза боятся, а руки что то не делают))
Реклама
Ответить

Вернуться в «AVR»