А. С. Каракулов, Д. С. Аксенов, Б. В. Арещенко, Саидов В. С. Разработка программного обеспечения для систем управления электрическими двигателями



страница1/9
Дата24.04.2016
Размер1.7 Mb.
  1   2   3   4   5   6   7   8   9

Версия 13 февраля 2008 г.___________________________

Федеральное агентство по образованию

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

и радиоэлектроники (ТУСУР)



А.С.Каракулов, Д.С.Аксенов, Б.В.Арещенко, Саидов В.С.


Разработка программного обеспечения для систем управления электрическими двигателями

Учебно-методическое пособие

Томск 2007

Аннотация
В данном пособии авторами (коллективом из ведущих специалистов ЗАО “ЭлеCи” и магистрантов кафедры ЭС ТУСУР) предлагается информация по реализации последовательного процесса сборки программного обеспечения (ПО). Предполагается, что изначально процесс отладки ПО идет на встроенных в него математических моделях реальных устройств (двигателя, преобразователя, датчиков), после чего происходит замена драйверов виртуальных устройств на драйверы реальных периферийных устройств процессора. Такой подход позволяет разрабатывать, во первых, программное обеспечение без наличия реальных электронных и электромеханических компонентов, и, во вторых, процедуры, выработанные при подобной технологии, являются практически платформонезависимыми, что позволяет переносить их на другие процессоры. Пособие составлено на основе информации, открыто предоставляемой производителями специализированных сигнальных процессоров.

Предполагается, что пользователь данного пособия имеет некоторые навыки разработки программного обеспечения, а также знаком со спецификой в такой области техники, как электропривод и его компоненты.



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

  1. Фильтрацию сигналов обратной связи и восстановление координат.

  2. Управление ключами силового преобразователя и формирование управления на двигатель.

  3. Осуществление защиты преобразователя, двигателя, механизма.

  4. Коммуникации с АСУ верхнего уровня и с собственными периферийными устройствами.

  5. Выполнение расчета управления технологическим контуром с формированием заданий на скорость и момент двигателя в зависимости от внешних условий.

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

Исходя из требований к минимальным затратам на аппаратную реализацию и временные ограничения на разработку программного обеспечения, разработчик вынужден обеспечивать выполнение следующих условий:



А) Для целей повышения эффективности работы самого устройства:

  • решение задач в режиме реального времени с требуемой периодичностью и заданной скоростью;

  • обеспечение параллельности вычислений;

  • использование минимального объёма памяти, ограниченного с точки зрения быстродействия процессора.

Б) Для повышения качества и снижения времени разработки программного обеспечения:

  • обеспечение легкой масштабируемости приложений при адаптации к конкретным требованиям устройства;

  • обеспечение тестируемости программного обеспечения (в том числе и при отсутствии аппаратной части системы);

  • обеспечение переносимости разработанного программного продукта на другую аппаратную платформу.

Традиционно разработки сложных программных комплексов содержат следующие этапы:

  1. Разработка библиотеки процедур, которая позволяет реализовать требуемые функции в соответствии с принятым стандартом разработки приложений. Стандарт оговаривает индивидуальные особенности каждого создаваемого приложения: потребляемые ресурсы памяти и число тактов расчета, периодичность запуска, интерфейс взаимодействия с другими процедурами.

  2. Разработка механизма разделения ресурса процессорного времени системы между приложениями.

  3. Разработка механизма взаимодействия процедур системы через определение применяемых процедур и потоков данных между ними (шаблон приложений).

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

