Например TDA7294

Форум РадиоКот • Просмотр темы - Как поместить цикл в case оператора switch
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт апр 16, 2024 15:11:10

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 252 ]  1, , , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 01:09:16 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
Необходимо при переключении кнопкой с помощью оператора switch включать мигание светодиода с различной частотой на каком либо выводе.при
использовании конструкции (для примера):
PORTB |= (1<<PB0);
_delay_ms(100);
PORTB&= ~(1<<PB0);
_delay_ms(100);
необходимо зациклить ее в теле case,но невозможно переключить switch в следующий case.Просто невозможно выйти из бесконечного цикла.
Я использовал while(),может быть есть какой либо способ решить эту проблему, я начал изучать программирование МК недавно и до сложных
кодов еще мне очень далеко. Надеюсь на помощь.
Спасибо.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 05:38:47 
Модератор
Аватар пользователя

Карма: 153
Рейтинг сообщений: 2801
Зарегистрирован: Сб авг 14, 2010 15:05:51
Сообщений: 18058
Откуда: г. Озерск, Челябинская обл.
Рейтинг сообщения: 0
Медали: 1
Лучший человек Форума 2017 (1)
для реальной помощи положено приводить исходный код и схему.
а также нужно подробно и четко описать, что тебе надо и как это должно работать.
при предоставленном минимуме информации могут помочь только гадалки и экстрасенсы.

_________________
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 10:22:30 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
Ну какой код? Студент не понятно чем занимался, как вдург препод огорошил!


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 11:01:14 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#define time 300
//attiny2313,8Mhz,ДЕЛИТЕЛЬ НА 8 ОТКЛЮЧЕН

void pause (unsigned long a)//Использую вместо стандартной задержки
{ unsigned long counter ;
for(counter=a;counter>0;counter--)
asm("nop");
}
int main(void)
{ uint8_t i=0;
DDRD = 0xFF;
PORTD=0x00;
DDRA = 0x00;
PORTA|=(1<<PA0);
while(1)
{
if (~PINA&(1<<PA0))
{
if (i<3)
{
i++;
}
else
{
i=0;
}
}
switch(i)
{
case 1:
PORTD|=(1<<PD0);
pause (10000L*time);
PORTD&=~(1<<PD0);
pause (10000L*time);
break;

case 2:
PORTD|=(1<<PD0);
pause (5000L*time);
PORTD&=~(1<<PD0);
pause (5000L*time);
break;

case 3:
PORTD|=(1<<PD0);
pause (1000L*time);
PORTD&=~(1<<PD0);
pause (1000L*time);
break;


}
_delay_ms(300);
}
}


