Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Светофор в "Си"для контроллера с SIG_INTERRUPT0
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
konstatinopol
Такое дело надо спрограмировать светофор. Есть 2 микроконтроллера которые соединяются друг с другом и на каждый из них зашивается одна и таже программаю. Программа почти готова, но есть одна проблемка, у меня неправильно вызыватся SIG_INTERRUPT0.
Буду ОЧЕНЬ благодарен любой помощи !!!! Зарание благодарю.
Так выглядит борт :

CODE
#include <stdint>
#include <avr>
#include <avr>
#include <avr>
#include <avr> // In/Outputs


short cntr = 0;
int a=0;
int b=0;

void lampochki()
{

if(PORTB==1)
{
PORTB=3;
}
else if(PORTB==3){
PORTB=4;

}else if(PORTB==4)
{
PORTB=2;

}else if(PORTB==2)
{
PORTB=1;
a=1;
PORTC = 1;
//long i;
//for(i = 0; i < 1000000; i++);

}
PORTC = 0;

}

int main()
{
DDRB=7;
DDRD=0;
PORTB=1;
DDRC = 7;
PORTC=0;
TCNT0 = 244;
cntr = 28;
TCCR0 = 5;
TIMSK = 1;
GICR = 64; // interrupt port D0 ein
MCUCR = 1; // oder 2
sei();

while(1){}
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_INTERRUPT0){
a=0;
}
_Pasha
Цитата(konstatinopol @ Jan 31 2009, 15:18) *
Программа почти готова, но есть одна проблемка, у меня неправильно вызыватся SIG_INTERRUPT0.

Надо объявить как volatile все, что юзается в прерываниях. Т.е. это cntr и a
ЗЫ: не в обиду, программа очень кривая и страшная.
aesok
Цитата(_Pasha @ Jan 31 2009, 16:55) *
Надо объявить как volatile все, что юзается в прерываниях. Т.е. это cntr и a


Не совсем точно!!!


Надо объявить как volatile все переменные, которые используются, И в обработчиках прерываний, И в функции main или в функциях вызываемых из main.


А переменная cntr используется только в обработчике прерывания SIGNAL(SIG_OVERFLOW0), и более грамотно объявить локальную статическую переменную cntr в SIGNAL(SIG_OVERFLOW0).

То konstatinopol, перевидите пожалуйста "у меня неправильно вызывается SIG_INTERRUPT0", с Вашего на инженерный.

Анатолий.
Сергей Борщ
Цитата(konstatinopol @ Jan 31 2009, 14:18) *
у меня неправильно вызыватся SIG_INTERRUPT0.
Начиная с какой-то версии avr-gcc надо использовать ISR() вместо SIGNAL(). Почитайте документацию на avr-libc вашего компилятора.
konstatinopol
_Pasha что вы подразумеваете под " программа очень кривая и страшная"?? Как она написанна, отредоктированна или что то в ней не потдаётся логике.
что значит обьявить volatile??
Код
volatile short cntr = 0;
volatile int a=0;
Видимо так.

Анатолий нащёт того чтобы обьявить cntr в SIGNAL(SIG_OVERFLOW0) точно я незнаю, но мы всегда её обьвляли до main(). Возможно и грамотнее но мы задаём ей значение в main() равное 28.

Возможно я неправильно выразился нащёт "SIG_INTERRUPT0". Дело в том что 2 борта соединяются и на них зашивается почти одна и таже программа, единственное отличие между программами это первое значение "а".
При запуске у обоих бортов зажигаются крассные лампочки. Тот борт у которого "а=0" зажигает лампочки в таком порядке : крассная-> крассно-желтая -> зелёная -> желтая -> крассная и сажает значение а=1 и останавливается, но в тот момент когда он останавливается(ботр) в SIG_INTERRUPT0 он посылает второму борту сигнал и тот сажает своё а=0 и проходит цепочку так же как и первый. Такая логика моего светофора.
Мне кажется что в программе неправильно написал принцип отправления а=0.