Примером существующих решений для встроенных систем на базе сигнальных процессоров можно назвать технологию «eXpressDSP» от корпорации Texas Instruments (США) . Данная технология поддерживает процессоры TMS320 серий С6000, С5000, С2000, и в ней достаточно полно реализованы этапы 1-3. В данном пособии будет рассмотрено применение некоторых ключевых моментов данной технологии для создания программного обеспечения систем управленя электродвигателями для процессоров серии С2000 TMS320F28xx.
Среда программирования CodeComposerStudio. Использование симулятора
Среда программирования CodeComposerStudio (CCS) предназначена для создания программного обеспечения, запускаемого на DSP-процессорах фирмы Texas Instruments. CCS содержит все необходимые инструменты для набора и редактирования программ, конфигурирования ядра реального времени DSP|BIOS, получения машинного кода с использованием компилятора языка С, загрузки машинного кода в процессор, запуска и отладки программ, в том числе и в режиме реального времени. CCS позволяет работать как с реальным устройством, так и его моделью в режиме симулятора. Симулятор позволяет заниматься отладкой программного обеспечения без наличия реального процессора, но при этом не поддерживает периферийные устройства на борту процессора и осуществляет вычисления со скоростью, отличной от скорости реального процессора. Таким образом, при работе с симулятором скорость выполнения программы будет в несколько раз меньше (поскольку компьютеру приходится моделировать работу всех системных устройств архитектуры ядра процессора), входные сигналы возможно только смоделировать, выходные сигналы не могут быть физически переданы во внешний мир и могут наблюдаться только по значениям переменных, невозможно смоделировать многозадачность. Однако для отработки логики работы расчетных процедур и некоторых других случаев симулятор оказывается доступным инструментом.

Изначально необходимо  с помощью утилиты CodeComposerStudioSetup ввести в CCS применяемые устройства. На рисунке 1 (слева) показано, что CCS может работать с отладочной платой eZdsp и симулятором процессора F2812.



Рис.1
После запуска CCS в появившемся окне Parallel Debug Manager необходимо выбрать устройство, с которым будет происходить работа (в нашем случае это F2812 Device Simulator, см.рис.2).


Примечание. Для установки драйвера платы eZdsp необходимо воспользоваться диском, поставляемым с платой. Драйвер с диска устанавливается поверх установленной версии CCS.

Рис.2
После запуска основного окна CCS необходимо создать проект, создать текст программы, подключить его к проекту, оттранслировать, загрузить его в память, запустить на исполнение, убедиться в правильности выполнения программы.



Ниже приведены инструкции по созданию простейшего приложения, позволяющего продемонстрировать работу простейшего цифрового фильтра.

  1. Создать проект Project-New… В появившемся окне указать имя проекта, зафиксировать каталог проекта.

  2. Создать текстовый файл File-New и ввести в него следующий код программы:


//для использования чисел с плавающей запятой

#include

#include
//объявление переменных программы

float t=0, //время

u, //входной сигнал

filtr=0, //отфильтрованный сигнал

k0=0.1, // коэффициент фильтра k0

k1=0.9; // коэффициент фильтра k1
void main()

{

while(1)// организация безусловных циклов вычислений

{ // начало цикла

t=t+0.1; // имитация времени

u=50*sin(t)+15*sin(100*t);// входной сигнал

filtr=k0*u+k1*filtr;// отфильтрованный сигнал

} // конец цикла

}


  1. Сохранить данный файл под именем sim_1, в качетсве типа файла выбрать из предложенного C/C++ Source file (*.c). Сохранение должно быть выполнено в каталог проекта.

  2. Добавить только что сохраненный файл исходного текста программы в проект с помощью меню Project-Add files to project.

  3. Добавить в проект аналогичным образом файл библиотеки rts2800.lib

  4. Открыть окно настроек CCS через Option-Customize и на закладке Program|Project Load установить галочку для свойства Load Program After Build.

  5. Выполнить трансляцию проекта через нажатие F7 или Project-Build. В случае успешного завершения трансляции и компоновки в появившемся окне сообщений будет показано:

----------------------------- sim_1.pjt - Debug ----------------------

Build Complete,