При симуляции в Proteus зацикливается в первом case , т.е. не переключается в следующий .На макетной плате после первого нажатия кнопки светодиод горит постоянно примерно 5 сек(pause (10000L*time)
и потом гаснет ,дальнейшие манипуляции кнопкой просто повторяют эту картину(нет мигания светодиода).
Что касается студента - я вышел на пенсию и для поддержания здоровья занялся программированием МК, база у меня есть(физфак БГУ) и пока голова работает хочу нагружать ее насколько это возможно.
В марте мне будет 71.
Спасибо за Ваши комментарии, надеюсь на Вашу помощь.


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 11:18:31 
Опытный кот
Аватар пользователя

Карма: -2
Рейтинг сообщений: -23
Зарегистрирован: Сб окт 22, 2016 17:33:32
Сообщений: 760
Откуда: кг
Рейтинг сообщения: 0
У вас переменная i принимает значения 0,1,2, а switch(i) 1,2,3.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 11:20:32 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2090
Рейтинг сообщения: 0
У вас внутри switch одинаковые ветки отличающиеся только задержкой, проще ее хранить в массиве:
Код:
uint16_t arr[] = { 10000, 5000, 1000 };

и потом просто подставлять:
Код:
if (~PINA & (1<<PA0))
{
    if(++i >= 3) i = 0;
}

uint32_t delay = arr[i] * time;
PORTD|=(1<<PD0);     
pause (delay);
PORTD&=~(1<<PD0);   
pause (delay);

На AVR умножение наверно лучше делать один раз, после инкремента i, или сразу перемноженные значения хранить...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 11:48:04 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
К сожалению не работает, если только я правильно понял идею с массивами:


#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#define time 300
//attiny2313,8Mhz,ДЕЛИТЕЛЬ НА 8 ОТКЛЮЧЕН

void pause (unsigned long a)
{ unsigned long counter ;
for(counter=a;counter>0;counter--)
asm("nop");
}
int main(void)
{
uint16_t arr[] = { 10000, 5000, 1000 };


uint8_t i=0;
DDRD = 0xFF;
PORTD=0x00;
DDRA = 0x00;
PORTA|=(1<<PA0);
while(1)
{

if (~PINA & (1<<PA0))
{
if(++i >= 3)
{

uint32_t delay = arr[i] * time;
PORTD|=(1<<PD0);
pause (delay);
PORTD&=~(1<<PD0);
pause (delay);
}
else
i=0;
}
}
_delay_ms(300);

}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 11:56:17 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2090
Рейтинг сообщения: 0
Конечно не работает, потому что это какой-то другой код :) Тут, например, будет выход за предела массива:
Код:
if(++i >= 3)
{
    uint32_t delay = arr[i] * time;
....

Да, еще на AVR же вроде int 16-ти битный, значит нужно при умножении приведение к uint32_t использовать... Наверно эффективнее сразу перемноженное хранить:
Код:
uint32_t arr[] = { 10000 * time, 5000 * time, 1000 * time };

while(1)
{
    if (~PINA & (1<<PA0))
    {
       if(++i >= 3) i = 0;
    }
 
    PORTD|=(1<<PD0);     
    pause (arr[i]);
    PORTD&=~(1<<PD0);   
    pause (arr[i]);

}

Опять же, это примерный код, я его не проверял потому что с AVR уже давно дела не имею, мелкие правки нужно самому делать. Например, если массив 32-х битный, то time должен быть задефайнен как 32-х битное значение.


Последний раз редактировалось Reflector Вт окт 12, 2021 12:19:07, всего редактировалось 2 раз(а).

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 12:19:02 
Друг Кота
Аватар пользователя

Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52
Сообщений: 4470
Откуда: Главный Улей России (Moscow)
Рейтинг сообщения: 0
Как уже сказали, switch у Вас реагирует только на значения i=1, 2 или 3, а переменная i принимает значения 0..2
Соответсвенно, case 3 у Вас никогда не сработает.
Ну и пока кнопка нажата, у Вас переменная i будет постоянно меняться, пока Вы ее не отпустите.
Как я понял, вы хотите мигать светодиодом с переключаемой с помощью кнопки задержкой.
Вам нужно после фиксации факта нажатия кнопки ожидать ее отпускание и уже после отпускания инкрементировать переменную i.
Вам еще нужно изучить такой эффект как "дребезг контактов" и методы борьбы с ним. Ибо в Протеусе дребезга нет,
а в реальной кнопке он есть.

И чтение лучше явно проверять:
Код:
if( (PINA & (1<<PA0)) == 0// Бит, соответсвующий выводу PA0 равен нулю (прижали подтянутую ногу к минусу)
{
   
// Делаем то, что надо
}
 


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

_________________
I am DX168B and this is my favourite forum on internet!


Последний раз редактировалось DX168B Вт окт 12, 2021 12:29:28, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 12:26:23 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2090
Рейтинг сообщения: 0
Ну и пока кнопка нажата, у Вас переменная i будет постоянно меняться, пока Вы ее не отпустите.

Там в конце задержка 300ms, если кнопку быстро нажимать, то для проверки сойдет, а дальше если еще и с антидребезгом делать, то это уже продвинутый уровень :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 12:30:58 
Друг Кота
Аватар пользователя

Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52
Сообщений: 4470
Откуда: Главный Улей России (Moscow)
Рейтинг сообщения: 0
К ней еще добавить задержки в switch и там уже гораздо больше, чем 300мс.

_________________
I am DX168B and this is my favourite forum on internet!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 13:03:55 
Вымогатель припоя

Карма: 6
Рейтинг сообщений: 167
Зарегистрирован: Ср янв 06, 2010 10:01:46
Сообщений: 547
Рейтинг сообщения: 0
Вариантов решения много.
Задержки лучше бы не использовать, или использовать по минимуму.
Для организации задержек идеально подходят таймеры чипа плюс флаги.
1) заводим таймер на срабатывание прерывания с частотой, например в 10 мс.
2) в обработчике прерывания просто инкрементируем переменную-счетчик (не забыть сделать ее при определении как volatile)
3) в начале main обнуляем переменную-счетчик и задаем переменную - максимум (например, через настройку индекса массива на его начало, как вам уже предлагали)
4) главный цикл:
4.1) читаем состояние кнопки (кнопок)
4.2) каскад проверок:
Если переменная - счетчик достигла значения переменной - максимум, обнуляем счетчик и инвертируем выход светодиода. Например, если время свечения / паузы светодиода должно быть полсекунды, переменная - максимум должна быть равна 50.
Если была нажата кнопка, переопределям переменную - максимум (например, через приращение индекса массива, как вам уже предлагали)