В моей версии avr-gcc ещё используется SIGNAL(), на других программах уже проверенно.

Вот принцеп соединения бортов, вроде правильно.
_Pasha
Цитата(konstatinopol @ Jan 31 2009, 19:01) *
_Pasha что вы подразумеваете под " программа очень кривая и страшная"??
Мне кажется что в программе неправильно написал принцип отправления а=0.

То, что мы сейчас делаем - как раз следствие "кривоватости" void lampochki()
Попробуйте кроме всего сказанного выше вернуть задержку, только зачем Вам такая огромная задержка?
Код
  PORTB=1; 
                                        a=1; 
                                        PORTC = 1; 
                                        //long i; 
                                        //for(i = 0; i < 1000000; i++); 
                               
                                } 
        PORTC = 0;


И еще. Настройка периферии не через символические имена сильно напрягает, потому что надо лазать в инфу. Т.е. мало кто захочет смотреть и проверять, все ли правильно установлено. Так что вот это GICR = 64; не читабельно.
rvk
Если у Вас трудности с прерыванием, зачем его вообще организовывать?
Можно предположить, что SIGNAL(SIG_OVERFLOW0) это прерывание от Timer0,
и когда отстреляется 28 прерываний и в это время a=0 запускаются лампочки.
После того как лампочки отстрелялись, устанавливается PORTC=1 и тут же PORTC=0,
все происходит очень быстро, возможно, маловероятно, но возможно, второй борд не успевает
словить этот импульс. У Вас в программе есть цикл for(i=0;i<10000;i++) , который заблокирован
в тексте программы. Уберите две черты "//" и сделайте хотя бы
for(i=0;i<100;i++) ; Этого должно с гарантией хватить на ширину импульса.

Если после этого не сработает, можно отказаться от прерываний.
Процессор все равно простаивает, во время ожидания импульса на PORTD0,
вот пусть опрашивает PIND и обрабатывает импульс.
Можно вообще отказаться от прерываний. Если Вы скажете, что это возможно,
приведу здесь текст модуля без прерываний.

PS: пока писал текст опередили, но менять не буду, кашу маслом не испортитьsmile.gif
konstatinopol
Цитата(_Pasha @ Jan 31 2009, 19:25) *
То, что мы сейчас делаем - как раз следствие "кривоватости" void lampochki()
Попробуйте кроме всего сказанного выше вернуть задержку, только зачем Вам такая огромная задержка?

И еще. Настройка периферии не через символические имена сильно напрягает, потому что надо лазать в инфу. Т.е. мало кто захочет смотреть и проверять, все ли правильно установлено. Так что вот это GICR = 64; не читабельно.


Под вернуть задержку вы подразумиваете это??
Код
PORTB=1; 
   a=1; 
   PORTC = 1; 
   long i; 
   for(i = 0; i < 10000; i++); 

PORTC = 0;


А что нащёт GICR = 64; , препод так требует, да и я подругому не умею.
rvk
Про задержку верно, только вместо 10000 поставить 100, этого должно с запасом хватить.
Сергей Борщ
Цитата(konstatinopol @ Jan 31 2009, 17:37) *
А что нащёт GICR = 64; , препод так требует, да и я подругому не умею.
Объсните преподу, что он не прав. Заодно и лишний балл (если препод адекватный) заработаете. Не умеете - учитесь, ведь именно этому (учиться) и должны учить в институте, не так ли?
konstatinopol
Такая ситуация что в данный момент я немогу опробовать программу.
Хочу ещё спросить про логику, то что есть в программе достаточно чтобы это всё работало так как задуманно. Или надо её ещё подработать??
Как только протестирую всё на борте, так сразу же отпишусь.
aesok
Цитата(konstatinopol @ Jan 31 2009, 18:01) *
Анатолий нащёт того чтобы обьявить cntr в SIGNAL(SIG_OVERFLOW0) точно я незнаю, но мы всегда её обьвляли до main(). Возможно и грамотнее но мы задаём ей значение в main() равное 28.


Ваш пример:

