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

 
 
17 страниц V  « < 2 3 4 5 6 > »   
Reply to this topicStart new topic
> MSP430 - снова вопросы от чайника, Вопросы от чайника про MSP и магнитный компас
rezident
сообщение Aug 21 2008, 21:19
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #47


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #48


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #50


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #52


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #54


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #55


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 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
MrYuran
сообщение Sep 13 2008, 10:53
Сообщение #57


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Daria @ Sep 12 2008, 22:04) *
Как быть? переустанавливать винду не хочется. Попробовать какую-нибудь другую версию? Где взять?

Может, лучче сразу GCC осваивать?
Потом не придётся отвыкать от специфических ИАРовских примочек.. И с законностью всё в порядке


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
rezident
сообщение Sep 13 2008, 16:48
Сообщение #58


Гуру
******

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



Цитата(MrYuran @ Sep 13 2008, 16:53) *
И с законностью всё в порядке
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 13 2008, 17:31
Сообщение #59


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(rezident @ Sep 13 2008, 20:48) *
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif

Заказчику мы обычно передаём только паспорт и РЭ, в крайнем случае схему.
А вообще, как говорил кот Матроскин, холодильник чей - государственный, а холод, который он вырабатывает - наш.

Так же и тут.
Компилятор - GPL, а код, который он вырабатывает - наш.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 13 2008, 18:20
Сообщение #60


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(rezident @ Sep 13 2008, 19:48) *
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif
Насколько я понимаю, лицензия GPL предписывает предоставлять по первому требованию исходники самого компилятора, но не код, им произведенный. Иначе ее можно было бы распространить и на траффик, зашифрованный с помощью OpenSSH и подобных продуктов.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

17 страниц V  « < 2 3 4 5 6 > » 
Reply to this topicStart new topic
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0

 


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


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