Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SED1335,PIC18F4550 и LCD320x240
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9
andreichk
добавил ptr=Buf;
теперь ничего не затирает, но и не рисует кривую.
andreichk
блин, инструкции перепутали 05.gif и ptr надо было локальной сделать. теперь работает
Цитата
//####################################################################
//--------------- собственно кривая ---------------------------
void curve_A(unsigned int8 y_pos_A)
{ unsigned char *ptr=Buf;
unsigned int8 x, yy;
x=2;
while(x++){
#asm
BCF 0x0F8B,2//LATC2=0;
#endasm
*ptr++=input_b(); //чтение порта В
#asm
BSF 0x0F8B,2//LATC2=1;
#endasm
}
for(x=1;x<255;x++){
yy = adcA;//y
adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
adcA = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
if (yy>adcA) front(x,yy,adcA); // Рисуем фронт A
if (yy<adcA) spad(x,yy,adcA); // Рисуем спад A
pixel(x,adcA,1); // Рисуем вершину A
}
}
//#########################################


только вот не замечаю разницы(пока), но работает beer.gif
Ilya_A
Да, конечно, засунуть бы ваш компилятор.... куда подальше wink.gif

Я полагаю, что если перекинуть while в конец, можно еще немного сэкономить:

Код
//--------------- собственно кривая ---------------------------
void curve_A(unsigned int8 y_pos_A)
{ unsigned char *ptr=Buf;
unsigned int8 x, yy;
x=2;
do{
#asm
BCF 0x0F8B,2//LATC2=0;
#endasm
*ptr++=input_b(); //чтение порта В
#asm
BSF 0x0F8B,2//LATC2=1;
#endasm
}while(x++);
for(x=1;x<255;x++){
yy = adcA;//y
adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
adcA = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
if (yy>adcA) front(x,yy,adcA); // Рисуем фронт A
if (yy<adcA) spad(x,yy,adcA); // Рисуем спад A
pixel(x,adcA,1); // Рисуем вершину A
}
}


Приведите дизассемблер как исправите, ОК?

Вообще руки чешуться исправить весь цикл чтения на асм.... да вот хрен его знает как в это CCS получать адреса Сишных переменных...
Цитата
только вот не замечаю разницы(пока), но работает

Особой разницы вы и не заметите... т.к. принципиально не правильно выбраны размеры буферов...

кстати, вы ПЛИСку во время работы тормознуть можете?
andreichk
Цитата
.................... //####################################################################
.................... //--------------- собственно кривая ---------------------------
.................... void curve_A(unsigned int8 y_pos_A)
.................... { unsigned char *ptr=Buf;
*
26F0: MOVLB 1
26F2: CLRF x6D
26F4: MOVLW 55
26F6: MOVWF x6C
.................... unsigned int8 x=2, yy;
26F8: MOVLW 02
26FA: MOVWF x6E
.................... do{
.................... #asm
.................... BCF 0x0F8B,2//LATC2=0;//PIN_C2. разрешить
26FC: BCF F8B.2
.................... #endasm
.................... *ptr++=input_b(); //чтение порта В
26FE: MOVFF 16D,03
2702: MOVF x6C,W
2704: INCF x6C,F
2706: BTFSC FD8.2
2708: INCF x6D,F
270A: MOVWF FE9
270C: MOVFF 03,FEA
2710: MOVLW FF
2712: MOVWF F93
2714: MOVFF F81,FEF
.................... #asm
.................... BSF 0x0F8B,2//LATC2=1;//PIN_C2.запретить
2718: BSF F8B.2
.................... #endasm
.................... }while(x++);
271A: MOVF x6E,W
271C: INCF x6E,F
271E: XORLW 00
2720: BNZ 26FC
.................... for(x=1;x<255;x++){
2722: MOVLW 01
2724: MOVWF x6E
2726: INCFSZ x6E,W
2728: BRA 272C
272A: BRA 27B8
.................... yy = adcA;//y
272C: MOVFF 154,16F
.................... adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
2730: MOVLW 01
2732: SUBWF x6E,W
2734: CLRF 03
2736: ADDLW 55
2738: MOVWF FE9
273A: MOVLW 00
273C: ADDWFC 03,W
273E: MOVWF FEA
2740: MOVF FEF,W
2742: SUBLW C8
2744: BC 274A
2746: MOVLW C8
2748: BRA 275C
274A: MOVLW 01
274C: SUBWF x6E,W
274E: CLRF 03
2750: ADDLW 55
2752: MOVWF FE9
2754: MOVLW 00
2756: ADDWFC 03,W
2758: MOVWF FEA
275A: MOVF FEF,W
275C: MOVWF x54
.................... adcA = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
275E: MOVLW FF
2760: BSF FD8.0
2762: SUBFWB x54,W
2764: ADDWF x6B,W
2766: MOVWF x54
.................... if (yy>adcA) front(x,yy,adcA); // Рисуем фронт A
2768: MOVF x6F,W
276A: SUBWF x54,W
276C: BC 2782
276E: MOVFF 16E,170
2772: MOVFF 16F,171
2776: MOVFF 154,172
277A: MOVLB 0
277C: CALL 1DF8
2780: MOVLB 1
.................... if (yy<adcA) spad(x,yy,adcA); // Рисуем спад A
2782: MOVF x54,W
2784: SUBWF x6F,W
2786: BC 279C
2788: MOVFF 16E,170
278C: MOVFF 16F,171
2790: MOVFF 154,172
2794: MOVLB 0
2796: CALL 1E24
279A: MOVLB 1
.................... pixel(x,adcA,1); // Рисуем вершину A
279C: CLRF x8C
279E: MOVFF 16E,18B
27A2: CLRF x8E
27A4: MOVFF 154,18D
27A8: MOVLW 01
27AA: MOVWF x8F
27AC: MOVLB 0
27AE: CALL 0BAA
.................... }
27B2: MOVLB 1
27B4: INCF x6E,F
27B6: BRA 2726
.................... }
27B8: MOVLB 0
27BA: RETLW 00
.................... //#########################################

ПЛИСКУ я тормознуть могу, но тогда и ПИК остановится, та как клок на него через неё идёт.А зачем её тормозить?

Цитата
принципиально не правильно выбраны размеры буферов...

это вы про ФИФО ? а какие тогда правильные.Я могу на IDT7205 8кб купить и поставить,других не нашёл
Ilya_A
Цитата(andreichk @ Apr 1 2008, 22:33) *
это вы про ФИФО ? а какие тогда правильные.