CODE
short cntr = 0;

int main()
{
...
cntr = 28;
...
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}



Чем это плохо:
1. Объявление, инициализация и использование разнесены далеко по тексту
программы. Это ухудшает сопровождение программы. В С нет необходимости
инициализировать нулем глобальные переменные, по стандарту это сделает
компилятор. То есть можно просто написать "short cntr;" и в cntr будет 0 перед
входом в main.

Также Вы можете инициализировать глобальные переменные при объявлении любым
значением:
CODE
short cntr = 28;

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}



2. Представьте что ваш проект будет увеличиваться и вам потребуется второй
таймер пишем:
CODE
short cntr;
... много текста ....
short cntr; // добавляем

int main()
{
...
cntr = 28;
... много текста ....
cntr = 144; // добавляем
...
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_OVERFLOW1){
if(!(cntr--))
{
TCNT0=244;
cntr=144;
if(a==0)
lampochki();
}
}


Но это неправильно, cntr будет изменяться сразу из двух обработчиков
прерываний, и придется переименовывать cntr в cntr_for_timer0 и добавлять
cntr_for_timer1. Для экономии своего времени на отладке проекта и
придумывании/написании имен переменых проще объявить cntr локальными
статическими переменными:

CODE
SIGNAL(SIG_OVERFLOW0){
static short cntr = 28;

if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_OVERFLOW1){
static short cntr = 244;

if(!(cntr--))
{
TCNT0=244;
cntr=144;
if(a==0)
lampochki();
}
}


Здесь объявление, инициализация и использование находятся рядом, что
упрощает понимание и изменение кода. Этот код более безопасный, локальные
перемене cntr видны только внутри своих обработчиков SIGNAL(SIG_OVERFLOW0)
и SIGNAL(SIG_OVERFLOW1) и не могут быть изменены из других частей программы.

PS: Что означает static и чем локальная статическая переменная отличается от не статической прочтите в любой книге по языку С.

Анатолий.



Цитата(rvk @ Jan 31 2009, 18:44) *
Про задержку верно, только вместо 10000 поставить 100, этого должно с запасом хватить.


Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);

На любом опримизирующем компиляторе одиноково и равно нулю.

Анатолий.
konstatinopol
Спасибо Анатолий, теперь я понял что вы имели введу, это действительно упрощает код, если в SIGNAL(SIG_OVERFLOW0) занести static short cntr = 244;. А со static я уже знаком, благодарю вас.
rvk
Цитата(aesok @ Jan 31 2009, 19:24) *
Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);

На любом опримизирующем компиляторе одиноково и равно нулю.

Анатолий.


Вот такой код сработает при любом уровне оптимизации.

for(i=0;i<100;i++){
PORTC=1;
}
Qwertty
Цитата(aesok @ Jan 31 2009, 19:24) *
Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);
На любом опримизирующем компиляторе одиноково и равно нулю.

Вовсе нет. Даже на Вашем любимом GCC. Зависит от способа объявления переменной i.
Она ведь может и квалификатор volatile иметь.
aesok
Цитата(Qwertty @ Jan 31 2009, 22:40) *
Вовсе нет. Даже на Вашем любимом GCC. Зависит от способа объявления переменной i.
Она ведь может и квалификатор volatile иметь.


Я не ипытываю никаких чувств к GCC.

В контексте данного поста переменная i объявленна как long.

Время задержки удобнее указывать или в секундах (ms, us) и использовать макросы _delay_ms, _delay_us или в машиных циклах используя _delay_loop_1(uint8_t __count), _delay_loop_2(uint16_t __count) и начиная с WinAVR20081205 __builtin_avr_delay_cycles(uint32_t __count), а не в попугаях меняющихся в зависимости от версии компилятора и уровня оптимизации.

Анатолий.
singlskv
Цитата(rvk @ Jan 31 2009, 19:58) *
Вот такой код сработает при любом уровне оптимизации.
for(i=0;i<100;i++){
PORTC=1;
}
код задержки однозначно в мемориз...
и даже лучше в такой интерпретации:
Код
for(i=0;i<100;i++){
PORTC=rand();
}
smile.gif
Rst7
Цитата
for(i=0;i<100;i++){
PORTC=rand();
}