Вроде всё. В протеусе должно взлететь, я думаю. В реальной схеме нужно будет добавить обработку дребезга контактов кнопки.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вт окт 12, 2021 13:53:17 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
Cпасибо.Сейчас не могу проверить,
доберусь до компьютера -отпишусь.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Ср окт 13, 2021 22:56:42 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
Всем спасибо .Все получилось. Для прерываний использовал Т0 в режиме переполнения и срабатывания 8мс.Правда обошелся без массивов.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пт окт 15, 2021 16:19:30 
Друг Кота
Аватар пользователя

Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52
Сообщений: 4470
Откуда: Главный Улей России (Moscow)
Рейтинг сообщения: 0
Рады, что смогли чем-то помочь. :beer:

Вообще, можете взять за правило.
Пишите один раз код, реализующий задержки на таймере и каждый раз,
когда создаете проект, копируете туда этот код и налаживаете его работу.
Задержки на таймере позволяют организовать асинхронные задержки, а таких задержек можно организовать
великое множество. Саму же программу реализовать можно в виде конечного автомата, который будет состоять
из множества состояний для различных действий. Главный цикл постоянно проходится по автомату и выполняет действия,
согласно текущему состоянию и переключается в другие состояния по каким-то событиям, значениям в переменных или флажках.
Благодаря такому подходу легко можно реализовать нечто, вроде "мигать светодиодом в течении 10 секунд. Если за это время нажали кнопку, зажечь светодиод, а иначе потушить."
Есть по этим вещам множество статей в блоге easyelectronics.

Вот пример того, как выглядит один из конечных автоматов в одном из моих проектов:
СпойлерТут язык C++, но это не суть.
Эта функция постоянно вызывается из главного цикла.
Она реализует опрос клавиатуры и антидребезг.
Состояния автомата определяются перечислительным типом enum KbProcState (это такой удобный способ дать числам названия)
и хранятся переменной state
Тут же используются и задержки с таймером.

Все разбито на определенный порядок действий.
Состояния физических кнопок читаются постоянно, функцией CheckPressedKey()
А дальше автомат:

1 состояние (оно же и начальное):
Проверяется, нажато ли вообще что-то.
Если нет, то остаемся в этом же состоянии.
Если нажалось что-то, значит запускаем таймер антидребезга и меняем состояние автомата (переход во второе состояние)

2:
Проверка, не поменялся ли номер нажатой кнопки при очередном опросе.
Если в течении задержки антидребезга номер не менялся, значит кнопка в стабильном состоянии,
происходит переключение в следующее состояние.
Если же номер изменялся (контакт еще нестабилен), то автомат переключается в начальное состояние и все начинается заново.

Последующие состояния уже детектируют короткое или длинное нажатие и выставляют событие (коротко/длинно нажата такая-то кнопка).
Это событие уже используется другими конечными автоматами, реализованными в программе.