Понимаете, ситуация у вас следующая: Допустим тактируете вы запись FIFO 80 МГц.
Вы заходите в процедуру pix_A(), ресетите буфер. Далее начианете искать фронт синхронизации. Частота считывания данных процом из FIFO, будет при этом порядка 100 кГц. Одновременно он заполняется данными на скорости 80 Мгц. Т.е. в 400 раз быстрее. Т.е. реально вы успеете считать 2 отсчета, и ФИФО буфер заткнется. (т.к. в нем стоит защита от переполнения). Далее вы считываете третий отсчет. И так как появилась свободная ячейка, ФИФО принимает еще один байт с АЦП. Затем, такая же ситуация с четвертым и последующими отсчетами. Т.е. картина следующая: первые, примерно 512 отсчетов заполняются на скорости 80 Мгц. все последующие заполняются на частоте вашего считывания.
Все хорошо, и вашего FIFO буффера достаточно, если порог синхронизации был найден в примерно в первых 256-ти отсчетах, т.к. после этого вы отрисовываете еще 253 отсчета (которые еще были оцифрованны на 80 Мгц). Но, чем дальше вы уходите при поиске фронта за первые 256 отсчетов, тем больше косячится конец буфера (т.к. все последующие отсчеты были занесены в буфер с частотой вашего считывания). Т.е. теоретически, если вы нашли фронт синхронизации за пределами первых 512 ти отсчетов, то вы как раз и отрисуете частокол, т.к. получиться эффект aliasing-а про который вы упоминали.(потому что вы с низкой частотой, выхватываете отсчеты из высокочастотного сигнала, а т.к. частоты не кратные, получается практически случайная картина).

Исходя из всего вышесказанного, можно сделать вывод, что ваш осцилл. будет работать "на ура", если будет находить фронты синхронизации, в первых 256 байтах ФИФО буфера. И как только, по каким либо причинам, он выходит за этот предел, начинаеться "каша".

Такчто, первое что нужно сделать - это исправить вашу программу - если нет фронта синхронизации в первых 256 ти байтах, то ресетить ФИФО, и искать заново. А по прошествии, допустим 10 попыток, если не нашелся фронт синхронизации, тупо отрисовывать оставшуюся часть буфера. Т.е. никогда не вылазить за первые 512 байт, т.к. там все равно информация собранная на другой частоте, а следовательно неправильная и отображению не подлежит!

Во вторых можно увеличить размер ФИФО буферов.

А вообще я бы посоветовал, взять ПЛИСку подороже, с внутренней памятью, и запрограммировать ее, чтобы она сама, напрямую загребала данные с АЦП, и на автомате искала фронты синхронизации. А процу доставался бы лишь готовый, синхронизированный массивчик для отображения на экране. ИМХО нефиг загружать проц такой работой, ибо MIPSов на это у него явно не достаточно wink.gif (Заодно сэкономите на буферах - они я смотрю не дешевые) wink.gif


Измененная процедура pix_A() будеу выглядеть вот так:
Код
#define TIMEOUT             10
#define MAXN                  258

void pix_A(unsigned int8 y_pos_A) // рисуем кривую, типа синусоиды и пр.
{  unsigned int16 n;
    unsigned int8  try=TIMEOUT;
   while(try--){
      n=0;
      Output_bit(PLCD_FIFO_RES ,0); //PIN_C0// сброс FIFO в "0"
      Output_bit(PLCD_FIFO_RES ,1); //PIN_C0// и разрешение на считывание
      Output_bit(READ_FIFO_B ,1); //PIN_C1 запрет канала B
      // слабая попытка синхронизации
      do{ Output_bit(READ_FIFO_A ,0);//PIN_C2
         adcA=input_b();
         Output_bit(READ_FIFO_A ,1);//PIN_C2
         if (n++>MAXN) break;// В этой попытке смотреть дальше неимеет смысла
      }while( adcA == 0);
      if (n>MAXN) contiune;// Начнем с начала
      do{ // ещё одна попытка синхронизации
         Output_bit(READ_FIFO_A ,0);//PIN_C2
         adcA=input_b();
         Output_bit(READ_FIFO_A ,1); //PIN_C2
         if (n++>MAXN) break;// В этой попытке смотреть дальше неимеет смысла
      }while(input_b()== adcA ); //уже лучше,но всё равно плохо
      if (n>MAXN) contiune;// Начнем с начала
      //-------------------- синхронизация ---------------------------
      while(1){
         Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
         adcA=input_b(); //чтение порта В
         Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
         adcA = (adcA > 200) ? 200 : adcA; //ограничитель до выбранной величины
         adcA = 255 - adcA; // разворот на 180° по вертикали
         if (n++>MAXN) break;// В этой попытке смотреть дальше неимеет смысла
         if (syncA){
            if(adcA>sync_volume_A) continue;
            else break;
         }else{
            if(adcA<=sync_volume_A+115) continue;
            else break;
         }
       }
       if (n>MAXN) contiune;// Начнем с начала
       else break;//Иначе выйдем из цикла и отрисуем кривую
   }
   curve_A(y_pos_A); // Сюда попадем только если нашли фронт синхронизации, либо исткло количество попыток
}

TIMEOUT - количество попыток синхронизации
MAXN - максимальное значение до которого ищем порог синхронизации.

Измененная процедура curve_A() будеу выглядеть вот так:
Код
//--------------- собственно кривая ---------------------------
void curve_A(unsigned int8 y_pos_A){
   unsigned int8 x, y , yy;
   for(x=1;x<255;x++){
      yy = y;
      Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
      adcA=input_b(); //чтение порта В
      Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
      adcA = (adcA > 200) ? 200 : adcA; //ограничитель до выбранной величины
      y = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
      if (yy>y) front(x,yy,y); // Рисуем фронт A
      if (yy<y) spad(x,yy,y); // Рисуем спад A
      pixel(x,y,1); // Рисуем вершину A
   }
}

Я убрал массив, т.к. он не имеет смысла. Торопиться здесь некуда. Данные лежат в ФИФО буфере и никуда не денуться пока мы их не считаем. Хотя, если одновременно еще строить спектр то можно завести глобальный массив, и заполнить его в этой процедуре.
andreichk
Блин, я в шоке!!! Да это просто супер как она сейчас рисует.На всех пределах показывает нормальную кривую.
По поводу замены мат.части- наверное этого не произойдёт,так как наверняка это сопряжено с переделкой подложки, на такое я пойтить не могу, как как не вижу особого смысла в дальнейших затратах.Проект-то ведь любительский.Единственное, что я себе позволю, так это замену ФИФО на более ёмкую, посмотрим, что это изменит.
Илье очередной a14.gif и beer.gif
ЗЫ. отдельное tort.gif за прояснение работы ФИФО.
Ilya_A
Цитата(andreichk @ Apr 2 2008, 19:01) *
Единственное, что я себе позволю, так это замену ФИФО на более ёмкую, посмотрим, что это изменит.
Илье очередной a14.gif и beer.gif
ЗЫ. отдельное tort.gif за прояснение работы ФИФО.


