Перейти к содержанию
    

ppram5

Участник
  • Постов

    32
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о ppram5

  • Звание
    Участник
    Участник

Информация

  • Город
    Array

Посетители профиля

Блок последних пользователей отключён и не показывается другим пользователям.

  1. В общем немного подразобрался и поэкспериментировал. Что касается времени преобразований: arm_rfft_fast_f32 (4096) идет за 7,7мс. arm_rfft_q31 - 10,2мс. Разница 2,5мс, float быстрее, хоть и не немного. Время приведения uint16_t к f32 перегоном в цикле 1,3мс. С коллегами произвели оценку необходимой точности - в q15 не влезаем. Напрямую грузить данные из апц через дма с левым сдвигом можно, но придется все равно сдвигать число на один бит вправо, т.к. первый бит знаковый. Все равно цикл прогонять. В итоге если сделать: фильтр+ФТТ+корреляция *10, думаю преимущество для float набежит на пару-тройку десятков миллисекунд.
  2. Как все напишу - обязательно поделюсь результатами и проведу сравнение.
  3. У fixed*32 24 мантисса бита и 8 бит под дробную часть и без знака, у float*32 - мантисса 23 и экспонента 8 и один под знак. И где выше Динамика? И во сколько раз? Как вы заметили, в ARM далеко не дураки придумали, конечно они умеют работать с фиксированной точкой, но зачем же тогда они слепили целый FPU и пихают их в недорогие ками? Вообще обо всем этом очень подробно тут: https://www.st.com/content/ccc/resource/technical/document/application_note/group0/c1/ee/18/7a/f9/45/45/3b/DM00273990/files/DM00273990.pdf/jcr:content/translations/en.DM00273990.pdf А вот тут сравнение размерности float и fixed. И о преимуществе применения FPU: http://microsin.net/programming/arm/stm32-floating-point-unit.html Дабы не копаться процитирую: Аппаратные вычисления FPU ускоряют алгоритм множества Жюлиа в 12.5 раз при использовании float, и в 7.2 раза при использовании double. Не требуется никакой модификации кода, FPU активируется опциями компилятора. Также FPU позволяет расширить диапазон точности. Таким образом, STM32 FPU реализует очень быстрые вычисления для чисел float и double, что очень важно для точных систем регулирования, обработки звука, декодирования звука или цифровой фильтрации. Интересная у нас дискуссия вышла, казалось бы из простого вопроса 🙂 Но еще раз повторюсь - float только при наличии FPU, иначе float станет злом, а fixed будет рулить. А лучше уж оставить uint если это возможно.
  4. А вот вопрос, fractional это fixed или float? В терминологии библиотеки CMSIS-DSP: fixed это Q31. Который кстати в библиотеке определен как typedef int32_t q31_t Можно и q31 обрабатывать, но на камне с FPU, это как то не правильно. f32 выигрывает, хоть и не так много. Скорость сильно зависит от того какие преобразования выполняются. Я все таки предполагал, что fractional - float, а не fixed. Хотя могу и ошибаться, я так глубоко не зарывался dsPIC. Ибо какой смысл крутить целочисленную арифметику на FPU, если она прекрасно работает и на основном процессоре. У Q31 (фиксированная точка) есть ряд недостатков, нужно быть очень аккуратным при выполнении мат операций ибо легко налететь на переполнение и неверный результат. О чем ST честно предупреждает. Более низкая точность чем во float. Данные с АЦП для Q31 тоже приводить нужно в STM32. Хотя надо попробовать левое выравнивание в настройках АЦП - по идее может прокатить. Вообще у ST есть очень толковое описание на предмет f32 и Q31, не помню, где лежит. Еще float удобен для отладочного вывода в порт с банальным printf(%f). Q31 на приемной стороне не поймут, как не понимает его и printf (ну разве что как целое).
  5. Fractional - дробь Integer - целое Есть ведь разница получить например 2354 или 0,458. В чем хранить 0,458? Вроде как логично, что в float?
  6. Общего назначения: PIC32MZ, может и другие умеют, не копался. https://static.chipdip.ru/lib/013/DOC004013135.pdf стр 446 REGISTER 28-1: ADCCON1: ADC CONTROL REGISTE bit 23 FRACT: Fractional Data Output Format bit 1 = Fractional 0 = Integer Специализированные: dsPIC33, но там вообще навернуто: FORM<2:0>: Data Output Format bits 011 = Signed Fractional 16-bit (DOUT = 0000 0000 0000 0000 sddd dddd dd00 0000) 010 = Fractional 16-bit (DOUT = 0000 0000 0000 0000 dddd dddd dd00 0000) 001 = Signed Integer 16-bit (DOUT = 0000 0000 0000 0000 ssss sssd dddd dddd) 000 = Integer 16-bit (DOUT = 0000 0000 0000 0000 0000 00dd dddd dddd) 111 = Signed Fractional 32-bit (DOUT = sddd dddd dd00 0000 0000 0000 0000) 110 = Fractional 32-bit (DOUT = dddd dddd dd00 0000 0000 0000 0000 0000) 101 = Signed Integer 32-bit (DOUT = ssss ssss ssss ssss ssss sssd dddd dddd) 100 = Integer 32-bit (DOUT = 0000 0000 0000 0000 0000 00dd dddd dddd) Данные выдает АЦП, и формат определяется настройками АЦП, а ДМА пересылает все что ей скормят не особо интересуясь что там, шишь бы размерность совпадала.
  7. arm_rfft_q15 - Пробовал, работает, чуть медленнее чем флоат.
  8. Видимо я как то неправильно задал вопрос: Есть АЦП, формат его выходных данных от 12 до 6 бит (можно настроить) и выравнивание по левому или правому краю. Как настроим так и будет. Есть ДМА - она "перекладывает" данные АЦП в соответствующий массив памяти. Причем делает это без участия центрального процессора (ядра) МК. Чтобы данные были положены в память некорректно типы данных должны совпадать и видимо в STM32 это может быть только uint. Собственно вопрос был в том, можно ли указать тип данных float и складировать в память уже в готовом к применению формате, как это сделано в более развитых МК. При этом не требуется ни выделение памяти, ни цикл, ни, соответственно, участие процессора. Теоретически можно переписать функцию чтобы она внутри себя делала этот перегон без буфера, но от цикла не избавиться и выполнять его все равно придется процессору. К тому же переписывать готовые библиотеки не очень правильно - теряется смысл применения библиотек.
  9. Функция требует входных данных в f32. void arm_rfft_fast_f32 ( const arm_rfft_fast_instance_f32 * S, float32_t * p, float32_t * pOut, uint8_t ifftFlag ) https://www.keil.com/pack/doc/CMSIS/DSP/html/group__RealFFT.html#ga5d2ec62f3e35575eba467d09ddcd98b5 Поскольку есть модуль FPU и библиотека под него заточена - все крутиться очень быстро, если память не изменяет, на 2048 уходило около 4мс - вполне устраивает, у меня не непрерывный поток. Да и другие функции ЦОС требуют f32. Если сунуть функции rFFT данные в uint - будет полная ересь, пробовал 🙂 Ну и компилятор орать начинает. Пробовал алгоритм rFFTс uint - без применения FPU (рукописный) - в несколько раз дольше выходит. Если сделать то жде самое без FPU (пробовал на 32F103) тоже реально долго выходит. Тоже долго ломал мозг - зачем вообще этот флоат - пока сам не попробовал.
  10. Чтобы потом делать FFT и прочие "нехорошие" вещи с сигналом 🙂 Пока это работает так: for (i=0; i<FFT_SAMPLES; i++) // По всем отсчетам { inputSignal[i]=(float32_t)adc[i]; } // Подготовливаем преобразование status = arm_rfft_fast_init_f32(&S, FFT_SAMPLES); // Выполняем релаьное преобразование arm_rfft_fast_f32(&S, inputSignal, outputSignal, 0); Библиотека SMSIS-DSP. Сейчас с фильтрацией перед FFT разбираюсь. Скользящее среднее - на ура, надо опробовать медианный фильтр и экспоненциальное бегущее среднее. Ну и продумать реализацию на FPU. В последней версии появилась возможность делать FFT над float16_t надо попробовать. ПС: А вот с алгоритмами анализа результатов ЦОС - пока не знаю даже куда копать... Кроме обучения нейросетей в голову ничего не приходит 😞
  11. Дабы не плодить темы, спрошу здесь: STM32F401. Работает АЦП + DMA, результат складывается в uint16_t, размером 4096 отсчетов, потом с помощью цикла перегонять все это в float32_t. Приходиться выделять память под еще один буфер и время на выполнение. Можно ли сделать так, чтобы результат от АЦП сразу получался в Float32_t, а лучше в fliat16_t? Подобные вещи можно например делать в dsPIC и некоторых PIC32, а в STM32?
  12. Быстро - вся операция по дерганью выходит примерно как 4 клока по времени, но можно конечно попробовать и лишний байт зарядить - посмотреть как МС отреагирует.
  13. Количество частот в общем случае не более 100 или 200. Именно чтобы не зависеть от разброса каждого экземляра МС и от внешней температуры (уличная эксплуатация) я и возился с таким методом. К тому же планирую добавить таймер, проверяющий наличие генерации - если сорвалась - перекалибровка.
  14. В итоге - победил. Причина действительно оказалась в реализации чтения. А конкретно в этой фразе из dataseet: "Finally, send 1 period of the clock." В общем, нужно дать один дополнительный тактовый импульс на CLK пред чтением данных. Поскольку SPI аппаратный - отключаю вывод от модуля SPI, передергиваю его и возвращаю на место. К тому же нужно сдвинуть полученные данные на два бита влево. Все заработало как нужно. Сначала выясняю какой VCO выбран в автомате для каждой частоты, а затем шишу их с ручным выбором. Рабочий код - вдруг кому то пригодиться... uint32_t SPI_ReadDWord() // Функция чтения { uint32_t spi_data=0; // Считанное значение uint8_t spi_packet[4]={0}; // Байтовый массив uint8_t i=0; LE_LAT=0; // Запись байта в SPI SPI1_ExchangeByte(0x00); // Запись байта в SPI SPI1_ExchangeByte(0x00); // Запись байта в SPI SPI1_ExchangeByte(0x00); // Запись байта в SPI SPI1_ExchangeByte(0x06); // Запись байта в SPI LE_LAT=1; // Запись с адресом R6 RB2PPS = 0x00; //RB2->LAT; RB2_SetHigh(); // Один тактовый импульс RB2_SetLow(); RB2PPS = 0x0D; //RB2->MSSP1:SCK1; for ( i = 0; i < 4; i++) { spi_packet[i] = SPI1_ExchangeByte(0x00); // Чтение } for ( i = 0; i < 4; i++) { spi_data |= spi_packet[i]; if ( i != 3) spi_data = spi_data << 8; } spi_data=spi_data<<2; // Сдвиг на два бита return spi_data; }
  15. Продолжил изыскания... Все-таки, что то не так с чтением. Пробовал разные вариации на тему чтения по примеру разных исходных кодов найденных в сети - результата нет. Зато обнаружил, что при изменении скорости SPI читаются разные данные (при 1МГц и 4МГц - одно значение, а при 16МГц - другое). А вот запись во всех случаях идет корректно и МС встает на нужную частоту. Что еще странно - после окончания калибровки и просто записи - на выходе SPI от MAX2871 продолжают идти данные, хотя команды на чтения не давал. В общем буду искать лог. анализатор, без него никак.
×
×
  • Создать...