0 Errors, 0 Warnings, 0 Remarks
После чего произойдет загрузка программы в память модели процессора.

  1. Если программа содержит ошибки, их необходимо исправить и повторить трансляцию.

  2. Для наблюдения за программой необходимо вывести окно WatchWindow, на нем открыть закладку Watch1, в клетки окна ввести переменные u и t.

  3. Для наблюдения за формой изменения сигналов необходимо открыть графическое окно через View-Graph-TimeFrequency, в окне настроек сделать изменения согласно приведенному ниже окну (свойства Display Type – Dual Time, Start address – upper display - &u, Start address – lower display - &filtr, Acquisition Buffer Size – 1, DSP Data type – 32-bit floating points, см.рис.3).

  4. Для отладки кода необходимо установить точку зондирования. Для этого необходимо щелкнуть левой клавишей мыши по строчке программы «t=t+0.1», затем правой клавишей и в появившемся контекстном меню выбрать Toggle Software Probe Point. Зелено-голубая точка появится слева от строчки, показывая место установки точки зондирования (при выполнении данной строчки будет происходить обновление показаний привязанных к данной точке окон).

  5. Для привязки данной точки зондирования к окнам отображения графиков и переменных (WatchWindow) необходимо вызвать окно привязки через Debug-ProbePoints, в появившемся окне щелкнуть мышью по слову NoConnection (для автоматической установки поля Location), после этого в поле Connect To выбрать Watch Window, нажать на окне кнопку Add. Аналогичным образом добавить вывод на графический дисплей. Нажать Ок.



Рис.3



  1. Для перезагрузки программы выполнить Project-Build.

  2. Запустить программу клавишей F5 или через Debug-Run.

Результатом работы программы должно быть окно, показанное ниже(графический экран и WatchWindow показывают изменения переменных), см. рис.4:

Рис.4
Далее показан более сложный пример использования симулятора. В примере показана система позицирования между двумя конечными положениями (лифт на 2 этажа), созданная на основе модели двигателя постоянного тока, ПИ-регулятора скорости, контура положения на базе П-регулятора и логической системы управления.



В примере создается зацикленный расчет работы системы. Происходит моделирование времени, работы двигателя постоянного тока, далее происходит расчет регуляторов скорости и положения, в завершение – система логического управления на основе смены состояний режимов работы в зависимости от координат системы и команд. Пример показывает возможность отладки программного обеспечения без наличия реальной системы управления, при этом затрагиваются основные моменты разработки процедур управления. Нижнее положение соответствует значению «0» в переменной pos, верхнее – «10». Срабатывание кнопок происходит при вводе в соответствующие переменные значения «1».
#include // в файле используются расчеты с плавающей запятой
// декларирование используемых переменных

float t=0,dt=0.001;

float w=0,i=0,u=0,R=3.6,L=0.034,Mc=1,Me=0,c=1.82,J=0.038,Mload;

float k0=2+0.001/0.01,k1=2,input=0,input_prev=0,output=0,w_error=0;

float w_set=0;

float pos_set=0,pos=0,pos_error;

int down_button=0,stop_button=0,up_button=0,mode=0;

int up_lamp=0,down_lamp=0,down_move_lamp=0,up_move_lamp=0;

void main()// процедура расчета