Желаю дальнейших творческих "узбеков" wink.gif
andreichk
вопрос(детский,но всё же).Что лучше , создать общую процедуру рисования для обоих каналов, или две раздельные?

Не поверите, прямо сейчас позвонили в дверь и принесли только вчера заказанные ФИФО 8кб.
теперь они уже в работе, однако пока не наблюдаю никаких изменений

наверное будет ваще супер, если на экран одновременно с кривыми ещё и значение частоты выводить
Ilya_A
Цитата(andreichk @ Apr 2 2008, 20:39) *
вопрос(детский,но всё же).Что лучше , создать общую процедуру рисования для обоих каналов, или две раздельные?


Я бы зделал четыре варианта:
1. Раздельная синхронизация и отрисовка по каждому каналу (как сейчас работает у вас)
2. Синхронизация по каналу А
3. Синхронизация по каналу B
4. Сделать на пике вход внешней синхронизации

Цитата
Не поверите, прямо сейчас позвонили в дверь и принесли только вчера заказанные ФИФО 8кб.
теперь они уже в работе, однако пока не наблюдаю никаких изменений


А программу то под них переписали? smile.gif

Цитата
наверное будет ваще супер, если на экран одновременно с кривыми ещё и значение частоты выводить

Да, конечно. а в чем проблема? wink.gif
andreichk
на пока синхронизация у меня раздельная на каждый канал.
Цитата
А программу то под них переписали?

а что ещё , кроме последних изменений надо переписать?
Цитата
Да, конечно. а в чем проблема?

не знаю, за что зацепиться.Понимаю, что нужно како-нибудь таймер задействовать......... help.gif
с выводом значений на экран проблем нет, а вот с остальным...... help.gif

Цитата
4. Сделать на пике вход внешней синхронизации

тут надо подуматьо том, надо ли оно?
Ilya_A
Цитата(andreichk @ Apr 2 2008, 22:55) *
а что ещё , кроме последних изменений надо переписать?

Конечно!
Во первых, сдесь, как я считаю становиться не нужным таймаут, хотя можно оставить, сделав, допустим равным 1:

#define TIMEOUT 1

а во вторых нужно изменить MAXN:

#define MAXN 7940

Цитата(andreichk @ Apr 2 2008, 22:55) *
не знаю, за что зацепиться.Понимаю, что нужно како-нибудь таймер задействовать......... help.gif

Таймер здесь вам ничем не поможет. У вас же все гораздо проще: значения за вас уже оцифрованны и лежат в буфере. Поэтому нужно в процедуру отрисовки добавить поиск номера N который второй раз удовлетворит условию синхронизации. Как только вы его найдете, вы получите:
N - количество отсчетов, характеризующих период сигнала
F - частота дискретизации
следовательно частота сигнала равна: F/N
т.е. если на 80ти мегагерцах, N состаило 100 отсчетов, следовательно частота сигнала будет равна 800 кГц wink.gif

Цитата
тут надо подуматьо том, надо ли оно?

Для сигналов, которые не получается засинхронизировать програмно - в полне надо. Тем более реализуется легко. Заходите в цикл отрисовки, ждете перепада на цифровом входе синхронизации, резетите FIFO и тут же отрисовываете smile.gif
andreichk
Цитата
Поэтому нужно в процедуру отрисовки добавить поиск номера N который второй раз удовлетворит условию синхронизации.

тут как мне кажется не всё так просто, так как этот момент наступает только после отрисовки всего экрана, то есть значение N будет всегда ок.255.А если на экран рисуется несколько периодов, то это значение становится неверным.Или я что-то не так понимаю? 05.gif
andreichk
попробовал таким макаром находить точку N для сравнения со значением oldA или oldB из процедуры
но ничего хорошего из этого не вышло.В общем ,значение переменной N хоть и изменяет своё значение от частоты , но оно скачет как мячик, а если ещё 80МГц на него делить, то тут вообще чума полная.
Сдаётся мне, что у меня опять косяк help.gif
Цитата
//--------------- собственно кривая ---------------------------
void curve(unsigned int8 y_pos)
{ unsigned int8 x, y , yy, oldA,oldB ;
//запоминаем первое значение точки синхронизации
if(kanal){//выбор канала А
#asm
BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить
#endasm
oldA=input_b(); //чтение порта В
#asm
BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить
#endasm
}else
{//выбор канала В
#asm
BCF 0x0F8B,1 //Output_bit(READ_FIFO_B ,0); //PIN_C1. разрешить
#endasm
oldB=input_b(); //чтение порта В
#asm
BSF 0x0F8B,1 //Output_bit(READ_FIFO_B ,1); //PIN_C1.запретить
#endasm
}
//.....................................................................
for(x=1;x<255;x++){
yy = y;
if(kanal){//выбор канала А
#asm
BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить
#endasm
y=input_b(); //чтение порта В
#asm
BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить
#endasm
}else
{//выбор канала В
#asm
BCF 0x0F8B,1 //Output_bit(READ_FIFO_B ,0); //PIN_C1. разрешить
#endasm
y=input_b(); //чтение порта В
#asm
BSF 0x0F8B,1 //Output_bit(READ_FIFO_B ,1); //PIN_C1.запретить
#endasm
}
//******************************************************************************
if(syncA){if(y>oldA) NA++;}//считаем до тех пор, пока не найдём равенство по фронту
else{if(oldA>y) NA++;}//считаем до тех пор, пока не найдём равенство по спаду
if(syncB){if(y>oldB) NB++;}//считаем до тех пор, пока не найдём равенство по фронту
else{if(oldB>y) NB++;}//считаем до тех пор, пока не найдём равенство по спаду
//******************************************************************************

y = (y > 200) ? 200 : y;// ограничитель до выбранной величины
y = (255 - y) + y_pos; // разворот на 180° по вертикали и сдвиг
if (yy>y) front(x,yy,y);// Рисуем фронт
if (yy<y) spad(x,yy,y); // Рисуем спад
pixel(x,y,1); // Рисуем вершину
}adcB=adcA=y;
}//--------------------------OK
//####################################################################
Ilya_A
Цитата(andreichk @ Apr 4 2008, 02:46) *
Сдаётся мне, что у меня опять косяк help.gif

Да, вы че-то конкретно намудрили... Вашу мысь я недогнал...

Для начала:

Код смотриться отвратно, сделайте, наконец макрос:
Код
#define ReadADC(var,chnl){ \
  if(chnl){//выбор канала А \
    #asm\
        BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить  \
    #endasm    \
    var=input_b(); //чтение порта В       \
    #asm                 \
        BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить   \
     #endasm        \
   }else{//выбор канала В    \
    #asm             \
        BCF 0x0F8B,1 //Output_bit(READ_FIFO_B ,0); //PIN_C1. разрешить \
    #endasm    \
        var=input_b(); //чтение порта В          \
    #asm          \
        BSF 0x0F8B,1 //Output_bit(READ_FIFO_B ,1); //PIN_C1.запретить       \
    #endasm    \
  }             \
}


Вызывать очень просто: var - переменная в которую считать, chnl - с какого канала.

Теперь о расчете частоты:
Код
float Fa,Fb; //Найденные частоты отрисовываемого сигнала
float FclockA,FclockB; //Частоты тактирования FIFO

//--------------- собственно кривая ---------------------------
void curve(unsigned int16 n,unsigned int8 y_pos){
   unsigned int8 x=1, y , yy=y_pos,syncF=0;
   unsigned int16 N=0; //Зануляем значение периода
   while(1){
      if (n++>8192){// Если дошли до сюда, значит не удалось найти период
          if (kanal) Fa=0; else Fb=0; // Занулим частоту (типа не посчитали... )
          return;
      }
      ReadADC(y,kanal); //Считываем значение в "у" с канала A или B
      y = (y > 200) ? 200 : y;// ограничитель до выбранной величины
      y = (255 - y); // разворот на 180° по вертикали
      if (kanal){// для канала А
         if(syncF==0) { // Первый этап
               N++;
               if (syncA){
                     if(y>sync_volume_A) syncF=1;
               }else{
                     if(y<sync_volume_A+115) syncF=1;
               }
         }else if(syncF==1){// Второй этап
              N++;
              if (syncA){
                     if(y<sync_volume_A) syncF=2;
              }else{
                     if(y>sync_volume_A+115) syncF=2;
              }
         }else{// Успешно нашли период
             if(x==255) {  // Если закончили отрисовку
                Fa=FclockA/N; // посчитаем частоту
               return;
             }
         }
      } else{// для канала B
         if(syncF==0) { // Первый этап
               N++;
               if (syncB){
                     if(y>sync_volume_B) syncF=1;
               }else{
                     if(y<sync_volume_B+115) syncF=1;
               }
         }else if(syncF==1){// Второй этап
              N++;
              if (syncB){
                     if(y<sync_volume_B) syncF=2;
              }else{
                     if(y>sync_volume_B+115) syncF=2;
              }
         }else{// Успешно нашли период
             if(x==255) {  // Если закончили отрисовку
                Fb=FclockB/N; // посчитаем частоту
               return;
             }
         }
      }
      if(x<255){//Рисуем, пока не вышли за пределы экрана
         y+= y_pos; //сдвигаем для отображения
         if (yy>y) front(x,yy,y); // Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1); // Рисуем вершину
         x++;
         yy=y;
      }
   }
}

Теперь функции нужно еще передать значение n, на котором остановилась процедура pix() чтобы процедура поиска N не вышла за границы правильных данных в FIFO буфере.
andreichk
Ок, не важно, что как смотрится,но после небольшого причёсывания всё заработало


Цитата
//##### выводим на экран числа в графическом режиме ##################
void frequenz(unsigned int8 wert,unsigned int8 x,unsigned int8 y)
{//Выводим на экран значение переменной с плавающей запятой
char freq[9];
switch(Fclock){
case 1: sprintf(freq, "%f",(float)( 80.0/wert ));break; //преобразуем в текст
case 2: sprintf(freq, "%f",(float)( 40.0/wert ));break;
case 3: sprintf(freq, "%f",(float)( 20.0/wert ));break;
case 4: sprintf(freq, "%f",(float)( 10.0/wert ));break;
case 5: sprintf(freq, "%f",(float)( 5.0/wert ));break;
case 6: sprintf(freq, "%f",(float)( 2.5/wert ));break;
case 7: sprintf(freq, "%f",(float)( 1.25/wert ));break;
case 8: sprintf(freq, "%f",(float)( 0.625/wert ));break;
}
freq[4] = '\0'; //ограничиваем тремя знаками
rect(x, y, x+25, y+7, 1,0); //стираем старое значение
text57(x, y, freq, 1, 1); //выводим новое значение
}//--------------------------OK
//##########################################################


макрос не переварился, поэтому его содержимое перекочевало обратно в процедуру
Цитата
//####################################################################
//--------------- собственно кривая ---------------------------
void curve(unsigned int16 n,unsigned int8 y_pos){
unsigned int8 x=1, y , yy,syncF=0;
unsigned int8 Nn=0; //Зануляем значение периода
for(;;){
if (n++>8192){// Если дошли до сюда, значит не удалось найти период
Nn=0; return;// Занулим частоту (типа не посчитали... )
}
#asm
BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить
#endasm
y=input_b(); //чтение порта В
#asm
BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить
#endasm
y = (y > 200) ? 200 : y;// ограничитель до выбранной величины
y = (255 - y); // разворот на 180° по вертикали
if(syncF==0) { // Первый этап
Nn++;
if (syncA){
if(y>sync_volume_A) syncF=1;
}else{
if(y<sync_volume_A+115) syncF=1;
}
}else if(syncF==1){// Второй этап
Nn++;
if (syncA){
if(y<sync_volume_A) syncF=2;
}else{
if(y>sync_volume_A+115) syncF=2;
}
}
else{// Успешно нашли период
if(x==255)
{//Если закончили отрисовку,посчитаем частоту
frequenz(Nn,195, 230);Nn=0;return;
}
}
//........................................................
if(x<255){//Рисуем, пока не вышли за пределы экрана
y+= y_pos; //сдвигаем для отображения
if (yy>y) front(x,yy,y); // Рисуем фронт
if (yy<y) spad(x,yy,y); // Рисуем спад
pixel(x,y,1); // Рисуем вершину
x++;
yy=y;
}
}
}//--------------------------OK
//#########################################################

a14.gif a14.gif a14.gif

ЗЫ.правда правильные показания только при условии чёткой синхронизации
andreichk
фото на память beer.gif
andreichk
вопрос имею, зачем тут else со скобками ? Я попробовал его убрать и ничего не изменилось 05.gif
Цитата
else{// Успешно нашли период
if(x==255)
{//Если закончили отрисовку,посчитаем частоту
frequenz(Nn,195, 230);Nn=0;return;
}
Ilya_A
Цитата(andreichk @ Apr 5 2008, 15:25) *
вопрос имею, зачем тут else со скобками ? Я попробовал его убрать и ничего не изменилось 05.gif

else{// Успешно нашли период
if(x==255)
{//Если закончили отрисовку,посчитаем частоту
frequenz(Nn,195, 230);Nn=0;return;
}


А как же? Видите что стоит return ? Следовательно если частота была подсчитана до того как был отрисован экран (x<255) то выходить из процедуры не стоит. А нужно дождться когда x станет равын 255, посчитть частоту и выйти wink.gif


Цитата
правда правильные показания только при условии чёткой синхронизации

А что вы хотели при таком примитвном алгоритме? wink.gif Для боле-менее стабильного алгоритма нужно гораздо больше заморачиваться, подключать цифровую обработку сигнала...

Цитата
макрос не переварился

Не нравиться мне ваш компилер.... wacko.gif
andreichk
ну дык из цикла мы не выходим, он же другими скобками ограничен.А вот else как то непонятно зачем, если и без него неплохо.
Компилятор мне тоже не нравится(вру, нравится), но другого нет
Ilya_A
Цитата(andreichk @ Apr 5 2008, 18:12) *
ну дык из цикла мы не выходим, он же другими скобками ограничен.А вот else как то непонятно зачем, если и без него неплохо.

Выложите как выглядит процедура без него
andreichk
Код
//--------------- собственно кривая A ---------------------------
void curve_A(unsigned int16 n,unsigned int8 y_pos){
   unsigned int8 x=1 , y , yy , syncF=0, Nn=0;//Зануляем значение периода
   for(ever){
      if (n++>8192){// Если дошли до сюда, значит не удалось найти период
      Nn=0;return;// Занулим частоту (типа не посчитали... )
      }
     #asm
       BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить
     #endasm
        y=input_b(); //чтение порта В
     #asm
       BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить
     #endasm
      y = (y > 200) ? 200 : y;// ограничитель до выбранной величины
      y = (255 - y); // разворот на 180° по вертикали
         if(syncF==0) { // Первый этап
               Nn++;
               if (syncA){
                     if(y>sync_volume_A) syncF=1;
               }else{
                     if(y<sync_volume_A+115) syncF=1;
               }
         }else if(syncF==1){// Второй этап
              Nn++;
              if (syncA){
                     if(y<sync_volume_A) syncF=2;
              }else{
                     if(y>sync_volume_A+115) syncF=2;
              }
         }
   if(x==255){// Успешно нашли период
              //Если закончили отрисовку,посчитаем частоту
              frequenz(FclockA/Nn,194, 230);Nn=0;return;
             }  
//........................................................
      if(x<255){//Рисуем, пока не вышли за пределы экрана
         y+= y_pos; //сдвигаем для отображения
         if (yy>y) front(x,yy,y); // Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1); // Рисуем вершину
         x++;
         yy=y;
      }
   }
}//--------------------------OK
//#################################################
Ilya_A
Ваш подход неправильный. Вы проверяете X и даже не проверяете, посчиталась ли на днный момент частота. Т.е. если частота еще не успела посчитаться (сигнал развернут так, что период длиннее экрана) То на экран выведеться ошибочная частота, равная периоду экрана а не сигнала.


Если же вы всетаки хотите отдельный if то придется сделать так:
Код
   if((x==255)&&(syncF==2)){// Успешно нашли период
              //Если закончили отрисовку,посчитаем частоту
              frequenz(FclockA/Nn,194, 230);Nn=0;return;
   }


wink.gif
andreichk
Ок,исправил как велел сенсей maniac.gif twak.gif
Ilya_A
Цитата(andreichk @ Apr 5 2008, 18:52) *
Ок,исправил как велел сенсей maniac.gif twak.gif

lol.gif
andreichk
Откопал тут ещё кусок кода.Скажите, это тоже Фурье-преобразование? CCS его переварил.
Код
#define SWAP( a , B ) tempr=( a);( a)=( B );( B )=tempr

four2(double data[] , int nn, int isign )
{
int n,mmax,m,j,istep,i;
double wtemp,wr,wpr,wpi,wi,theta;
double tempr,tempi;
double  p2;p2=8*atan(1);
n=nn << 1;
j=0;
for (i=0;i<n;i+=2) {
if (j > i) {
SWAP(data[j],data[i]);
SWAP(data[j+1],data[i+1]);
}
m=n >> 1;
while (m >= 2 && j >= m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax=2;
while (n > mmax) {
istep=2*mmax;
theta=-p2/(isign*mmax);
wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;
for (m=0;m<mmax;m+=2) {
for (i=m;i<n;i+=istep) {
j=i+mmax;
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i] += tempr;
data[i+1] += tempi;
}
wr=(wtemp=wr)*wpr-wi*wpi+wr;
wi=wi*wpr+wtemp*wpi+wi;
}
mmax=istep;
}
}

#undef SWAP
Ilya_A
Цитата(andreichk @ Apr 8 2008, 05:42) *
Откопал тут ещё кусок кода.Скажите, это тоже Фурье-преобразование? CCS его переварил.


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

(наверное все double в процедуре следует исправить на float)
andreichk
буфер сделал и он влез(даже ещё 30% RАМ осталось).
теперь что с ним делать?
И ещё вопрос имею, что это и как им пользоваться?
Код
#define SWAP( a , B ) tempr=( a);( a)=( B );( B )=tempr
Ilya_A
Цитата(andreichk @ Apr 8 2008, 15:13) *
буфер сделал и он влез(даже ещё 30% RАМ осталось).
теперь что с ним делать?

Перед преобразованием в него нужно занести 256 значений из FIFO буффера.

Цитата
И ещё вопрос имею, что это и как им пользоваться?
Код
#define SWAP( a , B ) tempr=( a);( a)=( B );( B )=tempr

Да это просто макрос. Который меняет местами 2 элемента. Сделан чисто для лучшей читаемости кода
andreichk
ну вот таким макаром слепил, вроде рисует какие-то палки, но они беспорядочные.Наверное тоже надо синхронизацию втыкать

Код
void spectrum_analizator(unsigned int8 y_pos)
{unsigned int8 x=0,y,yy;
  setCursorAddress(0x2581);
  clear_graphic();delay_ms(100);

#asm
    BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0"
    BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание
    BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B
#endasm
for(x=0;x<255;x++){
    #asm
       BCF 0x0F8B,2//LATC2=0;
    #endasm
      Buf[x]=input_b(); //чтение порта В
    #asm
      BSF 0x0F8B,2//LATC2=1;
    #endasm
}
for(x=0;x<255;x++){
      Buf_FFT[x]=SWAP(Buf[x]);//
}
for(x=0;x<255;x++){
         yy=y;
         y = Buf_FFT[x];//
         y = (y > 200) ? 200 : y; //ограничитель до выбранной величины
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
        
                }    
}
Ilya_A
Цитата(andreichk @ Apr 8 2008, 15:42) *
ну вот таким макаром слепил, вроде рисует какие-то палки, но они беспорядочные.Наверное тоже надо синхронизацию втыкать

Непонял, это вообще что такое вы написали????
Заместо этого:
Код
Buf_FFT[x]=SWAP(Buf[x]);//
Надо
Код
Buf_FFT[x]=Buf[x];


А где само преобразование фурье-то?

П.С. Для стабильности показаний, конечно же лучше буффер тоже синхронизировать
andreichk
Цитата
Buf_FFT[x]=SWAP(Buf[x]);//

А где само преобразование фурье-то?

вообще я думал, что это оно и есть 07.gif
Ilya_A
Цитата(andreichk @ Apr 8 2008, 16:03) *
вообще я думал, что это оно и есть 07.gif

Вот же оно:

four2(double data[] , int nn, int isign )

Вы сами же его и привели wacko.gif
andreichk
и куды его втыкать? wacko.gif
я точно свихнусь с этим аппаратом 07.gif
Ilya_A
Цитата(andreichk @ Apr 8 2008, 16:17) *
и куды его втыкать? wacko.gif
я точно свихнусь с этим аппаратом 07.gif

После того, как заполните массив Buf_FFT[]
вызываете функцию:
four2(Buf_FFT,512,1)

Извиняюсь, надо так:
Код
four2(Buf_FFT,128,1)


Потом надо будет еще кое чего подшаманить чтобы получить настоящий спектр... я помоему как -то ссылку уже давал....
andreichk
сделал так, только он теперь рисует точно такую же картинку как просто осциллограф.

Код
for(x=0;x<255;x++){
    #asm
       BCF 0x0F8B,2//LATC2=0;
    #endasm
      Buf[x]=255 - input_b(); //чтение порта В
    #asm
      BSF 0x0F8B,2//LATC2=1;
    #endasm
}
for(x=0;x<255;x++){
      Buf_FFT[x]=Buf[x];//
      
}
four2(Buf_FFT[x],512,1);
for(x=0;x<255;x++){
         yy=y;
         y = Buf_FFT[x] + y_pos;//
         y = (y > 200) ? 200 : y; //ограничитель до выбранной величины
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
        
                }    
}
Ilya_A
Во первых уберите [x] при вызове функции
а во вторых, я уже исправил предыдущий пост, нужно сделать так:
Код
four2(Buf_FFT,128,1)
andreichk
всё исправил, но всё равно рисует просто кривую
Ilya_A
Цитата(andreichk @ Apr 8 2008, 17:00) *
всё исправил, но всё равно рисует просто кривую

еще раз посмотрел на вашу функцию four2(),
во первых это опять функция для комплексного преобразования фурье, вам нужно преобразование для реальных чисел (гдето раньше вы уже выкладывали нужную процедуру)

Хотя... лучше возьмите вот эту:
Код
void realFFT(float a[], unsigned int tnn, char inversefft)
{
    float twr,twi,twpr,twpi,twtemp,ttheta;
    int i,i1,i2,i3,i4;
    float c1, c2, h1r, h1i, h2r,h2i,wrs, wis;
    int nn,ii, jj,n, mmax, m,j,istep,isign;
    float wtemp, wr,wpr, wpi, wi,theta,tempr,tempi;
    if( tnn==1 )return;
    if( !inversefft ){
        ttheta = 6.28318530717959/tnn;
        c1 = 0.5;
        c2 = -0.5;
    }else{
        ttheta = 6.28318530717959/tnn;
        c1 = 0.5;
        c2 = 0.5;
        ttheta = -ttheta;
        twpr = -2.0*(sin(0.5*ttheta))*(sin(0.5*ttheta));
        twpi = sin(ttheta);
        twr = 1.0+twpr;
        twi = twpi;
        for(i = 2; i <= tnn/4+1; i++){
            i1 = i+i-2;
            i2 = i1+1;
            i3 = tnn+1-i2;
            i4 = i3+1;
            wrs = twr;
            wis = twi;
            h1r = c1*(a[i1]+a[i3]);
            h1i = c1*(a[i2]-a[i4]);
            h2r = -c2*(a[i2]+a[i4]);
            h2i = c2*(a[i1]-a[i3]);
            a[i1] = h1r+wrs*h2r-wis*h2i;
            a[i2] = h1i+wrs*h2i+wis*h2r;
            a[i3] = h1r-wrs*h2r+wis*h2i;
            a[i4] = -h1i+wrs*h2i+wis*h2r;
            twtemp = twr;
            twr = twr*twpr-twi*twpi+twr;
            twi = twi*twpr+twtemp*twpi+twi;
        }
        h1r = a[0];
        a[0] = c1*(h1r+a[1]);
        a[1] = c1*(h1r-a[1]);
    }
    if( inversefft ) isign = -1;
    else isign = 1;
    n = tnn;
    nn = tnn/2;
    j = 1;
    for(ii = 1; ii <= nn; ii++)
    {
        i = 2*ii-1;
        if( j>i )
        {
            tempr = a[j-1];
            tempi = a[j];
            a[j-1] = a[i-1];
            a[j] = a[i];
            a[i-1] = tempr;
            a[i] = tempi;
        }
        m = n/2;
        while(m>=2&&j>m)
        {
            j = j-m;
            m = m/2;
        }
        j = j+m;
    }
    mmax = 2;
    while(n>mmax)
    {
        istep = 2*mmax;
        theta = 6.28318530717959/(isign*mmax);
        wpr = -2.0*(sin(0.5*theta))*(sin(0.5*theta));
        wpi = sin(theta);
        wr = 1.0;
        wi = 0.0;
        for(ii = 1; ii <= mmax/2; ii++)
        {
            m = 2*ii-1;
            for(jj = 0; jj <= (n-m)/istep; jj++)
            {
                i = m+jj*istep;
                j = i+mmax;
                tempr = wr*a[j-1]-wi*a[j];
                tempi = wr*a[j]+wi*a[j-1];
                a[j-1] = a[i-1]-tempr;
                a[j] = a[i]-tempi;
                a[i-1] = a[i-1]+tempr;
                a[i] = a[i]+tempi;
            }
            wtemp = wr;
            wr = wr*wpr-wi*wpi+wr;
            wi = wi*wpr+wtemp*wpi+wi;
        }
        mmax = istep;
    }
    if( inversefft )
    {
        for(i = 1; i <= 2*nn; i++)
        {
            a[i-1] = a[i-1]/nn;
        }
    }
    if( !inversefft )
    {
        twpr = -2.0*(sin(0.5*ttheta))*(sin(0.5*theta));
        twpi = sin(ttheta);
        twr = 1.0+twpr;
        twi = twpi;
        for(i = 2; i <= tnn/4+1; i++)
        {
            i1 = i+i-2;
            i2 = i1+1;
            i3 = tnn+1-i2;
            i4 = i3+1;
            wrs = twr;
            wis = twi;
            h1r = c1*(a[i1]+a[i3]);
            h1i = c1*(a[i2]-a[i4]);
            h2r = -c2*(a[i2]+a[i4]);
            h2i = c2*(a[i1]-a[i3]);
            a[i1] = h1r+wrs*h2r-wis*h2i;
            a[i2] = h1i+wrs*h2i+wis*h2r;
            a[i3] = h1r-wrs*h2r+wis*h2i;
            a[i4] = -h1i+wrs*h2i+wis*h2r;
            twtemp = twr;
            twr = twr*twpr-twi*twpi+twr;
            twi = twi*twpr+twtemp*twpi+twi;
        }
        h1r = a[0];
        a[0] = h1r+a[1];
        a[1] = h1r-a[1];
    }
}

вызывайте ее так:
Код
realFFT(Buf_FFT, 256, 0);


а после вызова сделайте такой цикл:
Код
for(i=0;i<256;i+=2){
    Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
}
Buf_FFT[0]=0;


Затем распечатайте на экран первые 128 значений буффера

Только перед распечаткой нужно еще пронормировать на максимальное значение (чтобы было равно высоте экрана)

Да, еще старайтесь чтобы на экран умещалось побольше периодов сигнала, чтобы лучше увидеть пик



Кстати, почитайте, очень похожий проект:
http://rf.atnn.ru/s10/digital_osc.html

там и про FFT че-то написано, даже есть исходник в низу страницы.
andreichk
экран замирает и ничего не происходит 07.gif
Код
void spectrum_analizator(unsigned int8 y_pos)
{unsigned int8 x=0,y,yy,k=0,i=0;unsigned int16 n=0;
//-----------------------------------------------------------------------------        
      if (n++>8192){// Если дошли до сюда, значит не удалось найти период
      return;// Занулим частоту (типа не посчитали... )
      }  
//-----------------------------------------------------------------------------
for(x=0;x<255;x++){
    #asm
       BCF 0x0F8B,2//LATC2=0;
    #endasm
      Buf[x]=255 - input_b(); //чтение порта В
    #asm
      BSF 0x0F8B,2//LATC2=1;
    #endasm
}
for(x=0;x<255;x++){
      Buf_FFT[x]=Buf[x];//
      
}
realFFT(Buf_FFT, 256, 0);

for(i=0;i<256;i+=2){
    Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
}
Buf_FFT[0]=0;

for(x=0;x<128;x++){
         yy=y;
         y = Buf_FFT[x] + y_pos;//
         y = (y > 200) ? 200 : y; //ограничитель до выбранной величины
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
        
               }
  setCursorAddress(0x2581);
  clear_graphic();
}
//#########################################


закрыл это- опять стала рисовать просто импульсы
Код
//for(i=0;i<256;i+=2){
//    Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
//}


изменил размерность переменной i на unsigned int16- на экране появились импульсы в два раза уже , чем обычные и прим. на одну треть выше
Ilya_A
Что-то вы шаманством каким-то занимаетесь... sad.gif

Не вижу у вас нормировки сигнала....

Давайте сделаем так:
Код
signed int16 Buf_FFT[512]; // переобъявим массив как int

void spectrum_analizator(void)
{
    unsigned int8 x=0,y,yy;
    unsigned int16 i=0,max=0,k=0;

    setCursorAddress(0x2581); //Я так понимаю чистить экран нужно перед отрисовкой а не после...
    clear_graphic();

    #asm
        BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0"
        BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание
        BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B
    #endasm

    for(i=0;i<512;i++){
        #asm
               BCF 0x0F8B,2//LATC2=0;
        #endasm
          Buf_FFT[i]=input_b(); //чтение порта В
        #asm
              BSF 0x0F8B,2//LATC2=1;
        #endasm
    }
    realFFT(Buf_FFT, 512, 0);
    for(i=0;i<512;i+=2){
        Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
    }
    Buf_FFT[0]=0;
    for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i];    // ищем max
    for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max);  //нормировка по max, и инвертирование перед распечаткой
    for(x=1;x<254;x++){
         yy=y;
         y = Buf_FFT[x];
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
    }
}