Не, не круто. Предлагаю зажечь так
Код
for(i=0;i<100;i++){*((volatile int*)i)=rand();}


Все как любят, volatile присутствует smile.gif

Хотя, это конечно шутка. Вообще-то такая затычка имеет право на существование в таком виде
Код
for(i=0;i<100;i++){SREG;}


Разве что в плюсах обматерит, где-то тут целый топик по этому поводу был.
singlskv
Цитата(Rst7 @ Feb 1 2009, 01:07) *
Вообще-то такая затычка имеет право на существование в таком виде
Код
for(i=0;i<100;i++){SREG;}
Ну вот, Вы всю "малину" иcтоптали, я то хотел автора сего "шедевра" задержек подвести через пару
страничек обсуждений smile.gif к мысли что нужно SREG;
А тут Вы... sad.gif
Rst7
Цитата
через пару страничек обсуждений


Будем считать, что я Вас спас от бана за флуд. Так что не жалуйтесь wink.gif
singlskv
Цитата(Rst7 @ Feb 1 2009, 01:20) *
Будем считать, что я Вас спас от бана за флуд. Так что не жалуйтесь wink.gif
Спасибо... beer.gif
delamoure
2Rst7
"for(i=0;i<100;i++){*((volatile int*)i)=rand();}"

Ну нельзя гнать так ночью.
Посмотрел на конструкцию, мысль: все понятно, но что это за "{" и "}"...
Думал секунд 10 smile.gif
Пипец, иду спать...
konstatinopol
Цитата(singlskv @ Feb 1 2009, 01:13) *
Ну вот, Вы всю "малину" иcтоптали, я то хотел автора сего "шедевра" задержек подвести через пару
страничек обсуждений smile.gif к мысли что нужно SREG;
А тут Вы... sad.gif


Товарищи а что собственно такое это SREG ??? Облазил гугл, форум посмотрел, ничего дельного не нашел.
Есть догадки, но не осмеливаюсь произнести их в слух т.к слишком глупые догатки....
SysRq
Цитата(konstatinopol @ Feb 1 2009, 16:12) *
Товарищи а что собственно такое это SREG ???

Регистр состояния smile.gif http://www.atmel.ru/Articles/Atmel15.htm
rvk
Цитата(konstatinopol @ Feb 1 2009, 16:12) *
Товарищи а что собственно такое это SREG ??? Облазил гугл, форум посмотрел, ничего дельного не нашел.
Есть догадки, но не осмеливаюсь произнести их в слух т.к слишком глупые догатки....

for(i=0;i<100;i++){SREG;}

Означает прочитать 100 раз содержимое регистра SREG в никуда.
konstatinopol
Всё работает не так как нужно, а именно :
первый борт пробегает все лампочки и останавливается из-за а=1, но второй борт не получает а=0 и получается так что они оба стоят. Это происходит при задержке и без ней и даже с
Код
for(i=0;i<100;i++){SREG;}


Я незнаю что ещё изменить в программе. На данный момент она выглядит так.
CODE
#include <stdint.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

void lampochki()
{
if(PORTB==1)
{
cntr=14;
PORTB=3;
}
else if(PORTB==3)
{
PORTB=4;
cntr=28;
}
else if(PORTB==4)
{
PORTB=2;
cntr=14;
}
else if(PORTB==2)
{
PORTB=1;
cntr=28;
a=1;
PORTC = 1;
long i;
for(i = 0; i < 100; i++){

SREG;
}
}
PORTC = 0;
}

int main()
{
DDRB=7;
DDRD=0;
PORTB=1;
DDRC = 7;
PORTC=0;
TCNT0 = 244;
TCCR0 = 5;
TIMSK = 1;
GICR = 64; // interrupt port D0 ein
MCUCR = 1; // oder 2
sei();

while(1){}
}

