Главная страница
Навигация по странице:

  • ===================================== Справочник по программированию «Bascom-8051» ==

  • Справочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001). Справочник по программированию bascom8051 Краснодар 2001


    Скачать 6.61 Mb.
    НазваниеСправочник по программированию bascom8051 Краснодар 2001
    АнкорСправочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001).pdf
    Дата26.04.2017
    Размер6.61 Mb.
    Формат файлаpdf
    Имя файлаСправочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001).pdf
    ТипСправочник
    #5699
    КатегорияПромышленность. Энергетика
    страница15 из 25
    1   ...   11   12   13   14   15   16   17   18   ...   25
    ===================================== Справочник по программированию «Bascom-8051» ==
    SHIFTOUT, SPIIN, SPIOUT. Затруднения появляются, когда устройство, с которым необходимо взаимодействовать, имеет число разрядов не кратное восьми (не целое число байт) и не допускает подачу лишних импульсов на входе синхронизации. Практически таких микросхем очень мало. Чаще микросхемы, не допускающие подачу лишних импульсов, ориентированы на байтовый обмен, и поэтому проблем с ними вообще не возникает. Справедливости ради, нужно сказать, что проблема числа импульсов синхронизации возникает только для микросхем, имеющих двухпроводный интерфейс, или при попытках использования имеющиеся трехпроводные (и более) интерфейсы как двухпроводный. Использование ассемблера для написания подпрограмм ввода-вывода оправдано только в одном случае, когда эти подпрограммы вызывается в прерывании, и к ним предъявляются особые требования по скорости и количеству используемых регистров. В остальных случаях это делать не рекомендуется, т.к. библиотеки Bascom дают оптимальный код и быстродействие (50 - 70 % от возможного). Ниже приведен пример программы, работающей с типичным устройством, имеющим последовательный интерфейс. В тексте программы имеются все варианты организации интерфейса с помощью операторов последовательного вывода SHIFTOUT и SPIOUT.
    '--------------------------------------------------------------
    ' Программа тестирование цифрового потенциометра AD8400 -2,-3
    '--------------------------------------------------------------
    Dim Badr As Byte 'байтовый адрес
    Dim Value As Byte 'значение записываемого кода
    Dim Wtmp As Byte 'временные данные
    Pdin Alias P1.0 'подключение ЦАП
    Pcs Alias P1.2
    Pclk Alias P1.3
    '---------------------
    Config Spi = Soft , Din = P1.0 , Dout = P1.1 , Cs = P1.2 , Clk = P1.3
    '---------------------
    'TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц '---------------------
    Set Pcs : Reset Pclk
    'Цикл
    Mc:
    Input "Enter number of DAC" , Badr 'запрос адреса ЦАП
    Input "Enter code for DAC" , Value 'запрос данных ЦАП
    Value = Value And &B00000011 'маска
    Print "DAC=" ; Badr ; " " ; "Code=" ; Value 'покажем '---------------------
    ' _ временная диаграмма работы интерфейса _
    ' |__________________________________________| CS
    ' ___ ____ ____ ____ ____ ____ ____ ____ ____ __
    ' ___X____X____X____X____X____X____X____X____X__ Data
    ' _ _ _ _ _ _ _ _
    ' ____| |__| |__| |__| |__| |__| |__| |__| |____ Clk
    '---------------------
    ' Gosub Ser_out 'использовать подпрограмму вывода
    Wtmp = Makeint(value , Badr) 'сложим как: младший + старший 'второй вариант
    Spiout Wtmp , 2 'послать два байта: адрес и данные
    Goto Mc
    '---------------------
    'подпрограмма последовательного вывода
    Ser_out:
    Acc = Badr 'адрес в аккумулятор
    Pcs = 0
    Pdin = Acc.1 : Set Pclk : Reset Pclk 'выдвинем старший бит адреса
    Pdin = Acc.0 : Set Pclk : Reset Pclk 'выдвинем младший бит адреса ' Shiftout Pdin , Pclk , Badr , 1 'выдвинем 8-битный адрес
    Shiftout Pdin , Pclk , Value , 1 'затем данные (старший - первым)
    Pcs = 1
    Return
    '------------------------------------------
    =============================================================================
    18-2

    ===================================== Справочник по программированию «Bascom-8051» ==
    Следующая программа демонстрирует организацию ввода и обработки данных 12-разрядного АЦП с последовательным интерфейсом. Для считывания данных АЦП используется оператор SHIFTIN. Особенность программы заключается в том, что тактирование работы программы осуществляется с помощью таймера, а для вывода вычисляется среднее значение шестнадцати отсчетов.
    '--------------------------------------------------------------
    ' Программа тестирования АЦП типа AD7893-3 (Шкала +-2.5 В)
    '--------------------------------------------------------------
    $large 'модель программы более 2 кбайт
    Dim B_dat As Bit 'бит "Есть новые данные"
    Dim Mes As Byte 'счетчик измерений '---------------------
    Dim Temp As Integer 'временные данные
    Dim R_bd As Integer '16-разр. двоичные данные '---------------------
    Dim R_fld As Single 'регистр данных АЦП
    '---------------------
    B_acnv Alias P1.0 'подключение АЦП
    B_aclk Alias P1.1
    B_adat Alias P1.2
    '--------------------------------------------------------------
    'TIMER0 в режиме 16-бит. счетчика
    Config Timer0 = Timer , Gate = Internal , Mode = 1 : Start Timer0
    '---------------------
    'TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц '---------------------
    'назначение режимов прерываний
    On Timer0 Timer_0_int Nosave 'вектор прерывания
    Enable Interrupts 'вообще разрешить прерывания
    Enable Timer0 'разрешить прерывания таймера 0
    '------------------------------------------
    Set B_acnv : Reset B_aclk
    Mes = 16 'количество усредняемых отсчетов '------------------------------------------
    Mc:
    Do
    If B_dat = 1 Then 'появился бит?
    Reset B_dat 'сбросить этот бит
    R_bd = R_bd + Temp
    Decr Mes
    If Mes = 0 Then
    R_fld = R_bd : R_bd = 0 'преобразуем в плавающий формат и очистим сумму
    R_fld = R_fld * 0.0000763 'преобразуем показания в вольты
    Print R_fld : Mes = 16 'вывести показания и восст. счетчик
    End If
    End If
    Loop
    '------------------------------------------
    'обработка прерывания таймера 0
    Timer_0_int:
    Th0 = &HD8 : Tl0 = &HFD 'Ffffh-10000 = D8fdh - период прерыв. 10 мс
    Set B_dat
    Return
    '------------------------------------------
    'запустить преобразование и считать данные
    Convert:
    Reset B_acnv : Reset B_acnv : Set B_acnv 'сформировать импульс 'до считывания нужно выдержать 6 мкс реально получается больше '---------------------
    =============================================================================
    18-3

    ===================================== Справочник по программированию «Bascom-8051» ==
    ' _ временная диаграмма работы интерфейса __
    ' |________________________________________| CS
    ' ___ ____ ____ ____ ____ ____ ____ ____ ____ _
    ' ___X____X____X____X____X____X____X____X____X_ Data
    ' __ __ __ __ __ __ __ __
    ' __| |_| |_| |_| |_| |_| |_| |_| |____ Clk
    '---------------------
    Shiftin B_adat , B_aclk , Temp , 1 'подходит режим 1
    Return
    '----------------------------------------------
    При программировании аналоговых преобразователей всегда приходится выбирать размерность воспроизводимых или измеренных данных. Лучше и понятней, когда данные представлены в общепринятых единицах, и при этом все числовые значения, принимаемые измеряемым (или воспроизводимым) параметром в процессе работы, соответствуют используемому устройству отображения. Имеется в виду, что, например, нельзя строить измерительную систему, в которой на 3.5-разрядный индикатор должно выводится число
    10000 Гц или 20000 кОм. Понятно, форма представления чисел в программе должна быть такой, чтобы указанные числа выводились как 10.00 кГц и 020.0 МОм. Удобней всего, когда числа в программе представлены в формате с плавающей точкой. Это позволяет работать с широким диапазоном значений без потери точности и производить любые вычисления. Микросхемы ЦАП и АЦП принимают и выдают значения, представленные в виде целого двоичного кода числа младших разрядов. Bascom предоставляет прекрасные возможности преобразования числа в формате с плавающей точкой в код загрузки ЦАП (в целое двоичное число) и, соответственно, выходного кода
    АЦП в число в формате с плавающей точкой, что показано в предыдущих примерах и последующей программе.
    При преобразовании двухполярного числа нужно позаботится, чтобы источником (или приемником) двоичных данных была знаковая переменная типа Integer или Long, и чтобы старший (знаковый) бит был заполнен, как это сделано в следующей демонстрационной программе (тестирования AD7711A) с помощью оператора ROTATE.
    Если преобразуется однополярное двоичное число, то его расположение в регистре двоичных данных имеет только то значение, что должно соответствовать разрядам ЦАП или АЦП.
    Второй составляющей преобразования кода является операция умножения на масштабирующий коэффициент. В случае загрузки ЦАП с помощью масштабирующего коэффициента происходит переход от принятой размерности к числу устанавливаемых младших разрядов (смотри пример в программе монитора синтезатора частоты). Чтобы привести к требуемой размерности данные АЦП, выраженные в единицах младшего разряда, также применяется соответствующий масштабный коэффициент.
    Ниже представлен еще пример программы, работающей с АЦП. В ней осуществляется тестирование 24- разрядного АЦП, связанного с процессором через последовательный интерфейс. АЦП перед началом работы инициализируется и проводится его самокалибровка (калибровка нуля и калибровка шкалы). В данной программе
    АЦП является источником сигнала синхронизации для всей программы. Установив при инициализации АЦП время измерения (интегрирования, т.к. АЦП интегрирующего типа) равное 20 мс и подав сигнал готовности данных АЦП на вход прерывания, мы будем каждые 20 мс получать новый отсчет. Вследствие того, что вывод и визуальное восприятие данных с такой скоростью невозможно, применено усреднение данных шестнадцати отсчетов. Теперь, каждые 320 мс (3 раза в секунду) мы будем получать результат. В программе считывания данных АЦП применено много ассемблерных вставок для повышения скорости работы и лучшего контроля ресурсов, используемых в прерывании. В программе предусмотрена калибровка АЦП, информация о которой будет представлена ниже.
    '--------------------------------------------------------------
    ' Программа тестирования 24-разр. АЦП AD7711A (+-2.5 В)
    '--------------------------------------------------------------
    $large 'модель программы более 2 кбайт
    Dim B_dat As Bit 'бит "Есть новые данные"
    Dim Mes As Byte 'счетчик измерений
    Dim R_ch As Byte 'введеный символ '---------------------
    Dim Temp As Long 'временные данные
    Dim R_bd As Long '32-разр. двоичные данные '---------------------
    Dim R_fld As Single 'регистр данных АЦП
    Dim R_zero As Single 'константа смещения нуля
    Dim R_scal As Single 'константа калибровки масштаба '--------------------------------------------------------------
    'TIMER0 в режиме 16-бит. счетчика
    Config Timer0 = Timer , Gate = Internal , Mode = 1 : Start Timer0
    '---------------------
    =============================================================================
    18-4

    ===================================== Справочник по программированию «Bascom-8051» ==
    'TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц '---------------------
    On Int0 Int0_int Nosave 'вектор INT0
    Enable Interrupts 'вообще разрешить прерывания '------------------------------------------
    Gosub Str_adc 'самокалибровка и установка режима АЦП
    Mes = 16 'количество усредняемых отсчетов
    R_zero = 0 'нет смещение нуля
    R_scal = 1 'масштаб идеальный
    Print " - MONITOR FOR ADC AD7711A - "
    Print " Calb zero - Z @ Uinp = 0 V "
    Print " Calb scale - S @ Uinp = + 2 V"
    Enable Int0 'разрешить внешнее прерывания 0
    '------------------------------------------
    Mc:
    Do
    If B_dat = 1 Then 'появился бит?
    Reset B_dat 'сбросить этот бит
    Rotate R_bd , Left , 4 'показания еще нужно умножить на 16
    'таким образом, сумма 16-ти отсчетов полностью расположиться в 32-битн. регистре
    R_fld = R_bd : R_bd = 0 'преобразуем в плавающий формат и очистим сумму
    R_fld = R_fld * 0.00000000116415322 'преобразуем показания в вольты
    R_ch = Inkey
    If R_ch <> 0 Then 'если нажата кнопка - проверить
    Gosub Makeclb 'при необходимости калибровать
    End If
    Gosub Calbr 'учесть калибровку
    Print R_fld 'вывести показания
    End If
    Loop
    '------------------------------------------
    'обработка прерывания таймера 0
    Int0_int:
    $asm
    Push Psw
    Push Acc
    $end Asm
    Psw.3 = 1 : Psw.4 = 1 'выберем третий банк - он не используется Bascom
    Gosub Rd_adc
    $asm djnz {Mes} , Int0_1 ;обработка счетчика измерений
    Setb {B_dat} ;если Mes=0, есть новые данные АЦП mov {Mes} , #16 ;восстановить счетчик
    Int0_1:
    Pop Acc
    Pop Psw
    $end Asm
    Return
    '----------------------------------------------
    ' УТИЛИТЫ СИГМА-ДЕЛЬТА АЦП ТИПА AD7711A
    '----------------------------------------------
    'регистры AD7711
    ' формат регистра управления ' --------- MD2 0 норм. 0 самокалиб.
    ' ¦-------- MD1 0 изм. 0 в выбранн.
    ' ¦¦------- MD0 0 1 канале ' ¦¦¦------ G2 0 0 0 0 1 1 1 1
    ' ¦¦¦¦----- G1 0=1 0=2 1=4 1=8 0=16 0=32 1=64 1=128
    ' ¦¦¦¦¦---- G0 0 1 0 1 0 1 0 1
    ' ¦¦¦¦¦¦--- CH 0-AIN1, 1-AIN2
    =============================================================================
    18-5

    ===================================== Справочник по программированию «Bascom-8051» ==
    ' ¦¦¦¦¦¦¦-- PD 0-работа, 1-останов ' ¦¦¦¦¦¦¦¦--------- WL Выход: 0-16 бит, 1-24 бита ' ¦¦¦¦¦¦¦¦¦-------- IO Вых. ток RTD 0-выкл, 1-вкл ' ¦¦¦¦¦¦¦¦¦¦------- BO Вых. ток BO 0-выкл, 1-вкл ' ¦¦¦¦¦¦¦¦¦¦¦------ B/U Вход: 0-двухполярный, 1-однополярн.
    ' ¦¦¦¦¦¦¦¦¦¦¦¦------------- FS11=0¬
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦------------ FS10 ¦ при кварце 5 МГц:
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦----------- FS9 ¦ 50 Гц FS=135 (0С3h)
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦---------- FS8 ¦ (fкв/512)
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦--------- FS7 ¦- FS = ----------------------
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦-------- FS6 ¦ частота первого полюса ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦------- FS5 ¦
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦------ FS4 ¦- FS - код первого полюса ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦----- FS3 ¦ от 19 до 2000
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦---- FS2 ¦
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦--- FS1 ¦
    ' ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦-- FS0 ---
    'C_M2B equ 00000000b 'старший байт рабочего режима:
    'C_M1B equ 10000000b 'средний байт 50 Гц, G=1, +-2.5 В
    'C_M0B equ 11000011b 'младший байт CH1, 24 бита, ток выкл '---------
    'C_С2B equ 00100000b 'старший байт самокалибровки:
    'C_С1B equ 10000000b 'средний байт 50 Гц, G=1, +-2.5 В
    'C_С0B equ 11000011b 'младший байт CH1, 24 бита, ток выкл '----------------------------------------------
    'определение констант
    Dim C_m2b As Const &B00000000
    Dim C_m1b As Const &B10000000
    Dim C_m0b As Const &B11000011
    Dim C_c2b As Const &B00100000
    Dim C_c1b As Const &B10000000
    Dim C_c0b As Const &B11000011
    '----------------------------------------------
    'НАЗНАЧЕНИЕ ПОРТОВ, ПОДКЛЮЧЕННЫХ К АЦП
    B_aa0 Alias P1.0 'ПОРТ ВЫБОРА РЕГИСТРА АЦП: 0-сост. 1-данных
    B_atfs Alias P3.5 'ПОРТ РАЗРЕШЕНИЯ ЗАПИСИ АЦП
    B_arfs Alias P1.3 'ПОРТ РАЗРЕШЕНИЯ СЧИТЫВАНИЯ АЦП
    B_aclk Alias P1.1 'ПОРТ ТАКТОВОГО СИГНАЛА ДЛЯ ДАННЫХ АЦП
    B_adat Alias P1.2 'ДАННЫЕ АЦП
    B_ardy Alias P1.4 'ГОТОВНОСТЬ ДАННЫХ АЦП
    '----------------------------------------------
    'ЗАПИСЬ 8 БИТ В АЦП ИЗ АККУМУЛЯТОРА
    Wrb_adc:
    $asm
    Mov R0 , #8
    Wrb_adc1:
    Rlc A ;данные в SDATA
    Mov {B_adat} , C
    Setb {B_aclk} ;защелкнуть - SCLK в "1"
    Clr {B_aclk} ;SCLK в "0"
    Djnz R0 , Wrb_adc1
    $end Asm
    Return
    '----------------------------------------------
    'ЧТЕНИЕ 8 БИТ ИЗ АЦП В АККУМУЛЯТОР
    Rdb_adc:
    $asm
    Mov R0 , #8
    Rdb_adc1:
    Setb {b_aclk} ;защелкнуть - SCLK в "1"
    Mov c , {B_adat}
    Clr {B_aclk} ;SCLK в "0"
    Rlc A ;данные в Acc
    =============================================================================
    18-6

    ===================================== Справочник по программированию «Bascom-8051» ==
    Djnz R0 , Rdb_adc1
    $end Asm
    Return
    '----------------------------------------------
    ' Начальная подготовка АЦП к работе:
    ' самокалибровка - установка режима '---------
    Str_adc:
    Reset B_aclk : Reset B_aa0 : Reset B_atfs 'SCLK=0, A0=0, разрешим запись
    Acc = C_c2b : Gosub Wrb_adc 'назначить самокалибровку АЦП
    Acc = C_c1b : Gosub Wrb_adc
    Acc = C_c0b : Gosub Wrb_adc
    Set B_atfs : Wait 2 'запретим запись и ждать 2 сек
    Reset B_atfs 'разрешить запись
    Acc = C_m2b : Gosub Wrb_adc 'назначить нормальный режим АЦП
    Acc = C_m1b : Gosub Wrb_adc
    Acc = C_m0b : Gosub Wrb_adc
    Set B_atfs : Set B_adat 'запретим запись подготовиться к приему данных
    Return
    '----------------------------------------------
    'Программа считывания данных из АЦП
    'Производится первичная обработка данных - они 'складываются с регистром суммы с учетом знака
    Rd_adc:
    B_adat = 1 : B_aclk = 0 'подготовить порты
    B_aa0 = 1 : B_arfs = 0 'разрешить чтение АЦП
    '---------
    Mov R1 , #{Temp + 3}
    Mov @R1 , #0
    Dec R1
    Gosub Rdb_adc
    Mov @r1 , A ;запомним старший байт
    Dec R1
    Gosub Rdb_adc
    Mov @r1 , A ;запомним средний байт
    Dec R1
    Gosub Rdb_adc
    Mov @r1 , A ;запомним младший байт '---------
    B_arfs = 1 'запретить чтение АЦП
    'суммирование показаний
    $asm
    Mov R0 , #{R_bd} ;сумма данные
    Mov R1 , #{Temp} ;считанные данные
    Mov R2 , #4 ;четыре байта
    Clr C
    Rd_adc1:
    Mov A , @R1 ;цикл суммирования
    Addc A , @R0
    Mov @R0 , A
    Inc R0
    Inc R1
    Djnz R2 , Rd_adc1
    $end Asm
    Return
    '---------
    'калибровка показаний
    Calbr:
    R_fld = R_fld - R_zero 'скорректировать смещение
    R_fld = R_fld * R_scal 'поправить масштаб
    Return
    '---------
    'провести калибровку
    =============================================================================
    18-7

    ===================================== Справочник по программированию «Bascom-8051» ==
    Makeclb:
    If R_ch = &H5B Then 'если введен Z - калибровать нуль
    R_zero = R_fld 'показания - константа смещения
    End If
    If R_ch = &H53 Then 'если введен S - калибровать масштаб
    R_fld = R_fld – R_zero'учтем поправку нуля и с ней
    R_scal = 2 / R_fld 'вычислим константу масштаба
    End If
    R_ch = 0
    Return
    '-------------------------------
    Следующий пример - программа тестирования цифрового синтезатора. В ней значение в формате с плавающей точкой и выраженной в килогерцах, преобразуется в значение количества единиц младшего разряда ЦАП, затем целое двоичное число и загружается в регистры синтезатора. Как и в предыдущих примерах, микросхема синтезатора подключена к процессору через последовательный интерфейс. Количество загружаемых бит – 40.
    '--------------------------------------------------------------
    ' Монитор тестирования синтеза AD9850 в режиме с ' последовательной загрузкой данных. Кварц = 60 МГц '--------------------------------------------------------------
    Dim N_dat As Bit 'бит "Есть новые данные"
    N_inp Alias Scon.0 'бит "Есть ввод" (RI)
    '---------------------
    Dim Temp As Byte 'временные данные '---------------------
    Dim R_bd As Long '32-разр. двоичный код загрузки '---------------------
    Dim R_frq As Single 'регистр значения частоты
    Dim R_fld As Single 'регистр кода загрузки '---------------------
    'подключение синтезатора
    B_data Alias P1.5 : B_clk Alias P1.3 : B_fqud Alias P1.4 : B_res Alias P1.7
    '---------------------
    ' TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц '---------------------
    'подготовить линии управления к работе
    Reset B_data : Reset B_clk : Reset B_fqud : Reset B_res
    '---------------------
    'главный цикл
    Mc:
    Do
    If N_dat = 1 Then 'есть новые данные?
    N_dat = 0 'на самом деле это бит RI
    Gosub Sload_9850 'загрузка новых данных
    End If
    If N_inp = 1 Then 'что-то принято?
    N_inp = 0 'очистим без анализа
    Input "Enter value of frequency [kHz] f= " , R_frq 'ввод частоты
    Print R_frq 'печатать введенное значение 'чтобы получить код загрузки умножим на число:
    R_fld = R_frq * 71582.788 ' 2^32 / Fclk = 4294967296 / 60000 kHz
    R_bd = R_fld 'преобр. в целое 32-разр. число
    Printhex "Hex " ; R_bd 'печать в hex формате
    Set N_dat 'есть данные на вывод в синтезатор
    End If
    Loop
    '------------------------------------------
    =============================================================================
    18-8

    1   ...   11   12   13   14   15   16   17   18   ...   25


    написать администратору сайта