Всем привет. Задумал я сделать одно устройство, которое будет измерять температуру в нескольких точках ( до 10 точек ) и в зависимости от этого регулировать ее с помощью исполнительных механизмов. *В качестве МК буду применять AVR. ( Какую конкретно, пока не решил, но макетка будет на Mega32 ) *Датчики температуры ds18b20 работающие по 1-wire и подключенные параллельно. *Устройство будет содержать клавиатуру. ( Пока не решил какую, но скорее всего такую http://www.ebay.com/itm/4-x-3-Matrix-Ar ... 5d365f41d7 или такую http://www.ebay.com/itm/MPR121-Capaciti ... 3395f54341 ) *Для вывода информации буду использовать дисплей от нокии3310 ( nokia 3510 ) *Писать буду на ассемблере ( СИ пока не изучал )
Перед тем как начать что-то делать, решил посоветоваться с Вами. Заодно хочу задать несколько вопросов...
0) Нет ли у кого готовой библиотеки для работы с ds18b20 написанной на асме? ( можно, как вариант, взять библиотеку, пригодную для моей цели и бог с ней на чем она написана.. ) Я бы не хотел тратить аппаратные ресурсы ( видел пример где для этих целей используют UART ) Вдруг мне что то пригодится - по этому лучше повесить на свободную ногу и организовать все программно.
1) Как лучше организовать работу с несколькими датчиками? В голову пока пришел только один вариант: Делаем на схеме кнопку - "обучение" И при установке устройства, нажимаем эту кнопку и по очереди подключаем датчики к схеме, соблюдая определенную последовательность. В это время МК считывает ИД датчиков и пишет их себе в ЕЕПРОМ. После обучения выключаем устройство. Выключаем кнопку "обучение" и снова включаем устройство. Теперь устройство само опрашивает данные датчики, обращаясь к каждому "по имени".... Такой вариант позволяет мне перепутать датчики местами при установке ( они ведь ни как не подписаны ) А так-же любой датчик можно безболезненно заменить на новый в случае если он выйдет из строя... Можете предложить еще варианты? ( например без использования ЕЕПРОМ )
Файл с программной реализацией протокола прикрепил. Ноги любые. Да, необходим этап пользовательского программирования, в ходе которого номера датчиков будут считываться и запоминаться.
А есть у кого ни будь библиотека для работы с LCD 3310 ( lcd 5110 ) написанная на ассеблере? Желательно что-бы библиотека содержала кирилицу, латиницу, арабские цифры и знаки пунктуации. В инете полно написанных на СИ, но на асме что то я найти не смог. Заранее Вам благодарен.
_________________ не зная броду не лезь к вольтмоду
НАПАЛМ, глянь вот в этом списке - http://vg.ucoz.ru/forum/15-324-1#5451 Я толком не разглядывал, просто накидал себе ссылок на будущее... Данный проект тоже должен работать с таким дисплеем, но за неимением оного подключил от NOKIA, для того что бы научится с датчиками температуры работать. А в дальнейшем самому понадобится библиотека на асме для дисплея 2004
_________________ не зная броду не лезь к вольтмоду
Взял готовую библиотеку от ВитГо ( библиотеку минимальной функциональности ) и решил ее модернизировать Но у меня не получилось, так как библиотека рассчитана на вывод знаков разрешением 4х7 пикселов. и некоторые буквы просто не влазят в такое разрешение ( например буквы "М" или "Щ" ) Следующий символ рисуется ровно через один пиксел ( отступ, что бы каши не было ). Отступы библиотека делает вправо после символа и вниз после строки. ( надеюсь понятно о чем я ? )
; ДРАЙВЕР МИНИМАЛЬНОЙ ФУНКЦИОНАЛЬНОСТИ ; для дисплеев на контроллере PHILIPS PCD 8544 (NOKIA 3310, 5110) ; автор Горбуков Виталий (Vitaly V Gorbukov) ; gorbukov@yandex.ru http://vg.ucoz.ru ; ;1. ОПИСАНИЕ ВЫЗОВОВ И ПРИМЕР ИСПОЛЬЗОВАНИЯ ДРАЙВЕРА ; ; Вызовы: ; ; LCD_INIT - инициализация дисплея ; ; LCD_POS (R17=X, R18=Y) - позиционирование вывода на экране (работает не на всех дисплеях) ; ; LCD_CHAR (R16=char) - вывод символа на дисплей ; ; ; ; ЗНАКОГЕНЕРАТОР дисплея содержит 17 символов: ; +-------+----+----+----+----+----+----+----+----+ ; |код |0x00|0x01|0x02|0x03|0x04|0x05|0x06|0x07| ; +-------+----+----+----+----+----+----+----+----+ ; |символ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ; +-------+----+----+----+----+----+----+----+----+ ; ; +-------+----+----+----+----+----+----+----+----+----------+ ; |код |0x08|0x09|0x0A|0x0B|0x0C|0x0D|0x0E|0x0F|0x10 | ; +-------+----+----+----+----+----+----+----+----+----------+ ; |символ | 8 | 9 | A | B | C | D | E | F | ' ' (пробел)| ; +-------+----+----+----+----+----+----+----+----+----------+ ; ; Символы рисуются на матрице 5х8 точек (4 вертикальных. линии на символ + 1 одна пустая ; линия как интервал между символами) ; ; Типовое использование библиотеки (текст программы) ;+----------+ ;|.include "m32def.inc" ; файл дефайнов вашего контроллера | ;| | ;|.CSEG | ;|.ORG 0x0000 | ;| RJMP START | ;| . . . . . таблица переходов по прерываниям . . . . . | ;|START: | ;| . . . . установка стека . . . . . | ;| . . . . . ваша инициализация . . . . . | ;| | ;| | ;| RCALL LCD_INIT ; инициализация дисплея | ;| | ;| LDI R16, 0x00 ; печать символа '0' | ;| RCALL LCD_CHAR | ;| | ;| LDI R16, 0x10 ; печать символа ' ' (пробел) | ;| RCALL LCD_CHAR | ;| | ;| ; позиционирование печати | | ;| LDI R18, 2 ;(Y) 3 строка (отсчет с 0) | ;| LDI R17, 40 ;(X) 41 линия по горизонтали | ;| RCALL LCD_POS | ;| | ;| LDI R16, 0x0F ; печать символа 'F' | ;| RCALL LCD_CHAR | ;| | ;| . . . . . продолжение программы . . . . . | ;| | ;|LOOP: | ;| rjmp LOOP ; пустой цикл (останов) | ;| | ;|.include "lcd5110mini.asm" ; подключение этой библиотеки | ;+----------+ ; ; ; ;2. ПОДКЛЮЧЕНИЕ ДИСПЛЕЯ И НАСТРОЙКА БИБЛИОТЕКИ ; ; ---------- ; ; ВНИМАНИЕ ! ; Обычно эти дисплеи питаются от 3.3 вольт, если вам необходимо питать дисплей от ; источника 5 вольт - поставьте последовательно с линией питаний два-три диода ! ; ; +----------+ ; | подключение дисплея | ; +----------+ ; Укажите к пинам каких портов подключены линии управления дисплеем: ; В примере ниже подключение произведено к порту D (порт вывода PORTD; порт настройки DDRD) ; соответственно, например для порта A это будут PORTA и DDRA, и так же для других портов) ; ; Линия управления сбросом дисплея (RST, RES. RESET) .equ RSTPORT =PORTb ; порт к которому подключен сигнал RST (RES, RESET) .equ RSTDDR =DDRb .equ RSTPIN =3 ; номер пина порта
; Линия последовательных данных дисплея (MOSI, DI) .equ MOSIPORT=PORTb ; порт к которому подключен сигнал MOSI (или DI) .equ MOSIDDR =DDRb .equ MOSIPIN =1 ; номер пина порта
; Линия управления видом данные\команды (DC, D/C) .equ DCPORT =PORTb ; порт к которому подключен сигнал DC (D/C) .equ DCDDR =DDRb .equ DCPIN =2 ; номер пина порта
; Линия тактирования данных (CLK, SCK, CLOCK) .equ CLKPORT =PORTb ; порт к которому подключен сигнал CLK (SCK, CLOCK) .equ CLKDDR =DDRb .equ CLKPIN =0 ; номер пина порта
; Линию выбора дисплея SCE (CS) дисплея подключить на землю ! ; ; Теперь после подключения дисплея нужно выбрать нужный вариант инициализации портов ввода вывода ; ; Если все линии управления (RST, MOSI, DC, CLK) подключены к одному порту ввода\вывода ; то расскоментируйте ниже DDR_ONE_LINE, иначе раскоментируйте DDR_MULTI_LINE ; ; работать модуль будет с любым из вариантов, но имейте ввиду что вариант DDR_ONE_LINE ; даст меньший размер кода при компиляции чем вариант DDR_MULTU_LINE на 2 байта ; ; ; ; ВНИМАНИЕ! Ниже используется инициализация при подключении дисплея к пинам одного порта ! ; поэтому расскомментирован вариант DDR_ONE_LINE !!! ; .MACRO DDR_INIT DDR_ONE_LINE ; разбивка по пинам одного порта ; DDR_MULTI_LINE ; разбивка по пинам разных портов .ENDMACRO
; Строка инициализации дисплея, не меняйте ее если не знаете что делаете ! ; последовательность инициализации для Nokia 5110, 3310
Как видно в массиве всего 4 столбца. Вот эти 4 столбца отвечают за символы состоящие из 4 пикселов в ширину. Если символы будут 5 пикселов в ширину, то и столбцов будет 5. ( Если из шести, то шесть соответственно - все просто.. ) Символы я рисую программой LFG ( LCD Font Generator )
вот пример получившегося массива, где символы состоят из 6 пикселов шириной
Для начала я попробовал просто заменить массив - не вышло, символы стали накладываться друг на друга.. ( этого и следовало ожидать... ) Я не знаю как устроен драйвер - нужно глубже разбираться - читай датащит на PCD8544 Но времени на это нет. Да и нет желания забивать этим голову. Хотелось пойти простым путем - взять готовое в интернете и просто попробовать... Тем более что в проекте будет установлен другой дисплей! Не судите строго меня за мою лень...
В общем... ( опять много воды лью, ближе к телу... к телу программы.. )
Я решил поискать в библиотеке параметр, который отвечает за ширину символа и исправить его на нужный...
LPM R16, Z+ RCALL LCD_SENDBYTE DEC R17 BRNE LCD_CHAR_LOOP
CLR R16 ; пробел между символами RCALL LCD_SENDBYTE
pop R17 pop ZH pop ZL RET
как видно я изменил значение "4" на "6" но и опять не помогло... Да, символы стали печататься полностью ( целиком ) и перестали печататься друг на друге! Но символы стали печататься не те что надо... Экспериментатор хренов...
Может подскажете какой параметр изменить, что бы можно было применить массив символов из шести пикселов шириной ???
Вложения:
Комментарий к файлу: Библиотека минимальной функциональности от ВитГо lcd5110RUS.asm [13 KiB]
Скачиваний: 537
_________________ не зная броду не лезь к вольтмоду
Мда... совсем запутался... Если изменять тот параметр, который меняю я, то библиотека правильно работает тока с первым символом. Остальные символы путаются с адресом. Выводится либо часть символа либо другой символ..
_________________ не зная броду не лезь к вольтмоду
Для определения позиции символа в таблице его значение нужно умножить на 6, а поскольку таблица большая, довольно быстро результат переполнит байт. Посмотрите набросок ниже.
Да, 32-ая умножать умеет. Я за основу взял драйвер написанный ВитГо для отладки схем. Драйвер минимальной функциональности. Драйвер был написан для работы со всеми мк семейства AVR. Изначально драйвер использовал умножение, но в связи с этим он не работал на ATtiny2313, которую я использовал в ходе своего обучения и ВитГо его переписал.
Цитата:
Для определения позиции символа в таблице его значение нужно умножить на 6
На шесть? Почему именно на шесть? Потому что теперь шесть столбцов? Ладно... Спасибо БОЛЬШОЕ, сейчас буду пробовать.
Цитата:
Код:
CLR R15
А что за регистр такой - R15 ???? Регистры R0-R15 обычно не юзают. Аж непривычно смотреть..
_________________ не зная броду не лезь к вольтмоду
А что за регистр такой - R15 ???? Регистры R0-R15 обычно не юзают. Аж непривычно смотреть..
All the register operating instructions in the instruction set have direct and single-cycle access to all registers. The only exception is the five constant arithmetic and logic instructions SBCI, SUBI, CPI, ANDI, ORI between a constant and a register and the LDI instruction for load immediate constant data. These instructions apply to the second half of the registers in the Register File (R16..R31). The general SBC, SUB, CP, AND, OR, and all other operations between two registers or on a single register apply to the entire Register File. Вот такая запись присутствовала в DS на первые камни AVR. Т.е. работать с R0...R15 можно со всеми другими командами, кроме вышеперечисленных. По мне, ущербность этих регистров небольшая, поэтому активно их использую.
Пытаюсь использовать библиотеку, которую дал мне выше НАПАЛМ. Обратил внимание на то, что библиотека написана для DS1820. Я же собираюсь использовать DS18B20. На сколько я знаю это разные датчики, но суть у них одна. Так что, по большому счету, библиотека должна подойти.
Попялился я немного в код библиотеки и понял, что данные полученные с датчика содержаться в регистре R0. Данные для отправки также должны содержаться в регистре R0. Вопрос в том как их туда запихнуть ? ( Дело в том, что я ни разу ни чего не записывал в регистры R0-R15 ) например делать вот так нельзя: ldi R0, 0x44 и вот так нельзя ldi R16, 0x44 mov R0, R16 Как же тогда быть ?
код библиотеки Спойлер
Код:
; команды для работы с датчиком DS1820
.equ CMD_SEARCH_ROM = 0xF0 ; поиск адресов всех устройств по спецалгоритму .equ CMD_READ_ROM = 0x33 ; считываение адреса единственного устройства .equ CMD_MATCH_ROM = 0x55 ; активация конкретного устройства по его адресу .equ CMD_SKIP_ROM = 0xCC ; обращение к единственному на шине устройству без указания его адреса ; .equ CMD_ALARM_SEARCH = 0xEC ; поиск устройств, у которых сработал ALARM (алгоритм поиска как у CMD_SERCH_ROM) .equ CMD_CONVERT_T = 0x44 ; старт преобразования температуры .equ CMD_W_SCRATCHPAD = 0x4E ; запись во внутренний буфер (регистры) .equ CMD_R_SCRATCHPAD = 0xBE ; чтение внутреннего буфера (регистров) .equ CMD_C_SCRATCHPAD = 0x48 ; сохранение регистров в EEPROM ; .equ CMD_RECALL_EE = 0xB8 ; заносит в буфер из EEPROM значение порога ALARM ; .equ CMD_READ_POWER = 0xB4 ; определение, есть ли в шине устройства с паразитным питанием
;используемые порты и регистры ;перед началом работы необходимо настроить выбранную линию порта ;на работу в качестве входа без подтягивающего резистора, т. е. DDRx=0 PORTx=0
.equ wireport = DDRB ; порт вывода 1-Wire .equ wirepin = PinB ; порт сигнальных линий 1-Wire .equ wirebit = 4 ; номер пина линии порта 1-Wire (PB4) ( 0b00010000 - команда CBI (SBI) работает с десятиричными цифрами ) .equ wirePORTx = PORTB
.def wiretemp = R25 ; temp регистр для 1-Wire .def wireres = R2 ; регистр из числа r0...r15
; задержка повышенной точности в 1 микросекунду c учетом длительности RCALL и RET ; rcall (им вызываем эту задержку) дает 3 + 9 nop + 4 ret = 16 ; 1 микросекунда при 16МГц не использует никаких регистров
nop nop nop nop nop nop nop nop nop ret
delay10us:
; задержка повышенной точности в 10 микросекунд, основана на delay1us ; rcall (им вызываем эту задержку) дает 3 + 11 команд вне цикла + (6*(16+3+2)+16+3+1)=146 дает сам цикл ; Итого 160 тактов = 10 микросекунд
push wiretemp ldi wiretemp, 7
delay10us_loop:
rcall delay1us dec wiretemp nop nop brne delay10us_loop pop wiretemp nop nop ret
delayus:
; задержка в wiretemp*10 микросекунд, повышенной точности не требуется ; на входе - wiretemp, где записано число десятков секунд (wiretemp изменяется)
dec wiretemp
delayus_loop:
rcall delay10us dec wiretemp brne delayus_loop rcall delay1us rcall delay1us
ret
;====================
Init_1W:
; выполняет сброс линии и выдает наличие сигнала присутствия PRESENCE от датчика ; при наличии сигнала присутствия взводим Z-флаг, иначе сбрасываем его
cbi wirePORTx, wirebit ; PORTx=0 cbi wireport, wirebit ; 0->DDR = Z-состояние sbis wirepin, wirebit ; проверим наличие 1 в линии rjmp presence_fault ; если нет - это ошибка sbi wireport, wirebit ; иначе давим линию в 0 ldi wiretemp, 48 ; задержка в 480 микросекунд rcall delayus cbi wireport, wirebit ; отпускаем линию, 0->DDR = Z-состояние ldi wiretemp, 6 ; задержка в 60 микросекунд rcall delayus
; начинаем ждать сигнал присутствия PRESENCE ; Датчик должен прижать линию к земле втечение 240 мкс
ldi wiretemp, 250 ; ждем с запасом - 240 max
presence_wait:
sbis wirepin, wirebit ; Проверка линии на 1, если появляется 0, то всё ОК rjmp presence_ok ; и переходим на presence_ok rcall delay1us dec wiretemp brne presence_wait
; выполняет прием байта из линии ; на входе ничего, на выходе R0 - принятый байт
ser wiretemp ; wiretemp <- 0xFF mov r0, wiretemp
Send_1W:
; выполняет передачу байта в линию ; вход: R0 - выводимый байт ; выход: R0 - то, что удалось ВВЕСТИ из линии ; портит: R0 ; примечание: если делать ВЫВОД 0хFF, то на выходе будет ПРИНЯТЫЙ байт
ldi wiretemp, 8 ; число битов в байте
sw1_next:
push Temp1 in Temp1, SREG push Temp1 ; сохраним флаги, т.к. будем запрещать прерывания
push wiretemp ldi wiretemp, 9 ; в некоторых случаях может потребоваться
; увеличить это значение, но не более 13! sw1_wait:
rcall delay1us dec wiretemp brne sw1_wait clc sbic wirepin, wirebit sec ror wireres ; Если линия была в нуле, то в бит 7 R2 запишется 0, ; а если линия была в единице, то в бит 7 R2 запишется 1 ldi wiretemp, 9 rcall delayus ; 90 микросекунд - длительность тайм-слота cbi wireport, wirebit ; 0->DDR = Z-состояние pop wiretemp
pop Temp1 out SREG, Temp1 pop Temp1
dec wiretemp brne sw1_next mov r0, wireres
ret
;====================
ReadBytes_1W:
; считывает 9 байтов в буфер, подсчитывает CRC ; изменяет R0 и SREG, регистры X и Z
st X+, r0 ; сохраняем принятый байт rcall crc8 ; считаем контрольную сумму pop wiretemp dec wiretemp brne r1w_next ret
CRC8:
; выполняет подсчет CRC по алгоритму 1-Wire ; на входе r0 - считанный байт ; на выходе CRC - содержит подсчитанную сумму ; портит регистр Z, R0 сохраняется ; примечание: перед первым вызовом CRC необходимо обнулить
Спасибо, Jack_A! Я раньше ни когда не использовал регистры R0-R15. Пытался вчерашним ночером погуглить, как с ними работать, но ни чего внятного не нашел. Можно было почитать датащит. Но он не очень то и понятлив для понимания... Хотелось найти хоть какой то пример... Но "дешевле" для нервов оказалось разместить вопрос тут.
Есть еще один интересный вопрос по этому датчику. В датащите ( в том который я прикрепил выше ) написано:
Цитата:
Выходные температурные данные DS18B20 калиброваны в градусах Цельсия. Температурные данные запоминаются как 16-битовое число со знаком (см. рис. 2). Биты признака (S) указывают, является ли температура положительная или отрицательная: для положительных S = 0, а для отрицательных чисел S = 1.
Все просто и понятно! НО !!! Ниже приведена схема, которая вынесла мне мозг. Какие я математические манипуляции не производил, так и не смог понять каким методом можно вычислить такие же отрицательные температуры. Думаю, что это банальная ошибка тех, кто составлял этот датащит ( или переводчик накосячил ) Я думаю, что должно быть так как я отметил красным шрифтом справа.
_________________ не зная броду не лезь к вольтмоду
Последний раз редактировалось uwrtey Сб окт 17, 2015 11:16:32, всего редактировалось 4 раз(а).
uwrtey В DS всё правильно, если учесть, данные представлены с дискретом 0,0625 °С, т.е. увеличенные в 16 раз. Например 1111 1111 1111 1000 -> запомним знак минусового результата -> инвертируем, получаем 7 -> прибавляем 1, получаем 8 -> 8/16=0,5 -> добавляем знак -> получаем -0,5 °С.
В тырнете нашел вот такие примеры примеры записи данных в R0
1) Копирование из регистра R1.
Код:
mov R0, R1 ;
Но меня засмущал регистр R1. Я не был уверен, что это правило относится и к регистрам R16-R31. Но Jack_A развеял сомнения.
2) с использованием переменной.
Код:
.dseg ; оперативка
var1: .byte 1 ; переменная var1 - 1 байт
.cseg
ldi r16, 0x44 sts var1, r16 lds r0, var1
Вариант с адресами то-же хорош
Код:
.dseg ; оперативка
var1: .byte 1 ; переменная var1 - 1 байт
.cseg
LDI YH,HIGH(var1) ; копируем старший байт адреса ОЗУ с меткой var1 LDI YL,LOW(var1) ; копируем младший байт адреса ОЗУ с меткой var1 LD R0,Y ; копируем данные в регистр R0 из памяти по адресу находящемуся в регистровой паре Y ;или LDD R0,Y+0 ;
Все это хорошо при работе с переменными. Мне же нужно грузить в регистр R0 команды для DS18B20. Команды записаны в библиотеке в виде констант. Мне ни чего не мешает использовать варианты приведенные выше, но хочется знать есть ли вариант с использованием констант. По сути константы тоже находятся где-то в памяти и вариант с адресами должен работать и с константами ???
.equ CMD_SEARCH_ROM = 0xF0 ; поиск адресов всех устройств по спецалгоритму .equ CMD_READ_ROM = 0x33 ; считываение адреса единственного устройства .equ CMD_MATCH_ROM = 0x55 ; активация конкретного устройства по его адресу .equ CMD_SKIP_ROM = 0xCC ; обращение к единственному на шине устройству без указания его адреса ; .equ CMD_ALARM_SEARCH = 0xEC ; поиск устройств, у которых сработал ALARM (алгоритм поиска как у CMD_SERCH_ROM) .equ CMD_CONVERT_T = 0x44 ; старт преобразования температуры .equ CMD_W_SCRATCHPAD = 0x4E ; запись во внутренний буфер (регистры) .equ CMD_R_SCRATCHPAD = 0xBE ; чтение внутреннего буфера (регистров) .equ CMD_C_SCRATCHPAD = 0x48 ; сохранение регистров в EEPROM ; .equ CMD_RECALL_EE = 0xB8 ; заносит в буфер из EEPROM значение порога ALARM ; .equ CMD_READ_POWER = 0xB4 ; определение, есть ли в шине устройства с паразитным питанием
; вот так можно делать? LDI YH,HIGH(CMD_CONVERT_T) ; копируем старший байт адреса CMD_CONVERT_T LDI YL,LOW(CMD_CONVERT_T) ; копируем младший байт адреса CMD_CONVERT_T LD R0,Y ; копируем данные в регистр R0 из памяти по адресу находящемуся в регистровой паре Y
**********************************
Другой вопрос относительно вычисления отрицательных значений.
Цитата:
В DS всё правильно, если учесть, данные представлены с дискретом 0,0625 °С, т.е. увеличенные в 16 раз. Например 1111 1111 1111 1000 -> запомним знак минусового результата -> инвертируем, получаем 7 -> прибавляем 1, получаем 8 -> 8/16=0,5 -> добавляем знак -> получаем -0,5 °С.
Ладно шутки шутками, но тут я опять затупил. В библиотеке написано, что для чтения данных с датчика используется регистр R0.
Код:
Send_1W:
; выполняет передачу байта в линию ; вход: R0 - выводимый байт ; выход: R0 - то, что удалось ВВЕСТИ из линии ; портит: R0 ; примечание: если делать ВЫВОД 0хFF, то на выходе будет ПРИНЯТЫЙ байт
а как же принять значения температуры, если данные о температуре выдаются в линию в виде двух байт?
_________________ не зная броду не лезь к вольтмоду
Последний раз редактировалось uwrtey Сб окт 17, 2015 22:51:51, всего редактировалось 1 раз.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 576
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения