реклама на сайте
подробности

 
 
> MSP430 - снова вопросы от чайника, Вопросы от чайника про MSP и магнитный компас
Daria
сообщение Jul 23 2008, 19:17
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



smile.gif Здравствуйте. Кто читал предыдущую мою тему "MSP430 - вопросы от чайника", тот поймет - это снова я biggrin.gif Тему закрыли, слишком долго висела. А вопрсов все больше. smile.gif
Если кому-то вдруг окажется не влом разбираться, то
Вот кусок проги:
int flag;//глобальные переменные
int cindex;
испульзуемые функции(write_flash - пишет число во flash, read_flash - считывает)
void write_flash(float* value, float *addr)
{ while(FCTL1 & BUSY);
_BIC_SR(GIE);
FCTL1 = FWKEY + ERASE;
FCTL3 = FWKEY;
*addr = 0;

while(FCTL1 & BUSY);
FCTL1 = FWKEY + WRT; for (int i=0;i<=3;i++)
{ *addr = value[i];
addr++;
}

_BIS_SR(GIE);
while(FCTL1 & BUSY);
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
}

void read_flash(float* addr, float* pfO)
{
for (int i=0;i<=3;i++)
{ pfO[i]=*addr;
addr++;
}
}
Чего хочу сделать - Если присылаю 0, то должны считаться два показания с выводов P6.3 и P6.4, присылается 0хАА - т.е. "считалось", записываются первые элементы двух массивоы данных.
Когда набирается по четыре элемента, индекс сбрасывается
Если присылаю 0xFF, то должна выполнится функция calibrovka_hmc, если она выполняется неверно, то присылается 0хСС, иначе из flash считывается и присылается вычисленная с помощью этой функции константа.
Внутри функции main
ADC12CTL0 = ADC12ON + REFON + SHT0_8; //настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;

float temp[4];
flag=0;
cindex=0;
for(;;)
{
for(delay = 0; delay <20000; delay++);
if( flag==0 )
{send_int(0x0);
}
if( flag==1 )
{

if (calibrovka_hmc(CVx, CVy, temp)==0)//calibrovka_hmc - имеет параметрами два массива и вычисляет четыре константы(нужные для калибровки устройства)

{
send_int(0xCC);
flag=0;
}
else
{
float pfO[4];
read_flash((float*)0x1000,pfO);
r=(int)(pfO[0]+0.5);
send_int®;
flag=0;
}

flag=4;
}

if (flag==2)
{
ADC12CTL0 |=ADC12SC + ENC; CVx[cindex] = ADC12MEM3; CVy[cindex] = ADC12MEM4;
ADC12CTL0 &= ENC;
cindex++;
send_int(0xAA);
flag=0;
}

if (cindex>3)
cindex=0;
}
}
#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx ( void)
{
if( RXBUF0==0xFF)
flag = 1;
if (RXBUF0==0x0)
flag = 2;
}
В ЧЕМ ПРОБЛЕМА:
Перед выполнением калибровки присылаю элементы массива, полученного при считывании показаний с выводов, - оказывается, что в массив записываются по два-три раза одно значение, хотя этого не может быть. Соответственно, из-за этого не работает и все остальное crying.gif
Может, неправильно настроен АЦП? Или в чем может быть дело?
И, если кому-то вдруг не влом разбираться - функции записи во flash и чтения flash - можно ли сделать как-то поумнее?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
rezident
сообщение Aug 12 2008, 23:30
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Daria, извините за откровенность, но у вас какой-то бред получается sad.gif Вы вообще понимаете суть и механизм работы прерываний? Я не знаю вашего возраста и семейного статуса, но надеюсь что "детская" ассоциация разъяснения сути прерываний будет вам понятна. smile.gif
Представте себе, что вы - мама. Сидите на лавочке с подругой и беседуете. Рядом в песочнице ковыряется и бегает возде нее ваш малыш. И вот в произвольный момент времени малыш подбегает к вам и, прерывая ваш разговор с подругой, спрашивает: "мама, а правда, что море мокрое?" "Правда", отвечаете вы. Малыш, удовлетворенный ответом, убегает, а вы возвращаетесь к разговору с подругой. Через некоторое (опять недетерменированное время) малыш снова подбегает к вам и, прерывает разговор, очередным вопросом: "мама, а небо голубое?" "Конечно голубое, сынок. Подними голову и убедись сам", отвечаете вы. Малыш, задрав высоко голову, долго рассматривает проплывающие в голубом небе облака, а вы по-прежнему продолжаете отложенный разговор с подругой.
Такая аналогия вам понятна? wink.gif
Развиваю мысль дальше.
Запрет прерываний. "Сынок, перестань отвлекать маму вопросами. Дай маме с тетей спокойно поговорить."
Разрешение прерываний. "Сынок, у тебя там все нормально? Никто тебя не обижает? Ну если что-то случится сразу беги ко мне и скажи."
Тот исходник, что вы привели можно переложить на детский сюжет так.
Мама, вместо того, чтобы разговаривать с подругой, отпускает малыша в песочницу и внимательно следит, чтобы он не упал и не перепачкался. Как только ребенок падает, она, отряхнув его одежду, говорит: "Ну вот, смотри как ты перепачкался! Не ходи больше в песочницу, поиграй рядом с мамой, пока я с этой тётей побеседую". Усадив ребенка рядом, продолжает беседу.
А эта аналогия понятна?
Вы запускаете преобразование АЦП и, не выходя из прерывания, ждете окончания преобразования и установки бита готовности. Спрашивается ЗАЧЕМ? 07.gif Факт возникновения прерывания УЖЕ является свидетельством о том, что преобразование выполнено и в регистре ADC12MEMx находится готовое значение. После перехода по вектору прерывания вам нужно только считать это значение и при необходимости (пере)запустить или остановить цикл последующих преобразований АЦП. Ждать готовности преобразования, находясь прямо в прерывании нет никакой необходимости!

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

И еще просьба. Оформляйте, пожалуйста, ваш текст исходников в теги code. Это такая решеточка над полем редактирования сообщения. Так сохраняются все отступы и код получается более удобным для восприятия.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 13 2008, 17:06
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 13 2008, 03:30) *

Rezident, циклы while совершенно случайно оказались в прерывании! Просто копировала и ... дело было вечером... 05.gif Так что совершенно зря разразились такой тирадой smile.gif Впрочем, не зря, долго еще могла не заметить. А история про маленького мальчика - супер. biggrin.gif Но - запрещение прерываний в прерывании таймера и АЦП делаю осознанно smile.gif , при переключении вывода должен пройти переходной процесс, прежде чем можно разрешать преобразование АЦП. Так что переключение вывода и старт АЦП должны совершенно точно делаться в разные моменты времени. Такие дела. А вообще - как всегда, спасибо biggrin.gif
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 14 2008, 08:09
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Ух-х, какие крутые виражи! Ух, как человека мысли колбасят:
Цитата( @ Aug 13 2008, 23:06) *
... Так что совершенно зря разразились такой тирадой smile.gif

И сразу же, не давая осознать -- ба-бах!
Цитата
Впрочем, не зря, ...


Rezident -- восхищаюсь Вашим терпением. Буду счастлив, если даму удастся выдернуть из девичьего восприятия мира. Да, длинный путь предстоит, долго ей топать. Но, человека надо вытаскивать. Тем более, сам чел этого хочет.

Daria, не останавливайтесь на полпути! Мы все за Вас переживаем и хотим получить полноценного товарища. Глупой Вас никто не считает, просто склад ума/логика мышления у Вас несколько иные. Это не плохо и не хорошо, это -- просто имеет быть.

"Не важно -- кто ты и где ты сейчас. Важно -- куда ты живешь" (С) не помню чье.
Всех благ!


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 14 2008, 20:47
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(zhevak @ Aug 14 2008, 12:09) *
Rezident -- восхищаюсь Вашим терпением. Буду счастлив, если даму удастся выдернуть из девичьего восприятия мира. Да, длинный путь предстоит, долго ей топать. Но, человека надо вытаскивать. Тем более, сам чел этого хочет.

Я сама восхищаюсь его терпением 07.gif Я бы себя уж давно послала, причем с громкими выкриками biggrin.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Daria, не останавливайтесь на полпути!

Ну не знаю, не знаю. мы женщины все такие непоследовательные - то почитать, то пострелять... biggrin.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Мы все за Вас переживаем

Надеюсь, аппетит не пропал? wink.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Всех благ!

И Вам!! Спасибо за мнение

Rezident, по поводу буфера, пример которого вы приводили. А что, если cbuf.rIdx будет равен cbuf. wIdx +1? Т.е. если считывание "обгонит" запись? Может, стоит поверять if((cbuf.cntr< max_bufsize)&(cbuf.rIdx !=cbuf. wIdx +1))?
Или опять мойс клад ума/логика мышления меня подвел? sad.gif тогда - ой, беда, беда - огорчение.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 14 2008, 21:01
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 15 2008, 02:47) *
Rezident, по поводу буфера, пример которого вы приводили. А что, если cbuf.rIdx будет равен cbuf. wIdx +1? Т.е. если считывание "обгонит" запись? Может, стоит поверять if((cbuf.cntr< max_bufsize)&(cbuf.rIdx !=cbuf. wIdx +1))?
Или опять мойс клад ума/логика мышления меня подвел? sad.gif тогда - ой, беда, беда - огорчение.
Вы про циклический буфер? Считывание не может обогнать запись, т.к. перед считыванием должен проверяется счетчик записей. Если счетчик равен нулю, то буфер пуст. А если при этом имеется "разбег" индексов, то его нужно обнулить, установив оба индекса в начало буфера. Только при этом конечно же нужно соблюдать атомарность доступа, чтобы не произошло сбоев записей при одновременном доступе к переменным индексов и счетчика. Атомарность доступа можно обеспечить временным запретом прерываний.
В дополнение. Ситуация когда cbuf.rIdx будет равен cbuf. wIdx +1 не исключена. Но она может быть только в случае, когда весь буфер заполнен. При этом счетчик элементов буфера должен иметь значение равное размеру буфера.
Хотя пожалуй нет. Я ошибся. Счетчик в этом случае будет равен размер_буфера-1. Т.к. для полностью заполненного (и для пустого) циклического буфера значения индексов д.б. равны.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 17 2008, 11:13
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Ага, будем считать с буфером приема разобрались smile.gif Теперь что касается передачи. Во-первых, все-таки мой старый вопрос - как в этом случае обойтись без этих циклов while, которые ждут установки флага о готовности? ведь тут тоже пустой простой... Что касается буфера, то у меня как-то не получилось biggrin.gif и даже наверное не буду приводить код, опять будете смеяться biggrin.gif Хотя бы принцип верный? -
Запись в буфер идет в прерывании АЦП, считывается постоянно в цикле for(;;); так как вообще говоря передача должна идти посылками по 4 байт (стартовый символ"*", два байта данных (int) и стоповый "#"), то считывается сначала в массив [4], а этот массив передается по байтам через регистр U0TXBUF. Но, когда передается, как обойтись без этих while?
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 17 2008, 15:09
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 17 2008, 17:13) *
Запись в буфер идет в прерывании АЦП, считывается постоянно в цикле for(;;); так как вообще говоря передача должна идти посылками по 4 байт (стартовый символ"*", два байта данных (int) и стоповый "#"), то считывается сначала в массив [4], а этот массив передается по байтам через регистр U0TXBUF. Но, когда передается, как обойтись без этих while?
Дык точно также как вы с АЦП делаете. Использовать передачу по прерываниям.
uart0.h
Код
#ifndef UART0_H
#pragma pack(2)
typedef struct st_uart  //тип структуры данных буфера UART0
{ unsigned int cntr;    //счетчик буфера
  unsigned int idx;     //индекс буфера
  unsigned char buf[10];//буфер UART
} st_uart;
#pragma pack()
#define UART0_H
#endif

main.c
Код
#include "uart0.h"

unsigned int adcRes;//результат преобразования АЦП, который нужно передать
st_uart uart;           //структура данных буфера UART0

void main( void )
{
  while(1)
  {
//  ...
    if ((IE1&UTXIE0)==0); //проверяем готовность UART0 к передаче, бит UTXIE0
    { uart.idx=0;         //используем еще и как признак окончания передачи пакета
      uart.cntr=0;
      uart.buf[uart.cntr++]='*';  //символ начала пакета
      uart.buf[uart.cntr++]=adcRes>>8;  //старший байт результата
      uart.buf[uart.cntr++]=adcRes&0xFF;//младший байт результата
      uart.buf[uart.cntr++]='#';  //символ конца пакета
      IFG1|=UTXIFG0;     //установим флаг, чтобы инициировать прерывания UART0
      IE1|=UTXIE0;        //разрешим прерывания UART0
    }
//  ...
  }
}

#pragma vector=USART0TX_VECTOR
#pragma type_attribute=__interrupt
void UART0TX_ISR(void)
{ if (uart.cntr>0)    //проверяем количество символов в буфере
  { U0TXBUF=uart.buf[uart.idx++]; //передаем текущий символ
    uart.cntr--;      //уменьшаем счетчик количества символов
  }
  else
    IE1&=~UTXIE0;     //если буфер пуст, то сбрасываем бит разреш.прерыв. UART0
}

Я использовал в примере typdef на случай, если вы разбиваете проект на отдельные модули. Если же у вас вся программа в одном файле, то можно объявить структуру uart прямо перед main-ом. Вместо строки
Код
st_uart uart;           //структура данных буфера UART0

Бит разрешения прерывания от передатчика UART0 я использовал как флаг готовности буфера передатчика. Он устанавливается в main, одновременно разрешая прерывания от передатчика и сбрасывается в обработчике прерывания по завершению передачи буфера. Для передачи 4-х байтного пакета будут 5 прерываний от передатчика UART0. В последнем прерывании передачи символа не будет, а будет лишь сброшен UTXIE0.

Цитата(zhevak @ Aug 17 2008, 20:49) *
Интересен вызов функция GetKey(). Вро де бы все ясно -- функция должна вернуть код клавиши. А что делать, если ни одна клавиша не нажата? Получается, функция

управление не должна возвращать. Допустим, что это так. Тогда получается, что наше устройство постоянно как-бы зависает на этой функции. И действительно, посчитать

результат и вывести его, действительно, занимает не так уж и много времени по сравнению с тем, что юзер может вообще пойти попить кофейку. Да?

Но для нашего устройства такое построение программы не страшно. Поскольку предопределенные действия выполняются тогда, когда юзер соизволит нажать кнопочку.
Извините, но у вас ерунда написана. Функция GetKey() никогда не циклится на опросе, а всегда и в любом случае возвращает код нажатой клавиши, иначе она бы называлась не GetKey, а WaitKey biggrin.gif Только в случае когда ни одна клавиша не нажата функций GetKey возвращает скан-код NULL. А если идет запись в буфер клавиатуры, то просто запись туда не производится. Поэтому бесконечный цикл вовсе не зависает на опросе клавиатуры, а крутится себе как и положено wink.gif Естественно, что в функции DoSomething() должна быть предусмотрена обработка скан-кода с кодом NULL.
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 17 2008, 15:51
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(rezident @ Aug 17 2008, 21:09) *
Извините, но у вас ерунда написана. Функция GetKey() никогда не циклится на опросе, а всегда и в любом случае возвращает код нажатой клавиши, иначе она бы называлась не GetKey, а WaitKey biggrin.gif Только в случае когда ни одна клавиша не нажата функций GetKey возвращает скан-код NULL. А если идет запись в буфер клавиатуры, то просто запись туда не производится. Поэтому бесконечный цикл вовсе не зависает на опросе клавиатуры, а крутится себе как и положено wink.gif Естественно, что в функции DoSomething() должна быть предусмотрена обработка скан-кода с кодом NULL.


Не, не! Не стоит так сильно реагировать на имя!

Функция GetKey() -- это моя функция, не библиотечная. Про библиотеки не говорю. Более того, я не писал готовый коупи-пэйст код, а излагал парадигму. Жаль что Вы зацепились за эту мелочь. Если Вас это очень смущает, ну замените что-ли название функции на GetPressedKey().


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 17 2008, 15:56
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zhevak @ Aug 17 2008, 21:51) *
Не, не! Не стоит так сильно реагировать на имя!

Функция GetKey() -- это моя функция, не библиотечная. Про библиотеки не говорю. Более того, я не писал готовый коупи-пэйст код, а излагал парадигму. Жаль что Вы зацепились за эту мелочь. Если Вас это очень смущает, ну замените что-ли название функции на GetPressedKey().
Да меня вообще не волнует названия функций smile.gif, а "прицепился" я как раз а вашей "парадигме", то бишь к описанию алгоритма "вечного цикла". Я бы еще понял зацикливаение на опросе клавиатуры, если бы перед этим MCU ушел в режим "спячки" для энергосбережения. Вы же описали другой алгоритм, который я не считаю оптимальным в частности и верным в общем. А если вы хотели описать "парадигму" расслоения на os, driver и application, то извините, сделали это не очень внятно. laughing.gif
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 17 2008, 16:38
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(rezident @ Aug 17 2008, 21:56) *
Да меня вообще не волнует названия функций smile.gif, а "прицепился" я как раз а вашей "парадигме", то бишь к описанию алгоритма "вечного цикла". Я бы еще понял зацикливаение на опросе клавиатуры, если бы перед этим MCU ушел в режим "спячки" для энергосбережения. Вы же описали другой алгоритм, который я не считаю оптимальным в частности и верным в общем. А если вы хотели описать "парадигму" расслоения на os, driver и application, то извините, сделали это не очень внятно. laughing.gif

не надо laughing.gif -- Я не описывал расслоение. Я описывал только парадигму событийно-управляемой системы. Т.е. ситему, которая работает на принципе реагирования на какие-либо события. Система не занимается поллингом. Система ждет событий, в свободное от работы время совершает холостые циклы. Если хотите -- может вообще спать. Не проблема!

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

Изложенная мною (но не я автор!) парадигма построения программ, предполагает, что она применяется к устройствам, которые намного сложнее, чем простой генератор прямоугольных импульсов. Да, действительно, там проще и легче в основном цикле программы сначала проверять конкретное ПУ (UART, ADC, таймер,...) и, если оно готово, вызывать соответствующую функцию. После чего переходить к проверке следующего ПУ. И т.д. до конца цикла.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 17 2008, 20:49
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



smile.gif Да-а-а 07.gif утром отправляю вопрос, иде себе спокойненько по своим делам, захожу вечером, а тут!... 07.gif Целая переписка Маркса и Энгельса! Я, когда защищалась на своем матфаке, то у меня доп. диплом был по квалификации "преподаватель" smile.gif Этот диплом представлял собой цикл лекций по истории развития теории вероятностей. Там тоже было много всяких примеров, баек и исторических справок. к чему это я? biggrin.gif А к тому, что вам, господа, особенно вам, zhevak, можно не только диплом защищать по специальности "преподаватель программирования контроллеров" , а целую кандидатскую по теме "история развития программирования контроллеров и ваще программирования" biggrin.gif
Но - если чел находит столько времени, сил и желания помочь и рассказать, то - большое спасибо, заходите еще, буду рада и все такое. Rezident, ваша лекция про детей и песочницы тоже была просто класс biggrin.gif a14.gif
Да, rezident, я давно знала, что вы хороший, но вы - ПРОСТО СУПЕР! biggrin.gif Большое спасибо за помощь. Даже не знаю, как вас благодарить за месяцы мучений со мной(а еще сколько предстоит... smile.gif )
На досуге подумаю об этом smile.gif (ну, ну - утихомирьтесь, случайно заглянувшие сюда пошляки) Будут пожелания - высказывайтесь biggrin.gif Есть пара непоняток по вашему коду, но пока не буду спрашивать - вдруг в процессе внедрения сама пойму biggrin.gif
заходите обязательно еще!
Эх, кто бы мне еще по поводу датчиком HMC помог - непонятки все же с калибровкой... т.е. самый простой способ понятен и почти работает, но при таком ТЗ он никак не годится... В разделе "датчики, метрологи и т.п." все на эту тему молчат crying.gif но это так, мысли вслух, и к теме не отностится
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 19 2008, 17:42
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



здравствуйте снова. Такой вопрос - во время работы проги, для того, чтобы выполнить калибровку, хочу перенастроить АЦП из однократно-последовательного режима в повторно-последовательный. И для калибровки работать без прерываний. Это ведь делается редко и при выполнении калибровки все остальное вообще не работает, можно же тогда и с циклами while, правильно? smile.gif Дело в том, что все остальное делается теперь по прерываниям и, запрещая их, очень легко и просто все останавливаю. Так вот. Могу я написать так:
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_1
ADC12CTL1 |= CONSEQ_3
Ну и после калибровки
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_3
ADC12CTL1 |= CONSEQ_1
Нет тут какого-нибудь недопустимого действия? А то мало ли, чего мое альтернативное мышление натворит smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 19 2008, 21:40
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 19 2008, 23:42) *
можно же тогда и с циклами while, правильно? smile.gif
Можно. Даже нужно. Чтобы не переопределять основной алгоритм измерения в прерывании.
Цитата(Daria @ Aug 19 2008, 23:42) *
Могу я написать так:
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_1
ADC12CTL1 |= CONSEQ_3
Ну и после калибровки
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_3
ADC12CTL1 |= CONSEQ_1
Нет тут какого-нибудь недопустимого действия? А то мало ли, чего мое альтернативное мышление натворит smile.gif
Можно, только аккуратнее с битовыми масками. Чистить биты CONSEQx лучше всегда так
Код
ADC12CTL1 &=~CONSEQ_3;

чтобы каждый раз не задумываться и случайно не "пролететь", ошибившись с предыдущим режимом измерения ADC12. Ну и конечно после изменения режима, не забыть вновь разрешить преобразование, установив ENC. А так, все верно, за исключением того, что хорошо бы изменить порядок сброса CONSEQx и ENC. Сначала останов последовательности преобразований сбросом CONSEQx, а потом сброс ENC. Это может быть существенным когда вы используете (разрешили) прерывание ADC12.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 20 2008, 18:20
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 20 2008, 01:40) *
А так, все верно, за исключением того, что хорошо бы изменить порядок сброса CONSEQx и ENC. Сначала останов последовательности преобразований сбросом CONSEQx, а потом сброс ENC. Это может быть существенным когда вы используете (разрешили) прерывание ADC12.

Спасибо!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 21 2008, 18:01
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте. rezident, по поводу примера буфера передачи, который Вы написали smile.gif
для чего делается вот это
#pragma pack(2)
...
#pragma pack()
Как я понимаю, это выравнивание? т.е. #pragma pack(2) - теперь структура будет иметь четное количество байтов, а #pragma pack() - возвращение к установке "по умолчанию"? Так или не совсем? А зачем тогда именно pack(2)? Если написать pack(1) - то будет ровно то количество байт, которое задается, т.е. четыре.
? Объясните чуть подробнее, пожалуйста. smile.gif И еще - почему именно buf[10], чем обусловлено 10 и как его выбирать? smile.gif

И вообще мне не понятно, при таком протоколе, а это вроде довольно распространенный: *, данные, #- как быть при приеме? Вот цифровое значение # - 35, а если приходит такое число? Вот азимут у меня, допустим, 35 - тогда же путаница получится?
Вот у меня такой флажок 0хFF - уникален, учитывая, что передаю по 6 бит smile.gif А как обычно делают?
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 21 2008, 21:19
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 22 2008, 00:01) *
для чего делается вот это
#pragma pack(2)
...
#pragma pack()
Как я понимаю, это выравнивание?
Да, это выравнивание структуры.
Цитата(Daria @ Aug 22 2008, 00:01) *
т.е. #pragma pack(2) - теперь структура будет иметь четное количество байтов,
Нет, не "иметь четное количество байт", а члены структуры будут выровнены на границу 2-х байтового слова.
Цитата(Daria @ Aug 22 2008, 00:01) *
а #pragma pack() - возвращение к установке "по умолчанию"?
Да.
Цитата(Daria @ Aug 22 2008, 00:01) *
А зачем тогда именно pack(2)?
Потому, что MSP430 16-и разрядный микроконтроллер и доступ к переменным структуры по невыровненному на границу 16-и битного слова указателю может привести к очень неприятным ошибкам.
Цитата(Daria @ Aug 22 2008, 00:01) *
Если написать pack(1) - то будет ровно то количество байт, которое задается, т.е. четыре.
Общее количество байт занимаемое данной конкретной (упоминаемой ранее) структурой будет то же самое, т.к. она уже сама по себе выровнена за счет подбора порядка следования переменных внутри структуры. Но на архитектуре большей разрядности, при другом размере выравнивания размер структуры может увеличиться.
Цитата(Daria @ Aug 22 2008, 00:01) *
? Объясните чуть подробнее, пожалуйста. smile.gif
Объясняю. Имеем вот такую структуру, выровненную на размер 1 байта
Код
#pragma pack(1)
typedef struct qqq_t
{ char a;
  int b;
  long c;
  char d;
} qqq_t;
#pragma pack(1)

qqq_t QQQ;

qqq_t *pQ=&QQQ;

Допустим, что компилятор расположил структуру, начиная с адреса 0x0200, выровняв ее на границу байта. Тогда структура займет в памяти 8 байт.
QQQ.a расположена по адресу 0x0200 - нормально, 1 байт
QQQ.b расположена по адресу 0x0201 - внимание! слово по нечетному адресу!!!, 2 байта
QQQ.c расположена по адресу 0x0203 - опять внимание!!!, 4 байта
QQQ.d расположена по адресу 0x0207 - допустимо, т.к. переменная 1-но байтовая, 1 байт
Теперь, если мы захотим изменить значение, например, элемента b, то в указатель будет загружен ее адрес 0x0201.
Код
pQ->b += 1;

И мы получим полный облом - обращение к 16-и битному слову по нечетному адресу!!! Но поскольку архитектура MSP430 такого не позволяет, то этим оператором будет считано значение слова по четному адресу (0x0200, вместо 0x0201) и увеличенное на единицу значение будет записано по этому же адресу (0x0200). В результате изменится не только значение переменной под именем b, но и значение переменной a тоже.
Если же мы предусмотрительно сделаем выравнивание на границу 16-и разрядного слова, то структура расположится в памяти, заняв правда уже 9 байт, так.
QQQ.a по адресу 0x0200 - нормально, 1 байт
неиспользуемый 1 байт по адресу 0x0201
QQQ.b по адресу 0x0202 - нормально, 2 байт
QQQ.c по адресу 0x0204 - нормально, 4 байт
QQQ.d по адресу 0x0208 - нормально, 1 байт
Но зато при этом выравнивании не будет никаких проблем при обращении с помощью указателя к любому члену структуры, т.к. все адреса членов структур четные и выравнены на границу 16-и разрядного слова.
В случаях когда мы сами себе хозяева, а состав структуры данных нам не "спущен сверху", то можно перетасовать элементы структуры так, чтобы они располагались в памяти более оптимально, без "дырок", образующихся при выравнивании. Лучше располагать их в порядке убывания размеров переменных. Например.
Код
#pragma pack(2)
typedef struct qqq_t
{ long c;
  int b;
  char a;
  char d;
} qqq_t;
#pragma pack()

Еще момент. Вроде бы тут структура уже самоупорядочилась и выравнивание вроде не требуется. Но это только для того случая, когда структура сама по себе единица данных. Если же мы попробуем включить эту структуру в состав другой (невыравненной) структуры, то можем получить снова такую же ситуацию, которая описана чуть выше. Так что я за то, чтобы структуры всегда были выровнены. Причем если используется 32-х битная архитектура, то выравнивать лучше на границу 32-х битного слова (на 4 байта).
Вообще говоря, стандартом Си гарантируется только порядок следования членов структуры, а насчет занимаемого в памяти размера структуры стандарт ничего не говорит. Это отдается на откуп программисту и компилятору. Поэтому при переносе структур данных на архитектуры разной разрядности нужно быть очень внимательным.
Цитата(Daria @ Aug 22 2008, 00:01) *
И еще - почему именно buf[10], чем обусловлено 10 и как его выбирать? smile.gif
А данном случае 10 это абстрактное число взятое мной "с потолка" smile.gif Размер буфера выбирается, исходя из максимального размера пакета или, исходя из времени определяемого неравномерностью доступа к буферу. Первый случай рассматривать по-моему не стоит. Размер буфера д.б. не меньше, чем максимальный размера принимаемого пакета. Это для случая когда требуется принять весь пакет целиком и только потом начать его разбор.
Второй случай. Допустим, нам хочется организовать непрерывный поток данных через UART и для этого мы хотим использовать буфер аля FIFO - линейный буфер по принципу "первый вошел-первый вышел". Пускай отправка 1 символа UART занимает условно 10мс. А темп поступления данных на конвейер UART определяется какими-либо внешними событиями, распределенными по времени неравномерно от 0,2 мс до 20мс. Какого размера буфер требуется? Исходя из самого худшего предположения, за время отправки 1 символа (10мс) мы можем получить до 50 символов с периодом 0,2мс. Значит размер буфера должен быть (10-0,2)/0,2>=49 элементов. Конечно, это для случая нормального (гауссового) распределения задержек в указанном диапазоне. В противном случае нам может не хватить даже буфера из 1000 элементов, если на каком-то весьма продолжительном отрезке времени данные будет поступать с высоким темпом (с минимальной задержкой).
Цитата(Daria @ Aug 22 2008, 00:01) *
И вообще мне не понятно, при таком протоколе, а это вроде довольно распространенный: *, данные, #- как быть при приеме? Вот цифровое значение # - 35, а если приходит такое число? Вот азимут у меня, допустим, 35 - тогда же путаница получится?
Вот у меня такой флажок 0хFF - уникален, учитывая, что передаю по 6 бит smile.gif А как обычно делают?
Обычно символы начала (и конца) пакета являются уникальными. При этом либо весь пакет как-то обрабатывается (кодируется) так, чтобы не допустить символ с кодом начала (конца) пакета, либо совпадающие по коду символы дублируются, либо заменяются на последовательность уникальных символов. Посмотрите, например, описание протокола Wake, там эта проблема решена вполне изящно.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 24 2008, 17:36
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Как всегда - большое спасибо! smile.gif про выравнивание ясно, про размер буфера - тоже(примерно).
С протоколом буду разбираться, будут вопросы - завтра задам biggrin.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 29 2008, 18:53
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте снова.
Вот опять вопросы_
Делаю усреднение по по тридцать отсчетов
Код
int filter1(int input[], int in)
{    float result = 0;                  
    int i;
    if (in>0)
    {
        for (i = 0; i < 30; i++)    
            result += input[i];
            result=result/in;
        for (i = 0; i < 30; i++)    
            input[i] = input[i+1];    

        return (int)(result);
    }
}

Потом в прерывании АЦП
Код
if((index>=29)|(f==1))//если уже набрался массив  из 30 элементов для усреднения
    {               f=1;
        Vr[0][29]= ADC12MEM3;
        Vr[1][29] = ADC12MEM4;
                    
        ADC12CTL0 &= ~ENC;    
                
        buf[0] = filter1(Vr[0], 30);    //фильтр
        buf[1] = filter1(Vr[1], 30);
                    
        offset[0] = (Vs[0] -buf[0])/2;     // вычисляются смещения на основе Vset, Vreset
        offset[1] = (Vs[1] - buf[1])/2;
        Vx = buf[0] - offset[0];        //координаты вектора маг. индукции
        Vy = buf[1] - offset[1];
                        
        index=0;            
                        
                    
            float F[2];
            azimut = calculation (Vx,Vy,F);
            send_int(azimut);
    }
                
if ((index<29)&(f==0))// пока массив не набрался
                
               {
                   Vr[0][index]= ADC12MEM3;
                   Vr[1][index] = ADC12MEM4;
        index++;
        ADC12CTL0 &= ~ENC;    
               }

Массив Vr[2][30] глобальный. Преобразование АЦП разрешается в прерываниях от таймера, которые происходят через 5мс. флаг f становится равным единице, когда уже набрался массив, индекс потом обнуляется, чтобы не возрастал постоянно до максимального значения, а флаг остается.
Кривовато?
Дело в том, что почему-то для 30 отсчетов работает, для 35 - тоже, а для 40 - уже нет, передача данных не идет. Хотя в отладчике все вроде происходит нормально, хоть до ста отсчетов давай.
И все-таки по поводу буфера,rezident.
Выравнивание #pragma pack(2) почему-то дает какой-то жуткий эффект - данные перепутываются и вообще не идут. А если по одному байту выравнивать, то нормально...но и данные ведь по одному байту пишутся. И вообще-то, зачем делать счетчик буфера int? Буфер же однобайтовый... 05.gif
Поясните еще, я все же видимо, непонятливая 05.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 29 2008, 20:16
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 30 2008, 00:53) *
Делаю усреднение по по тридцать отсчетов

Что-то не совсем понятно, что за сдвиг вы формируете при усреднении? Вы пытаетесь фильтровать скользящим средним что ли? Или просто накапливаете 30 значений, а потом среднее арифметическое берете? Тогда зачем сдвиг элементов буфера? cranky.gif
Цитата(Daria @ Aug 30 2008, 00:53) *
Потом в прерывании АЦП
Вычисления и фильтрация в прерывании??? 07.gif Эх, Дарья, ничево вы видимо не поняли sad.gif
Цитата(Daria @ Aug 30 2008, 00:53) *
if((index>=29)|(f==1))//если уже набрался массив из 30 элементов для усреднения
Сразу же ошибка. Оператор | это "побитовое ИЛИ". Более уместное в логическом выражении "логическое ИЛИ" записывается как ||.
Цитата(Daria @ Aug 30 2008, 00:53) *
...

Поскипано. Мне грустно видеть как жуткие вычисления с плавучкой в прерывании транжирят драгоценное время crying.gif
Цитата(Daria @ Aug 30 2008, 00:53) *
if ((index<29)&(f==0))// пока массив не набрался
Опять аналогичная ошибка. "Логическое И" записывается как &&. Одиночный амперсанд & это "побитовое И".
Цитата(Daria @ Aug 30 2008, 00:53) *
Кривовато?
Не то слово!
Цитата(Daria @ Aug 30 2008, 00:53) *
Дело в том, что почему-то для 30 отсчетов работает, для 35 - тоже, а для 40 - уже нет, передача данных не идет. Хотя в отладчике все вроде происходит нормально, хоть до ста отсчетов давай.
А вы в отладчике посмотрите сколько циклов занимает ваш расчет и фильтрация wink.gif Поделите на тактовую MCLK и выясните, как оно соотносится с 5мс таймерными прерываниями? Ведь пока вы в прерывании АЦП считаете, все остальные прерывания запрещены.
Цитата(Daria @ Aug 30 2008, 00:53) *
И все-таки по поводу буфера,rezident.
Выравнивание #pragma pack(2) почему-то дает какой-то жуткий эффект - данные перепутываются и вообще не идут. А если по одному байту выравнивать, то нормально...но и данные ведь по одному байту пишутся.
Что перепутывается? Кто куда не идет? Про какой именно буфер речь? Если про буфер UART, то что там не так с выравниванием? Вынесите сам буфер (массив) типа unsigned char наружу структуры, как самостоятельный глобальный массив переменных. Его-то выравнивать не нужно. А в структуре только указатель на начало этого массива оставьте.
Цитата(Daria @ Aug 30 2008, 00:53) *
И вообще-то, зачем делать счетчик буфера int? Буфер же однобайтовый... 05.gif
Потому, что в Си тип int является машинно-ориентированно-оптимальным. Поскольку MSP430 16-и разрядный микроконтроллер, то 16-и битовое слово является для него оптимальным. А, например, на ARM тип int 32-х битный. Нет, вы конечно же можете имеете право и unsigned char для счетчика использовать, если стоит задача экономии ОЗУ. У MSP430 есть команды для работы с байтовыми операндами. Я же совершенно не против laughing.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 30 2008, 18:33
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Да знаю я, знаю, что долго сидеть в прерывании нехорошо, не ругайтесь так... biggrin.gif Но тут какая проблема была - если вычисления делать просто в цикле for(;;), то за время, пока эти вычисления делаются, уже успевает прийти несколько прерываний, и данные обновляются прямо по ходу вычислений. И происходит такая вещь - если плавно поворачивать плату, то оцифрованый уровень меняется далеко не плавно, жутко скачет во время поворота и долго "успокаивается", если вращать быстро, то будет долгий переходной процесс - т.е. улетает сначала намного выше реального уровня, затем медленно возвращается. Вот, по-женски так объясняю, самой смешно biggrin.gif я думаю, это происходит оттого, что допустим координата Х уже просчиталась, а У еще нет, пришло прерывание, данные обновились, У считается, и уже характеризует новое положение, а Х - еще старое, поэтому при вращении возникают большие ошибки.
Такое дело нежелательно, потому что компас может медленно вращаться во время использования, или сразу после остановки может быть обращение к нему. Я перенесла вычисления прямо в прерывание, и все стало меняться просто на заглядение плавно biggrin.gif Кстати, на ваш вопрос - да, усредняю скользящим, среднее арифметическое - это глупо даже для меня biggrin.gif Каждый раз дожидаться, пока наберется 30 отсчетов... Я жду, пока они наберутся только в самом начале работы, а потом каждое новое число записывается 30-м элементом массива, и массив усредняется и сдвигается.
Ну да, зато теперь тратится куча времени... 05.gif
А, если все же не в прерывании считать, то как бы избавится от той проблемы, о которой я говорю? если, конечно, вы меня поняли biggrin.gif у меня в последнее время с объяснением не лады 05.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 30 2008, 21:04
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 31 2008, 00:33) *
Да знаю я, знаю, что долго сидеть в прерывании нехорошо, не ругайтесь так... biggrin.gif Но тут какая проблема была - если вычисления делать просто в цикле for(;;), то за время, пока эти вычисления делаются, уже успевает прийти несколько прерываний, и данные обновляются прямо по ходу вычислений.
Есть два способа решения этой проблемы. Либо на время вычислений в основном цикле запрещать прерывания от АЦП (либо останавливать его) - все равно АЦП не работает, когда вы считаете в прерывании. Либо использовать два циклических буфера. В то время пока вы обсчитываете результаты одного буфера, в другой буфер (по прерываниям АЦП) идет запись новых результатов изменений. В основном цикле вы только устанавливаете номер буфера и флаг сигнализирующий обработчику прерывания АЦП о смене номера буфера. В прерывании АЦП сначала анализируется состояние флага и при необходимости изменяется указатель на буфер, а запись новых значений происходит уже в другой буфер.
Цитата(Daria @ Aug 31 2008, 00:33) *
И происходит такая вещь - если плавно поворачивать плату, то оцифрованый уровень меняется далеко не плавно, жутко скачет во время поворота и долго "успокаивается", если вращать быстро, то будет долгий переходной процесс - т.е. улетает сначала намного выше реального уровня, затем медленно возвращается. Вот, по-женски так объясняю, самой смешно biggrin.gif я думаю, это происходит оттого, что допустим координата Х уже просчиталась, а У еще нет, пришло прерывание, данные обновились, У считается, и уже характеризует новое положение, а Х - еще старое, поэтому при вращении возникают большие ошибки.
Значит у вас где-то ошибка в алгоритме. нужно синхронизировать обновления значений переменных координат так, чтобы не было разбега, как он у вас описан.
Цитата(Daria @ Aug 31 2008, 00:33) *
Кстати, на ваш вопрос - да, усредняю скользящим, среднее арифметическое - это глупо даже для меня biggrin.gif Каждый раз дожидаться, пока наберется 30 отсчетов... Я жду, пока они наберутся только в самом начале работы, а потом каждое новое число записывается 30-м элементом массива, и массив усредняется и сдвигается.
Ну да, зато теперь тратится куча времени... 05.gif
А вам приниципально усреднять уже готовые значения координат или можно усреднять непосредственно отсчеты АЦП? Ведь просуммировать целые числа получается гораздо быстрее, чем получить сумму "плавучих" чисел? К тому же при целочисленных вычислениях не накапливается ошибка округления. Поэтому алгоритм скользящего вычисления среднего можно значительно ускорить. Для этого нужно лишь хранить отдельно текущее значение суммы элементов буфера. При поступлении нового значения в буфер достаточно вычесть из этой суммы значение самого древнего элемента буфера, прибавить значение нового элемента буфера и вуаля! - вы получаете готовую сумму. Итого одно сложение и одно вычитание, вместо суммирования всего буфера. Для "плавучки" такой способ не годиться, т.к. довольно быстро набегает ошибка вычисления суммы. К тому же зачем вы каждый раз при записи нового значения в буфер сдвигаете все элементы в буфере? Это же лишнее время и совершенно ненужное действие. Сдвигайте не сам буфер, а лишь индекс-указатель на текущий элемент буфера. Получается то же самый неоднократно упомянутый циклический буфер.
Код
#define MAXNUMFLTRBUF  30

unsigned int funcSMA(unsigned int val)
{ static unsigned int fltrBuf[MAXNUMFLTRBUF];
  static unsigned int idx;
  static unsigned long sumBuf;
  sumBuf-=fltrBuf[idx];     //вычитаем из суммы значение самого старого элемента
  sumBuf+=val;              //прибавляем к сумме значение нового элемента
  fltrBuf[idx]=val;         //записываем в буфер значение нового элемента
  if (idx<(MAXNUMFLTRBUF-1))//сдвигаем индекс
    idx++;
  else
    idx=0;
  return(sumBuf/MAXNUMFLTRBUF);//высисляем среднее значение
}

При желании можно добавить команды управления фильтром. Например, команду очистки буфера или инициализация его определенным значением. Для того, чтобы увеличить начальную крутизну его переходной характеристики.
Код
#define MAXNUMFLTRBUF  30

unsigned int funcSMA(unsigned int cmd, unsigned int val)
{ static unsigned int fltrBuf[MAXNUMFLTRBUF];
  static unsigned int idx;
  static unsigned long sumBuf;
  if (cmd==0)                 //это случано не команда инициализации фильтра?
  { sumBuf-=fltrBuf[idx];     //нет, вычитаем старое значение
    sumBuf+=val;              //прибавляем к сумме значение нового элемента
    fltrBuf[idx]=val;         //записываем в буфер значение нового элемента
    if (idx<(MAXNUMFLTRBUF-1))//сдвигаем индекс
      idx++;
    else
      idx=0;
    return(sumBuf/MAXNUMFLTRBUF);//вычисляем среднее значение
  }
  else                        //да, инициализируем буфер фильтра новым значением
  { sumBuf=val*MAXNUMFLTRBUF;
    idx=MAXNUMFLTRBUF-1;
    while (idx!=0)
      fltrBuf[idx--]=val;
    return(val);
  }
}

Учитывая, что входные значения 12-и разрядные и сумма заведомо не превышает разрядности типа long, то при целочисленном вычислении среднего можно повысить точность, если перед делением сдвигать сумму до заполнения разрядности типа, а потом сдвигать обратно.
Код
return(((sumBuf<<8UL)/MAXNUMFLTRBUF)>>8UL);
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 31 2008, 16:48
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 31 2008, 01:04) *
Есть два способа решения этой проблемы. Либо на время вычислений в основном цикле запрещать прерывания от АЦП (либо останавливать его) - все равно АЦП не работает, когда вы считаете в прерывании.

А разве не тож на тож получится? 07.gif Та же самая потеря времени... Единственное, что таймер не будет пробрасывать свои прерывания и будет четко вести счетчик прерываний... но лишние 10-20мс до начала короткого импульса - вроде не проблема...
Цитата(rezident @ Aug 31 2008, 01:04) *
Либо использовать два циклических буфера. В то время пока вы обсчитываете результаты одного буфера, в другой буфер (по прерываниям АЦП) идет запись новых результатов изменений. В основном цикле вы только устанавливаете номер буфера и флаг сигнализирующий обработчику прерывания АЦП о смене номера буфера. В прерывании АЦП сначала анализируется состояние флага и при необходимости изменяется указатель на буфер, а запись новых значений происходит уже в другой буфер.

Ух. Жестко! Ладно, спасибо, попробую.
Цитата(rezident @ Aug 31 2008, 01:04) *
Значит у вас где-то ошибка в алгоритме. нужно синхронизировать обновления значений переменных координат так, чтобы не было разбега, как он у вас описан.

Нужно. Вопрос - как biggrin.gif
Цитата(rezident @ Aug 31 2008, 01:04) *
А вам приниципально усреднять уже готовые значения координат или можно усреднять непосредственно отсчеты АЦП?

Э-э... а я вроде именно отсчеты АЦП и усредняю... 05.gif так мне казалось... biggrin.gif
Цитата(rezident @ Aug 31 2008, 01:04) *
Для этого нужно лишь хранить отдельно текущее значение суммы элементов буфера. При поступлении нового значения в буфер достаточно вычесть из этой суммы значение самого древнего элемента буфера, прибавить значение нового элемента буфера и вуаля! - вы получаете готовую сумму.

Точно! Спасибо большое! Действительно, куча лишних действий получалась!
Только немного не ясно, почему строка
sumBuf-=fltrBuf[idx];- это вычитание самого старого элемента 05.gif Вы записываете новый элемент fltrBuf[idx]=val; и сдвигаете счетчик - idx++. Значит, при поступлении следующего элемента fltrBuf[idx] будет хранить значение предыдущего, а не самого старого... Поясните, пожалуйста.
Цитата(rezident @ Aug 31 2008, 01:04) *
Учитывая, что входные значения 12-и разрядные и сумма заведомо не превышает разрядности типа long, то при целочисленном вычислении среднего можно повысить точность, если перед делением сдвигать сумму до заполнения разрядности типа, а потом сдвигать обратно.
Код
return(((sumBuf<<8UL)/MAXNUMFLTRBUF)>>8UL);

А почему это повышает точность?
как всегда спасибо за комментарии! smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 31 2008, 18:39
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 31 2008, 22:48) *
Нужно. Вопрос - как biggrin.gif
Как обычно. С помощью буферов. Две переменные которые будут обновляться одновременно и считывание значений из которых не будет прерываться вычислениями.
Цитата(Daria @ Aug 31 2008, 22:48) *
Э-э... а я вроде именно отсчеты АЦП и усредняю... 05.gif так мне казалось... biggrin.gif
Опс! Это я ошибся sad.gif Извиняюсь! Почему-то отложилось в памяти, что у вас там фильтрация плавающих числе идет, а страницу с вашим кодом еще раз посмотреть поленился. twak.gif
Цитата(Daria @ Aug 31 2008, 22:48) *
Только немного не ясно, почему строка
sumBuf-=fltrBuf[idx];- это вычитание самого старого элемента 05.gif Вы записываете новый элемент fltrBuf[idx]=val; и сдвигаете счетчик - idx++. Значит, при поступлении следующего элемента fltrBuf[idx] будет хранить значение предыдущего, а не самого старого... Поясните, пожалуйста.
В полностью заполненном циклическом буфере фильтра индекс указывает на тот элемент, куда нужно записать новое значение, которое замещает самое старое значение. Следовательно индекс указывает на самое старое значение.
Пример. Буфер из трех элементов. Поток состоит из последовательности натуральных чисел.
Код
         | значения
значение | элементов
индекса  |  буфера
---------------------------
  0       -, -, -    - буфер пуст
  1       1, -, -    - 1 элемент, единственный и самый старый, индекс указывает на следующий, но буфер ЕЩЕ НЕ ЗАПОЛНЕН
  2       1, 2, -    - 2 элемента, самый старый 1-й, буфер ЕЩЕ НЕ ЗАПОЛНЕН, индекс указывает на следующий
  0       1, 2, 3    - 3 элемента, буфер заполнен!!!, индекс указывает на следующий (1-й элемент), который является самым старым
  1       4, 2, 3    - 3 элемента, буфер заполнен, индекс указывает на следующий (2-й элемент). который является самым старым
  2       4, 5, 3    - 3 элемента, буфер заполнен, индекс указывает на следующий (3-й элемент). который является самым старым
  0       4, 5, 6    - ну и т.д.
  1       7, 5, 6

Цитата(Daria @ Aug 31 2008, 22:48) *
А почему это повышает точность?
Это особенности целочисленной математики. Хотя пожалуй в данном конкретном случае (единственная операция в выражении) это рояли не играет. Я просто перестраховался. Отставить сдвиги! smile.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 31 2008, 20:29
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 31 2008, 22:39) *
В полностью заполненном циклическом буфере фильтра индекс указывает на тот элемент, куда нужно записать новое значение, которое замещает самое старое значение.

Ага, ясно. Спасибо за очень подробное разъяснение smile.gif
Цитата(rezident @ Aug 31 2008, 22:39) *
Это особенности целочисленной математики. Хотя пожалуй в данном конкретном случае (единственная операция в выражении) это рояли не играет. Я просто перестраховался. Отставить сдвиги! smile.gif

Есть "отставить сдвиги" smile.gif
Я теперь неделю буду в отпуске 08.gif так что можете от меня недельку отдохнуть biggrin.gif
а через неделю жду вас с новыми ответами на новые вопросы wink.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Sep 12 2008, 18:04
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Ну вот, отпуск кончился, пошли суровые будни crying.gif
И вопросы smile.gif
Такая беда. У меня был iar, версия 4.11в - тридцатидневная демо-версия с официального сайта. Срок лицензии истек, я снесла эту версию, скачала опять и поставила снова. И вот фиг. Удаляю отовсюду, откуда только можно, но в реестр он прописался в закрытую область, которую нельзя удалить. Теперь сколько новый iar не ставь, все бестолку crying.gif
Как быть? переустанавливать винду не хочется. Попробовать какую-нибудь другую версию? Где взять? У меня был ломаный iar 3.2, но он почему-то жутко глючил. Можно как-нибудь почистить и закрытые области?
Вот такая проблема, немного не по теме, но печальная crying.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 12 2008, 18:27
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Sep 13 2008, 00:04) *
Вот такая проблема, немного не по теме, но печальная crying.gif
Там все дело в волшебных пузырьках biggrin.gif То бишь в лицензии которую вы скармливаете при установке. "Правильную" лицензию можно сгенерить с помощью вот этой штучки wink.gif Инструкция по применению inside package.
P.S. некоторые излишне подозрительные антивирусы (например, AVAST) реагируют на содержимое архива как на вирус. Не стоит волноваться, они перестраховываются.
Go to the top of the page
 
+Quote Post
Daria
сообщение Sep 18 2008, 13:34
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Sep 12 2008, 22:27) *

rezident, большое спасибо. Все работает. Вы хороший smile.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Sep 23 2008, 18:33
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте. Такие вопросы -
сейчас я прошиваю контроллер самодельной отладкой, схему которой советовали, по-моему, вы, rezident - она питается с платы, 3,3 В. В дальнейшем хочу использовать MSP-FET430PIF, так как требования - либо на свою отладку оформлять докуметацию по всем правилам, либо пользоваться готовой. и вот вопрос - у MSP-FET430PIF питание от LPT - мне сказали, что это опасно, что LPT часто горят, если программатор питается прямо от порта. Это правда? насколько часто? smile.gif Может, лучше не покупать этот MSP-FET430PIF?
И еще - не совсем в по теме. Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров? И, желательно, планарный smile.gif Не могу найти, на такую частоту все какие-то здоровые, а нужно сокращать размеры платы sad.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 23 2008, 19:56
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Sep 24 2008, 00:33) *
В дальнейшем хочу использовать MSP-FET430PIF, так как требования - либо на свою отладку оформлять докуметацию по всем правилам, либо пользоваться готовой. и вот вопрос - у MSP-FET430PIF питание от LPT - мне сказали, что это опасно, что LPT часто горят, если программатор питается прямо от порта. Это правда? насколько часто? smile.gif Может, лучше не покупать этот MSP-FET430PIF?
Согласен. MSP-FET430PIF покупать не нужно в любом случае smile.gif. Если вам нужен индивидуальный отладчик и программатор, то купите лучше MSP-FET430UIF или его полнофункциональный клон MSPLink. Olimex-овский USB-FET покупать не рекомендую.
Если же вы хотите передать прошивку кристаллов на производство, то лучше сразу купить MSP-GANG430. Мы покупали в Терраэлектронике.
Преимущества:
- можно программировать до 8ми кристаллов одновременно.
- все кристаллы можно запитать непосредственно от MSP-GANG430.
- поддерживает функцию прожигания fuse.
- можно загрузить прошивку в программатор и использовать его автономно, т.е. он не требует обязательного наличия компьютера. С компьютера вы только загружаете образ прошивки и конфигурацию программирования через последовательный интерфейс RS-232. Соответственно при отсутствии в компе RS-232 можно дополнить программатор любым готовым кабелем USB-COM и работать дальше. В случае же LPT-ного MSP-FET430PIF и отсутствия LPT-порта вы получите массу трудностей.
- MSP-GANG430 поддерживает все предыдущие и последующие серии MSP430, т.е. у него есть перспективы техподдержки. Например, аналогичный по функциям MSP-PRGS430 уже сейчас не поддерживает интерфейс Spy-Bi-Wire и некоторые кристаллы из серии MSP430x2xx.
- чуть не забыл упомянуть главное достоинство MSP-GANG430 для производства, на котором не всегда адекватные по знаниям люди работают smile.gif У MSP-GANG430 из органов управления всего ОДНА кнопка! wink.gif Из индикации два ряда светодиодов (красные и зеленые). Обучить нажатию на кнопку можно даже неквалифицированный персонал. biggrin.gif
Кстати, раз вы планируете программировать кристаллы уже запаянные в плату, то обдумайте стоит ли для этого использовать именно JTAG? Я, например, в серийных устройствах на MSP430 вывожу для программирования сигналы BSL. Во-первых, требуется меньше контактов (всего 6). Во-вторых, BSL позволяет и в дальнейшем менять firmware, когда уже установлена защита (fuse уже пережжен) и JTAG не работает.
Цитата(Daria @ Sep 24 2008, 00:33) *
И еще - не совсем в по теме. Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров? И, желательно, планарный smile.gif Не могу найти, на такую частоту все какие-то здоровые, а нужно сокращать размеры платы sad.gif
Посмотрите резонаторы фирм Geyer Electronic и Golledge. Мы часовой (32768Гц) KX-327LT от Geyer недавно начали применять, размеры его всего 1,5х7мм. Продукцией Geyer Electronic торгует Компел и Терраэлектроника, а продукцию Golledge представляет фирма ЭФО.
Go to the top of the page
 
+Quote Post
Daria
сообщение Sep 23 2008, 20:12
Сообщение #31


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Ага, но мне, как пока неквалифицированному программисту, хотелось бы все же программить именно на плате, сразу непосредсственно смотреть сигналы с датчиков. Возможность BSL заложу, но с JTAG мне гораздо проще - удобно отлаживать все это дело, то так, то так попробовать smile.gif А с полноценным отладчиком не знаю, как и работать biggrin.gif такой парадокс. Пробовать ведь надо на реальной плате 05.gif а так - вставить кристалл и... чего дальше? biggrin.gif Мое парадоксальное мышление проявляется тут с новой силой biggrin.gif Когда прога будет уже окончательно выверена, тогда, конечно - вставил кристалл, прошил - давай следующий. Но окончательно - это еще неизвестно когда, к тому же задание постоянно меняется biggrin.gif
Значит PIF - не пойдет? A UIF - разве позволяет программировать прямо на плате?
Резонаторы посмотрю, спасибо

Сообщение отредактировал Daria - Sep 23 2008, 20:53
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 23 2008, 20:47
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Sep 24 2008, 02:12) *
Значит PIF - не пойдет? A UIF - это ведь тоже отдельная коробка smile.gif
Для вашего нынешнего случая (MSP430F149) подойдет и PIF и UIF. Я вам на будущее/перспективу рекомендации давал. Для отладки конечно же лучше нормальный отладчик. BSL это для серии и техподдержки.
Go to the top of the page
 
+Quote Post
Daria
сообщение Sep 23 2008, 20:56
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Sep 24 2008, 00:47) *
Для вашего нынешнего случая (MSP430F149) подойдет и PIF и UIF. Я вам на будущее/перспективу рекомендации давал. Для отладки конечно же лучше нормальный отладчик. BSL это для серии и техподдержки.

А UIF позволяет программировать прямо на плате? Как-то он так выглядит... я думала. что нет. по его внешнему виду biggrin.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 23 2008, 21:35
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Sep 24 2008, 02:56) *
А UIF позволяет программировать прямо на плате? Как-то он так выглядит... я думала. что нет. по его внешнему виду biggrin.gif
Конечно позволяет. Он функционально более расширен по сравнению с MSP-FET430PIF. В принципе вы даже сами можете изготовить MSP-FET430UIF wink.gif Схема его имеется в slau138, а прошивку тут в форуме где-то выкладывали.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Daria   MSP430 - снова вопросы от чайника   Jul 23 2008, 19:17
- - rezident   Некоторое (продолжительное) время не заглядывал в ...   Jul 23 2008, 22:03
|- - Daria   Ага, все же заглянули спасибо за комментарии и кр...   Jul 24 2008, 19:29
|- - =DS=   Цитата(Daria @ Jul 24 2008, 23:29) А по п...   Jul 25 2008, 03:03
|- - Daria   Цитата(=DS= @ Jul 25 2008, 07:03) *addr ...   Jul 25 2008, 18:27
|- - rezident   Цитата(Daria @ Jul 26 2008, 00:27) а к...   Jul 25 2008, 19:47
|- - Daria   И версии, и настройки. А кикстарт - потому что сн...   Jul 25 2008, 21:05
|- - rezident   Цитата(Daria @ Jul 26 2008, 03:05) И верс...   Jul 25 2008, 21:38
||- - Daria   Цитата(rezident @ Jul 26 2008, 01:38) Ну ...   Jul 26 2008, 12:38
||- - rezident   Цитата(Daria @ Jul 26 2008, 18:38) rezide...   Jul 26 2008, 12:58
||- - Daria   Так вот. Галочка стоит. А состояние переменных все...   Jul 28 2008, 20:14
||- - rezident   Цитата(Daria @ Jul 29 2008, 02:14) Так во...   Jul 28 2008, 23:05
||- - Daria   Цитата(rezident @ Jul 29 2008, 03:05) Ну ...   Jul 30 2008, 19:31
||- - Daria   Здравствуйте, снова я Цитата(rezident @ Jul...   Aug 7 2008, 20:43
||- - rezident   Цитата(Daria @ Aug 8 2008, 02:43) ЗКак бы...   Aug 8 2008, 01:29
||- - Daria   Цитата(rezident @ Aug 8 2008, 05:29) Можн...   Aug 8 2008, 20:28
||- - rezident   Цитата(Daria @ Aug 9 2008, 02:28) а вот п...   Aug 9 2008, 01:10
||- - Daria   Цитата(rezident @ Aug 9 2008, 05:10) Коли...   Aug 9 2008, 20:42
||- - rezident   Цитата(Daria @ Aug 10 2008, 02:42) Ну и п...   Aug 9 2008, 22:10
||- - Daria   Так. Ну вот, как-то не выходит ничего Если в пре...   Aug 11 2008, 20:19
||- - Dog Pawlowa   Цитата(Daria @ Aug 11 2008, 23:19) Как бы...   Aug 12 2008, 06:14
||- - Daria   Цитата(Dog Pawlowa @ Aug 12 2008, 10:14) ...   Aug 12 2008, 19:55
|- - =DS=   Цитата(Daria @ Jul 26 2008, 01:05) Дебагг...   Jul 25 2008, 21:40
- - Т.Достоевский   Может так? Код#pragma vector=ADC_VECTOR { if ...   Aug 11 2008, 21:52
- - rezident   Все дело в том, что вы маски неверно накладываете....   Aug 11 2008, 23:19
|- - rezident   Цитата(Daria @ Aug 13 2008, 23:06) Но - з...   Aug 13 2008, 18:19
||- - Daria   Цитата(rezident @ Aug 13 2008, 22:19) Яс...   Aug 13 2008, 19:59
|- - zhevak   О-хо-хо... Ну да ладно! Даша, я предполагаю, ...   Aug 17 2008, 14:49
|||- - Сергей Борщ   Цитата(Daria @ Sep 23 2008, 23:56) Как-то...   Sep 23 2008, 21:52
|||- - Daria   Цитата(Сергей Борщ @ Sep 24 2008, 01:52) ...   Sep 24 2008, 17:18
||- - Сергей Борщ   Цитата(Daria @ Sep 23 2008, 21:33) мне ск...   Sep 23 2008, 20:01
||- - LCD   Цитата(Daria @ Sep 23 2008, 22:33) Не под...   Sep 24 2008, 19:14
|- - MrYuran   Цитата(Daria @ Sep 12 2008, 22:04) Как бы...   Sep 13 2008, 10:53
|- - rezident   Цитата(MrYuran @ Sep 13 2008, 16:53) И с ...   Sep 13 2008, 16:48
|- - MrYuran   Цитата(rezident @ Sep 13 2008, 20:48) А в...   Sep 13 2008, 17:31
|- - Сергей Борщ   Цитата(rezident @ Sep 13 2008, 19:48) А в...   Sep 13 2008, 18:20
|- - rezident   Цитата(MrYuran @ Sep 13 2008, 23:31) А во...   Sep 13 2008, 20:13
|- - AHTOXA   Цитата(rezident @ Sep 14 2008, 02:13) При...   Sep 15 2008, 17:38
- - Kurt   2rezident: я восхищен силой вашего воображения ))   Aug 13 2008, 04:41
|- - _3m   Цитата(Kurt @ Aug 13 2008, 08:41) 2rezide...   Aug 13 2008, 06:34
- - rezident   Я не вижу функции инициализации UART, но попробуйт...   Sep 24 2008, 18:12
|- - Daria   Цитата(rezident @ Sep 24 2008, 22:12) Я н...   Sep 25 2008, 18:43
|- - rezident   Цитата(Daria @ Sep 26 2008, 00:43) Ну, те...   Sep 25 2008, 19:30
|- - Daria   Цитата(rezident @ Sep 25 2008, 23:30) Пок...   Sep 26 2008, 15:21
- - VAI   ЦитатаКварц, кстати, подходящий нашла у Murata - C...   Sep 25 2008, 06:57
- - rezident   Ну вот она и ошибка. Первой командой инициализации...   Sep 26 2008, 15:33
|- - Daria   Цитата(rezident @ Sep 26 2008, 19:33) Ну ...   Sep 29 2008, 19:16
|- - rezident   Цитата(Daria @ Sep 30 2008, 01:16) не-а, ...   Sep 29 2008, 20:23
|- - Daria   Цитата(rezident @ Sep 30 2008, 00:23) Дел...   Sep 30 2008, 19:00
|- - rezident   Цитата(Daria @ Oct 1 2008, 01:00) NData -...   Sep 30 2008, 19:49
|- - Daria   Кодtypedef struct CharBuffer { unsigned char* Dat...   Sep 30 2008, 20:26
|- - rezident   Цитата(Daria @ Oct 1 2008, 02:26) но так ...   Sep 30 2008, 23:05
|- - Daria   Цитата(rezident @ Oct 1 2008, 03:05) Поче...   Oct 1 2008, 18:23
|- - rezident   Цитата(Daria @ Oct 2 2008, 00:23) Да, но ...   Oct 1 2008, 19:34
|- - Daria   Цитата(rezident @ Oct 1 2008, 23:34) Если...   Oct 2 2008, 19:37
- - VAI   Кстати, по уартам, я как-то выкладывал свои исходн...   Oct 3 2008, 01:12
- - Daria   Цитата(VAI @ Oct 3 2008, 05:12) Кстати, п...   Oct 4 2008, 17:01
- - Daria   Опять я теперь нужен еще буфер - для АЦП. посмот...   Oct 5 2008, 15:42
- - Daria   И еще Мне нужно обмениваться с двумя устройствам...   Oct 5 2008, 19:35
- - Dog Pawlowa   Цитата(Daria @ Oct 5 2008, 22:35) И еще ...   Oct 6 2008, 06:04
- - Daria   Цитата(Dog Pawlowa @ Oct 6 2008, 10:04) О...   Oct 6 2008, 17:45
- - rezident   Цитата(Daria @ Oct 6 2008, 23:45) одно ус...   Oct 6 2008, 19:04
- - Daria   Цитата(rezident @ Oct 6 2008, 23:04) Личн...   Oct 7 2008, 17:09
- - rezident   Цитата(Daria @ Oct 7 2008, 23:09) Ага, а ...   Oct 7 2008, 17:41
- - Daria   Цитата(rezident @ Oct 7 2008, 21:41) В IA...   Oct 7 2008, 18:12
- - rezident   Цитата(Daria @ Oct 8 2008, 00:12) Все же ...   Oct 7 2008, 19:07
- - Daria   Цитата(rezident @ Oct 7 2008, 23:07) Либо...   Oct 10 2008, 20:23
3 страниц V   1 2 3 >


Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 19:13
Рейтинг@Mail.ru


Страница сгенерированна за 0.02323 секунд с 7
ELECTRONIX ©2004-2016