а процедуру realFFT переобъявим следующим образом:
Код
void realFFT(signed int16 a[], unsigned int tnn, char inversefft)
andreichk
по-прежнему просто узкие , но очень большие по аплитуде импульсы. Они теперь даже не влезают в экран.
зы.я не шаман,теперь я как все зелёный человечек.
Ilya_A
Цитата(andreichk @ Apr 8 2008, 20:55) *
по-прежнему просто узкие , но очень большие по аплитуде импульсы. Они теперь даже не влезают в экран.
зы.я не шаман,теперь я как все зелёный человечек.



Хачу видеть 2 картинки - исходного сигнала и его спектра. Не меняя частоту тактирования FIFO.

Сделайте так чтобы на экран при этом входило периодов 8 примерно
andreichk
выставил сейчас прямоугольники 400кГц, развёртка на 3.2мксек.амплитуда прим. 3 вольта
одно могу сказать пока, они в два раза Уже и по аплитуде скачут то вверх, то вниз.Рисуются медленней и плохо синхронизируются как в режиме спектра, так и в осциллографическом.

вот и фотки
1 скоп
2 спектр

хачу таааак crying.gif
Ilya_A
Цитата(andreichk @ Apr 8 2008, 22:17) *
выставил сейчас прямоугольники 400кГц, развёртка на 3.2мксек.амплитуда прим. 3 вольта
одно могу сказать пока, они в два раза Уже и по аплитуде скачут то вверх, то вниз.Рисуются медленней и плохо синхронизируются как в режиме спектра, так и в осциллографическом.