Код:
///////////////////////////////////////////////////////////////////////
// Keyboard process
void CKeyboard::Process()
{
    // Detect pressed key
    KbKeys pressedKey = CheckPressedKey();
    
    
// Keyboard process state machine
    switch (state)
    {
    // Initial state
    case KbProcState::INITIAL:
        if(pressedKey != KbKeys::KEY_NONE)
        {
            prevKey = pressedKey;
            kbTim.SetTimer(KEYBOARD_DEBOUNCE_DELAY); // begin debounce timer
            state = KbProcState::KEY_PRESS_DEBOUNCE;
        }
        break;

    // Press debounsce
    case KbProcState::KEY_PRESS_DEBOUNCE:
        if(pressedKey != prevKey)
        {
            state = KbProcState::INITIAL;
        }
        else
        
{
            if(kbTim.CheckTimer() == true) // check debounce timer
            {
                kbTim.SetTimer(KEYBOARD_LONGPRESS_DELAY);
#ifndef KEYBOARD_EVENT_KEY_AND_CLICK_SYNC
                currentKey = pressedKey;
#endif
                currentClick = ClickType::NO_CLICK;
                state = KbProcState::KEY_PRESS;
            }
        }

        break;

    // Key pressed state
    case KbProcState::KEY_PRESS:
        if(pressedKey == KbKeys::KEY_NONE)
        {
            if(kbTim.CheckTimer() == false)
            {
                currentClick = ClickType::SHORT_CLICK;
#ifdef KEYBOARD_EVENT_KEY_AND_CLICK_SYNC
                currentKey = prevKey;
#endif
            }

            state = KbProcState::INITIAL;
        }

        if(kbTim.CheckTimer() == true)
        {
            currentClick = ClickType::LONG_CLICK;
#ifdef KEYBOARD_EVENT_KEY_AND_CLICK_SYNC
            currentKey = pressedKey;
#endif
            state = KbProcState::KEY_UNPRESS;
        }
        
        break
;

    // Wait for unpress key
    case KbProcState::KEY_UNPRESS:
        if(pressedKey == KbKeys::KEY_NONE)
        {
#ifndef KEYBOARD_EVENT_KEY_AND_CLICK_SYNC
            currentKey = pressedKey;
#endif
            state = KbProcState::INITIAL;
        }

        break;

    // Other states
    default:
        currentKey = KbKeys::KEY_NONE;
        currentClick = ClickType::NO_CLICK;
        state = KbProcState::INITIAL;
        break;
    }
}

_________________
I am DX168B and this is my favourite forum on internet!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Сб окт 16, 2021 23:29:02 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
Подскажите, если не трудно литературу по конечным автоматам .Может быть есть ссылки в интернете по этой теме.
Спасибо.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Сб окт 16, 2021 23:42:53 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
Цифровые устройства Пухальского и Новосельцевой.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 18, 2021 02:24:41 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1384
Рейтинг сообщения: 0
Цикл статей Татарчевского. Здесь тоже статья, в ней ссылка на архив.
Моя реализация программных таймеров.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Чт фев 03, 2022 14:30:05 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
DX168B , metan!
Попробовал эту методику, с прерываниями и конечным автоматом. Все получилось.
Спасибо!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Чт окт 06, 2022 11:03:05 
Открыл глаза

Зарегистрирован: Пн окт 05, 2020 17:20:11
Сообщений: 43
Рейтинг сообщения: 0
Возникла проблема. Хочу написать код для переключения кнопками(например три кнопки)
трех выходов. С помощью методики "конечных автоматов" попробовал сделать программу.
Но получился трехканальный переключатель без фиксации ,т.е. включение и выключение
любого канала происходит независимо от состояния других каналов.
Мне нужно превратить этот переключатель в переключатель с фиксацией. Т.е.
при нажатии на любую кнопку остальные выходы обнуляются(неважно что на них было -
0v,+5v или blink для светодиода) и на выходе канала с этой включенной кнопкой появляется
нужный сигнал +5v или blink.Причем выключить этот канал можно включением другого("переключение
с фиксацией") или просто повторным нажатием на кнопку включенного канала.
Проблема в том, что я не смог добиться отключения активного канала включением любого другого.
Перепробовал различные приемы выключения других выходов при включении нужного мне канала.
Помещал код типа PORTB&=~(1<<PB3); в switch для blink_click,пробовал в button_ KA после строки
поднятия флага fclk: if(fclk =1){PORTB&=~(1<<PB3)}.Номера портов здесь условные.
Я понимаю, что мне не хватает опыта для использования таких тонкостей.
Поэтому и прошу помощи.
Спасибо.
В архиве код и протеус
https://drive.google.com/file/d/1kOjc23 ... sp=sharing


Вложения:
temp2.rar [103.71 KiB]
Скачиваний: 49
Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 252 ]  1, , , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Google [Bot] и гости: 20


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y