SIGNAL(SIG_OVERFLOW0){
static short cntr = 28;
static int a=0;
if(!(cntr--))
{
TCNT0=244;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_INTERRUPT0){
a=0;
}
aesok
Зачем Вы переменую "a" сделали локальной???????

Она то как раз должна быть глобальной и volatile.

Анатолий.
konstatinopol
Цитата(aesok @ Feb 1 2009, 18:44) *
Зачем Вы переменую "a" сделали локальной???????

Она то как раз должна быть глобальной и volatile.

Анатолий.


Теперь она глобальная и volatile, но всё же не идёт программка ...
В чём может быть проблемма???? Я немогу найти ошибку.
SysRq
А у вас ATMega8? Или 48?
konstatinopol
Цитата(SysRq @ Feb 1 2009, 21:25) *
Если у вас ATMega48 (исхожу из картинки), то этот кусок:
является бредом каким-то (GICR вообще не существует, а с MCUCR выполняется часть процедуры переноса таблицы векторов прерываний).



Дело в том что в предыдущих программах мы работали с GICR и MCUCR и всё работало, просто в данном случае я не уверен в правильности этих значений.
А с EICRA , EIFR и EIMSK мы не работали, но если вы скажите что так правильнее то не буду спорить. Но всё же хотелось зделать программу с GICR и MCUCR.

Точное название борта немогу дать, но на странице производителя стоит myAVR Board MK1 LPT. Страна Германия.
SysRq
Я углядел что на картинке m48 и выше, а m8 не заметил, и написал здоровенный пост, но потом заметил и m8, и написанное стер laughing.gif
Определитесь какой у вас там МК, ибо разница есть, я как раз ее и описал. Или вы без железа проверяете?..

PS: cntr тоже надо сделать глобальной.
konstatinopol
Цитата(SysRq @ Feb 1 2009, 20:52) *
Я углядел что на картинке m48 и выше, а m8 не заметил, и написал здоровенный пост, но потом заметил и m8, и написанное стер laughing.gif
Определитесь какой у вас там МК, ибо разница есть, я как раз ее и описал. Или вы без железа проверяете?..

PS: cntr тоже надо сделать глобальной.


Если я вас понял правильно то MK это микроконтроллер, в описании стоит Prozessor ATmega8
На всякий случай выложу полное описание запчастей :

# 1 Prozessor ATmega8
# 1 RS232Treiber
# 1 Bustreiber 74HC 125N
# 1 Drosselspule 10 µH
# 1 Gleichrichter
# 5 Diode 100mA
# 1 Diode 1A
# 1 gelbe LED 2mA
# 2 grьne LED 2mA
# 1 rote LED 2mA
# 4 Kondensator 1µF
# 4 Kondensator 100nF
# 1 Kondensator 220µF
# 2 Kondensator 33pF
# 1 Kondensator 47µF
# 4 Widerstand 1,2 kOhm
# 2 Widerstand 10,5 kOhm
# 2 Potentiometer
# 2 Miniaturtaster
# 1 IC-Sockel
# 1 Buchse 9-polig SUBD
# 1 Buchse 25-polig SUBD
# 2,25 Sockelleiste SPL20, einreihig
# 1 Piezoschallwandler
# 1 Printstecker
# 1 Standardquarz
# 1 20polig einreihig, abgewinkelt
# 1 Stiftleiste
# 2 PSK-Kontakt
# 1 Kupplungs-Leergehдuse

Страница производителя
Прошу прощения за мою безграмотность.


cntr уже посадил как глобальную.
aesok
У Вас прерывание настроенно по обеим фронтам MCUCR = 1; => ISC01:ISC00 = 01 => Any logical change on INT1 generates an interrupt request.

Нужно скорее всего по одному.

Анатолий.
konstatinopol
Цитата(aesok @ Feb 2 2009, 01:11) *
У Вас прерывание настроенно по обеим фронтам MCUCR = 1; => ISC01:ISC00 = 01 => Any logical change on INT1 generates an interrupt request.

Нужно скорее всего по одному.

Анатолий.


Значит ли это что MCUCR я должен прировнять к 2 ?? Или я ошибаюсь. Я просто запись => ISC01:ISC00 = 01 => неочень понял
aesok
Цитата(konstatinopol @ Feb 2 2009, 01:15) *
Значит ли это что MCUCR я должен прировнять к 2 ??


Или 2 или 3 в зависимость от того переходом PC1 из 1->0 или 0->1 Вы хотите запускать второй сфетофор.

Цитата(konstatinopol @ Feb 2 2009, 01:15) *
Я просто запись => ISC01:ISC00 = 01 => неочень понял


Таблица 31 в даташите на ATmega8.

Биты ISC01 и ISC00 регистра MCUCR задают условия срабатывания
прерывания. Можно написать ISC01, = 0 ISC00 = 1 а можно объединить эти
2 бита записав ISC01:ISC00 = 10.


Анатолий
konstatinopol
Цитата(aesok @ Feb 2 2009, 01:34) *
Биты ISC01 и ISC00 регистра MCUCR задают условия срабатывания
прерывания. Можно написать ISC01, = 0 ISC00 = 1 а можно объединить эти
2 бита записав ISC01:ISC00 = 10.


Напишу как понял. Это значит что в одной программе(на одном борту) должно быть MCUCR=2, а на другом MCUCR=3.
Или мне туда ещё ISC01:ISC00 = 10 вписать нужно?? Программу надо представить уже завтра а я смотрю на неё и немогу понять что в ней надо подправить чтобы она работала.
_Pasha
Цитата(konstatinopol @ Feb 2 2009, 03:10) *
Или мне туда ещё ISC01:ISC00 = 10 вписать нужно??

Надо так:

Код
MCUCR = (1 << ISC01);


Если бы Вы написали что-нить в таком стиле (с симв. именами) изначально, то этот косяк ужЕ вчера бы кому-то на глаза попался.
SysRq
Цитата(_Pasha @ Feb 2 2009, 02:27) *
Если бы Вы написали что-нить в таком стиле (с симв. именами) изначально, то этот косяк ужЕ вчера бы кому-то на глаза попался.

Он попался, но это не имеет значения. Ошибка где-то глобальнее.
konstatinopol
Господа благодарю всех за содействие программа работает без ошибок. biggrin.gif
Проблемма была в том месте где мы закрывали PORTC. Я просто поменял место где его закрываю.
Вот так выглядит готовая программа светофора.

CODE
#include <stdint.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/signal.h>
#include <avr/interrupt.h>


short cntr = 0;
int a=0;

void lampochki()
{
if(PORTB==1)
{
PORTB=3;
}
else if(PORTB==3){
PORTB=4;

}else if(PORTB==4)
{
PORTB=2;

}else if(PORTB==2)
{
PORTB=1;
a=1;
PORTC = 1;
}
}

int main()
{
DDRB=7;
DDRD=0;
PORTD=4;
PORTB=1;
DDRC = 7;
PORTC=0;
TCNT0 = 244;
cntr = 28;
TCCR0 = 5;
TIMSK = 1;
GICR = 64;
MCUCR = 3;
sei();

while(1){}
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
PORTC = 0;
}

SIGNAL(SIG_INTERRUPT0){
a=0;
}


И если борты разсоединить то они оба останавливаются на крассной лампочке.
aesok
Код
#include <stdint.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/signal.h>
#include <avr/interrupt.h>                                                                              

short cntr = 0;
int a=0;


Ах..... не умеете Вы учиться на чужих ошибках. Будете учиться на своих, по крайней мере как делать правильно Вам расказали.

Анатолий.
konstatinopol
Цитата(aesok @ Feb 2 2009, 21:28) *
Ах..... не умеете Вы учиться на чужих ошибках. Будете учиться на своих, по крайней мере как делать правильно Вам расказали.

На своих всегда интерестнее ...
Всёравно спасибо, для меня щас главное что всё работает!!!!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.