вот и фотки
1 скоп
2 спектр

хачу таааак crying.gif


Да это у вас совсем не спектр... sad.gif

Приведите в итоге весь цикл как вы получаете и отрисовываете спектр.

Не понял что значит рисуется медленней? У вас чтоли одновременно и спектр и сигнал рисуется, или я че-то не догоняю....
andreichk
вызываем процедуру
void spectr_A(unsigned int8 y_pos_A)

Код
void spectr_A(unsigned int8 y_pos_A) // пытаемся нарисовать спектр
{  unsigned int16 n=0,amplitude;
#asm
    BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0"
    BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание
    BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B
#endasm
//-------------------- синхронизация ---------------------------
for(ever){
  #asm
       BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить
  #endasm
      amplitude=input_b(); //чтение порта В
  #asm
       BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить
  #endasm
         amplitude = (amplitude > 200) ? 200 : amplitude; //ограничитель до выбранной величины
         amplitude = 255 - amplitude; // разворот на 180° по вертикали
        if (n++>MAXN) break;// В этой попытке смотреть дальше не имеет смысла
         if (syncA){//синхронизация по фронту A
            if(amplitude>sync_volume_A) continue;
            else break;
         }else{//синхронизация по спаду A
            if(amplitude<=sync_volume_A+115) continue;
            else break;
         }
      }  spectrum_analizator(y_pos_A,n);//Сюда попадем только если нашли фронт синхронизации
}//--------------------------OK
//####################################################################
void spectrum_analizator(unsigned int8 y_pos,unsigned int16 n)
{
    unsigned int8 x=0,y,yy;
    unsigned int16 i=0,max=0,k=0;
//-----------------------------------------------------------------------------        
      if (n++>8192){// Если дошли до сюда, значит не удалось найти период
      return;// Занулим частоту (типа не посчитали... )
      }  
//-----------------------------------------------------------------------------


    #asm
        BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0"
        BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание
        BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B
    #endasm

    for(i=0;i<512;i++){
        #asm
               BCF 0x0F8B,2//LATC2=0;
        #endasm
          Buf_FFT[i]=input_b(); //чтение порта В
        #asm
              BSF 0x0F8B,2//LATC2=1;
        #endasm
    }
    realFFT(Buf_FFT, 512, 0);
    for(i=0;i<512;i+=2){
        Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
    }
    Buf_FFT[0]=0;
    for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i];  //ищем max
    for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max);//нормировка по max, и инвертирование перед распечаткой
    for(x=1;x<254;x++){
         yy=y;
         y = Buf_FFT[x];
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
    }
    setCursorAddress(0x2581); // чистить экран
    clear_graphic();
}