{

m1: // начало цикла

// модель времени

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

t=t+dt;
// модель двигателя постоянного тока

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

i=i+(u-R*i-c*w)/L*dt; // вычисление тока

Me=i*c;// вычисление крутящего момента

w=w+(Me-Mload)/J*dt;//вычисление скорости

pos=pos+w*0.1;//вычисление положения
// модель реактивной нагрузки (лифт с противовесом)

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

if (w<0) Mload=-Mc;else

if (w>0) Mload=Mc;else Mload=0;
// регулятор скорости

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

w_error=w_set-w;// расчет ошибки

input=w_error;// передача сигнала ошибки на вход регулятора

output=output+k0*input-k1*input_prev;// расчет регулятора

input_prev=input;//запоминание текущего значения как

// предыдущего

// для следующего цикла расчета

if (output>220) output=220; // ограничение

// максимального значения

if (output<-220) output=-220;
u=output; //соединение сигнала регулятора

// и напряжение якоря двигателя
// регулятор положения

//--------------------------------------------------------------------
pos_error=pos_set-pos;// расчет ошибки

w_set=pos_error*0.25;// расчет положения

// и передача задания на

// регулятор скорости
// управление сигнализацией положения

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

if (pos<1) down_lamp=1;else down_lamp=0;// лампа

//нижнего положения

if (pos>9) up_lamp=1;else up_lamp=0; // лампа

//верхнего положения
// режим работы «остановлен»

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

if (mode==0)

{

pos_set=pos_set;

u=0;//обесточиваем двигатель

w_set=0;//останавливаем регулятор скорости

down_move_lamp=0; // выключили лампы

// движения вниз

up_move_lamp=0; // выключили лампы

//движения вверх

if (up_button==1) mode=1; //реакция на

//нажатие

//кнопки up

if (down_button==1) mode=2; //реакция

//на нажатие

//кнопки down

if (stop_button==1) mode=0; // реакция

// на нажатие

// кнопки stop

}
// режим подъема

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

if (mode==1)

{

up_move_lamp=1; // включили лампы

//движения вверх

down_move_lamp=0; // выключили лампы

//движения вниз

pos_set=10;// задание целевого положения

if (up_button==1) mode=1; //реакция

// на нажатие

// кнопки up

if (down_button==1) mode=0; //реакция

//на нажатие

// кнопки down

if (stop_button==1) mode=0; // реакция

// на нажатие

// кнопки stop

if (pos>pos_set) mode=0;// требуемое

//положение достигнуто

}
// режим опускания

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

if (mode==2)

{

up_move_lamp=0; // выключили

//лампы движения вверх

down_move_lamp=1; // включили

//лампы движения вниз

pos_set=0; // задание целевого положения

if (up_button==1) mode=0; //реакция

// на нажатие кнопки up

if (down_button==1) mode=2; //реакция

// на нажатие кнопки down

if (stop_button==1) mode=0; // реакция

// на нажатие кнопки stop

if (pos

//положение достигнуто

}
goto m1;//конец цикла

}
При запуске программы и имитации включения кнопок возможно отслеживание отработки положения и срабатывания ламп сигнализации через окно WatchWindow. На графике, приведенном на рисунке 5, выводятся осциллограммы тока якоря и скорости.
Внимание! В представленной системе содержатся ошибки различного характера (как минимум 3), которые не позволяют применить разработанную систему для управления реальным лифтом с гарантией обеспечения безопасности доставки груза. В качестве задания для самостоятельной работы предлагается выявить эти ошибки и предложить способы по их устранению, а также установить в данную систему ПИ-регулятор тока.

Рис.5


Разработка шаблона программного обеспечения
Ниже будет показано, каким образом с «нуля» можно собрать готовый проект в CCS. Проект при компиляции будет создавать программу, которая заставляет мигать светодиод, подключенный к пину процессора IOPF14. При этом будет показано, как собирать проект для загрузки в ОЗУ и флеш, без использования операционной системы реального времени DSP/BIOS. Создано на основе материала spra928f.pdf и spra958f.zip (исходные файлы), с сайта www.ti.com.

Необходимое оборудование – CCS версии 3.x c DSP/BIOS версии 5.20, плата eZdsp или другая с сигнальным процессором TMS320F2812.

Файлы и подкаталоги будут размещены в каталоге D:\template\ , к данному документу прилагается файл с архивом использованных файлов (полученный в результате выполнения данной инструкции).

Итак, создаем самый простой вариант шаблона – без использования операционной среды реального времени DSP|BIOS, с загрузкой в RAM. Для этого открываем CCS, создаем проект под названием RAM_nonBIOS. Предложенный CCS отдельный каталог для проекта следует удалить, так как большинство файлов для всех проектов будут едины:


Рис.6
Создаем каталоги src (для с-файлов), include (для h-файлов), cmd (для командных файлов распределения памяти), DSP281x_headers (для h-файлов периферии и системных устройств процессора).


Рис.7
Создаем новый исходный файл и сохраняем его в каталог src под именем main.c. Тип файла не выбирать, в названии сохраненного файла вводить имя с расширением. В файл вводим текст программы:



void main()

{

while(1);

}
Особенностью программирования встроенных систем на микроконтроллерах является необходимость распределения памяти программистом. При программировании DSP принято проводить распределение памяти за счет добавления двух
cmd-файлов :

  1. f2812_nonBIOS_ram.cmd – файл распределения памяти программ и памяти данных.

  2. DSP281x_Headers_nonBIOS.cmd – файл указания положения специальных регистров процессора (регистры управления периферией процессора, системные регистры и т.д.)

Помещаем файл f2812_nonBIOS_ram.cmd в каталог cmd. Он состоит из двух частей MEMORY и SECTIONS.

В разделе MEMORY показаны начальные адреса и емкость возможных для использования ресурсов памяти процессора. Карта памяти находится в файле sprs174n.pdf, глава 3.1. Memory map.

В разделе SECTIONS назначается соответствие между указанными ранее блоками памяти и секциями, сгенерированными компилятором при компилировании проекта.

Секции бывают следующие (согласно файлу spru514.pdf, глава 7):

Инициализируемые (с присваиванием начальных значений при загрузке в память):

.text – содержит исполняемый код и константы

.cinit и .pinit – содержит таблицы, в которых находятся значения начальной инициализации переменных (например, инициализируемых в программе как int a=5;)

.const - инициализация констант

.econst – инициализация констант (для языка С)




Рис.8
Неинициализируемые (без присваивания начальных значений при загрузке программы в память):

.bss – глобальные и статические переменные;

.ebss – глобальные и статические переменные (используются в языке C);

.stack – системный стек (для сохранения контекста процессора при вызове процедур);

.sysmem – для динамического выделения памяти, используется malloc-функцией;

.esysmem – для динамического выделения памяти, используется malloc-функцией .

Соответственно неинициализируемые секции нужно располагать в ОЗУ, а инициализируемые – в ОЗУ или ПЗУ.

Помещаем файл DSP281x_Headers_nonBIOS.cmd в каталог cmd. Он также состоит из двух частей: MEMORY и SECTIONS. В этом файле расписано расположение системных регистров и регистров управления периферией. Физическое расположение адресов, а также назначение регистров управления периферией расписано в следующих файлах (расширения pdf), см.таблицу 1:


Таблица 1

SPRU051

TMS320F28x Serial Communication Interface (SCI) Peripheral Reference Guide

SPRU712

TMS320F28x Serial Communication Interface (SCI) Peripheral Reference Guide

SPRU716

TMS320x280x Analog to Digital Converter (ADC) Module Reference Guide

SPRU721

TMS320x280x DSP Inter-Integrated Circuit (I2C) Module Reference Guide

SPRU722

TMS320x280x DSP Boot ROM Reference Guide

SPRU790

TMS320x280x Enhanced Quadrature Encoder Pulse (eQEP) Module Reference Guide

SPRU791

TMS320x280x Enhanced Pulse Width Modulator (ePWM) Module Reference Guide

SPRU807

TMS320x280x Enhanced Capture (eCAP) Module Reference Guide

SPRU059

TMS320F28x Serial Peripheral Interface (SPI) Peripheral Reference Guide

SPRU074

TMS320F28x Enhanced Controller Area Network (eCAN) Peripheral Reference Guide

SPRU060

TMS320F28x Analog-to-Digital Converter (ADC) Peripheral Reference Guide

SPRU095

TMS320F28x Boot ROM Peripheral Reference Guide

SPRU065

TMS320F28x Event Manager (EV) Peripheral Reference Guide

SPRU067

TMS320F28x External Interface (XINTF) Peripheral Reference Guide

Периферийные регистры объединены в структуры по функциональному принципу (менеджер событий, АЦП, SCI и т.д.).

Например, регистры управления аналого-цифровым преобразователем (согласно файлу DSP281x_Adc.h) объединены в структуру ADC_REGS (справа в комментариях подписаны назначения регистров):
struct ADC_REGS {

union ADCTRL1_REG ADCTRL1; // ADC Control 1

union ADCTRL2_REG ADCTRL2; // ADC Control 2

union ADCMAXCONV_REG ADCMAXCONV;

// Max conversions

union ADCCHSELSEQ1_REG ADCCHSELSEQ1;

// Channel select sequencing control 1

union ADCCHSELSEQ2_REG ADCCHSELSEQ2;

// Channel select sequencing control 2

union ADCCHSELSEQ3_REG ADCCHSELSEQ3;

// Channel select sequencing control 3

union ADCCHSELSEQ4_REG ADCCHSELSEQ4;

// Channel select sequencing control 4

union ADCASEQSR_REG ADCASEQSR;

// Autosequence status register

Uint16 ADCRESULT0; // Conversion Result Buffer 0

Uint16 ADCRESULT1; // Conversion Result Buffer 1

Uint16 ADCRESULT2; // Conversion Result Buffer 2

Uint16 ADCRESULT3; // Conversion Result Buffer 3

Uint16 ADCRESULT4; // Conversion Result Buffer 4

Uint16 ADCRESULT5; // Conversion Result Buffer 5

Uint16 ADCRESULT6; // Conversion Result Buffer 6

Uint16 ADCRESULT7; // Conversion Result Buffer 7

Uint16 ADCRESULT8; // Conversion Result Buffer 8

Uint16 ADCRESULT9; // Conversion Result Buffer 9

Uint16 ADCRESULT10; // Conversion Result Buffer 10

Uint16 ADCRESULT11; // Conversion Result Buffer 11

Uint16 ADCRESULT12; // Conversion Result Buffer 12

Uint16 ADCRESULT13; // Conversion Result Buffer 13

Uint16 ADCRESULT14; // Conversion Result Buffer 14

Uint16 ADCRESULT15; // Conversion Result Buffer 15

union ADCTRL3_REG ADCTRL3; // ADC Control 3

union ADCST_REG ADCST; // ADC Status Register

};
Соответственно, каждый такой регистр структуры раскладывается в подструктуру, например:

struct ADCTRL1_BITS { // bits description

Uint16 rsvd1:4; // 3:0 reserved

Uint16 SEQ_CASC:1; // 4 Cascaded sequencer mode

Uint16 SEQ_OVRD:1; // 5 Sequencer override

Uint16 CONT_RUN:1; // 6 Continuous run

Uint16 CPS:1; // 7 ADC core clock pre-scalar

Uint16 ACQ_PS:4; // 11:8 Acquisition window size

Uint16 SUSMOD:2; // 13:12 Emulation suspend mode

Uint16 RESET:1; // 14 ADC reset

Uint16 rsvd2:1; // 15 reserved

};

Таким образом, для возможности обращения к регистру либо целиком как к 16-разрядному значению, либо “побитно” вводится тип объединения union (один и тот же физический адрес расписывается либо как число, либо как отдельные биты):



union ADCTRL1_REG {

Uint16 all;

struct ADCTRL1_BITS bit;

};

К каждому периферийному устройству существует свой заголовочный файл, который необходимо скопировать в папку include (см.рис.9).


Рис.9
Для того чтобы каждый раз не подключать все указанные заголовочные файлы, они все подключаются в файле DSP281x_Device.h.

Реальные экземпляры таких типов объявлены в файле DSP281x_GlobalVariableDefs.c (в котором подключен файл DSP281x_Device.h), при этом файл обеспечивает стыковку между адресами, объявленными в командном файле периферийных регистров, и именами, по которым следует обращаться к этим адресам. Такая стыковка обеспечивается за счет директивы #pragma:
#ifdef __cplusplus

#pragma DATA_SECTION("AdcRegsFile")

#else

#pragma DATA_SECTION(AdcRegs,"AdcRegsFile");

#endif

volatile struct ADC_REGS AdcRegs;
Здесь:

AdcRegsFile – имя секции в командном файле, которая располагается в области памяти ADC.

Обращение к конкретному биту следует делать как:



AdcRegs.ADCTRL1.bit.CONT_RUN = 1.

CCS оснащен системой подсказки полей структур – при наборе имени переменной и постановки знака «.» происходит контекстное открытие меню с полями структуры. Раскрытие контекстного меню может происходить с задержкой 1-10 секунд (особенность CCS), иногда CCS не может найти поля структуры (даже если они реально объявлены), в таком случае он пишет в статусной строке (внизу окна) сообщение «No members found».

  1   2   3   4   5   6   7   8   9


База данных защищена авторским правом ©bezogr.ru 2016
обратиться к администрации

    Главная страница