ну насчёт медленнее рисует-это я наверное погорячился.просто чем больше развёртка, тем медленнее рисует. или чем больше элементов для рисования, тем больше времени на это требуется.

#define EVER ;; //приколы нашего двора
Ilya_A
Так, на вид, почти все нормально. Но давайте для на чала отладим сам алгоритм FFT.

Для этого сделаем тестовую процедуру, и заполним массив известным меандром:
(я специально взял такой период (28 отсчетов) чтобы в 512 отсчетов не укладывалось ровное число периодов, иначе картинка будет слишком красивая, и далекая от реальности)
Код
void testspectr(void)
{
    unsigned int8 x=0,y,yy;
    unsigned int16 i=0,max=0,k=0;

    setCursorAddress(0x2581); // чистить экран
    clear_graphic();

     for(i=0;i<512;i++){
      if (k<14) {Buf_FFT[i]=10;k++;}
      else if(k<28) {Buf_FFT[i]=230;k++;}
      else {Buf_FFT[i]=10;k=1;}
    }

    realFFT(Buf_FFT, 512, 0);
    for(i=0;i<512;i+=2){
        Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5);
    }
    Buf_FFT[0]=Buf_FFT[1];
    for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i];  //ищем max
    for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max);//нормировка по max, и инвертирование перед распечаткой
    for(x=1;x<254;x++){
         yy=y;
         y = Buf_FFT[x];
         if (yy>y) front(x,yy,y);// Рисуем фронт  
         if (yy<y) spad(x,yy,y); // Рисуем спад  
         pixel(x,y,1);           // Рисуем вершину
    }
}


Я специально не поленился, и написал программку для Borland. Все один в один.
Получились следующие картинки:

СИГНАЛ:
Нажмите для просмотра прикрепленного файла
СПЕКТР:
Нажмите для просмотра прикрепленного файла

P.S. Хочу посмотреть что получиться у вас wink.gif
Ilya_A
Цитата(andreichk @ Apr 9 2008, 14:39) *
фотки пока нет.
график представляет из себя следующее, слева-направо с отступом от лев.края в 10 пикселей длинная закрашенная палка на весь экран толщиной в 4 пикселя,далее 17 прямоугольников при по 8 пикселей шапка 8 пикселей яма . Всё это рисуется от самого низа экрана


Что-то по описанию явно бред какой-то..... wacko.gif приведите еще раз ф-ию realFFT();

Просто, не понятно в чем косяк - процедурка то ведь рабочая. Я же проверил...
andreichk
первое фото было получено при обозначении процедуры
void realFFT(char *a, unsigned int tnn, char inversefft)
а второе при
void realFFT(signed int16 a[] , unsigned int tnn, char inversefft)
в обоих случаях это мало похоже на ожидаемый результат

при более детальном рассмотрении второго графика я замечаю интересный момент- мне кажется что первые 4 или 5 всплесков отрисовались в области первых 16ти пикселей, начиная от левого края, но почему-то каждый последующий начинался не с низу, а от какого-то другого значения.Остальной меандр- это просто мусор какой-то
andreichk
я тут подумал и мы решили, а вообще в каком диапазоне частот работает наш спектроскоп?
И ещё вопрос- как эта функция передаёт значения в буфер?
void realFFT(signed int16 a[] , unsigned int tnn, char inversefft)
Ilya_A
Да... такое ощущение что у вас вообще буфер не обрабатывается....

Цитата(andreichk @ Apr 10 2008, 07:44) *
первое фото было получено при обозначении процедуры
void realFFT(char *a, unsigned int tnn, char inversefft)

Так точно не правильно, лучше попробывать так:
void realFFT(int *a, unsigned int tnn, char inversefft)

еще в функции realFFT() есть цикл:
while(m>=2&&j>m)
попробуйте заменить на:
while((m>=2)&&(j>m))

также в процедуре есть float переменные tempr и tempi. сделайте их int:
int tempr,tempi;

Цитата(andreichk @ Apr 10 2008, 07:44) *
я тут подумал и мы решили, а вообще в каком диапазоне частот работает наш спектроскоп?

Диапазон зависит от текущей частоты оцифровки (F) следующим образом:
от 0 до F/2

промежуточные частоты равны: i*F/512, где 1<i<N/2

Цитата(andreichk @ Apr 10 2008, 07:44) *
И ещё вопрос- как эта функция передаёт значения в буфер?
void realFFT(signed int16 a[] , unsigned int tnn, char inversefft)

Мы же ей передаем указатель на начало буфера. она присваивает его a. А дальше тупо обращается по индексам...

А вообще грешить помоему уже надо на компилятор.... все-таки приведите текст вашей realFFT() может че-то в ней случайно изменилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.