pl161187smi 0 1 июля, 2015 Опубликовано 1 июля, 2015 · Жалоба Доброго времени суток. Сразу приношу извинения за нубские вопросы. Но какую литературу я бы ни читал о ЦОС там высвечиваются только алгоритмы, методы анализа и расчета. Меня интересуют можно сказать таки детские вопросы, и так по порядку. 1. Я рассчитал FIR фильтр в Matlab и получил искомые коэффициенты, фильтр устойчив, порядок фильтра оптимальный. 2. Теперь я хочу применить его для обработки сигнала полученного из АЦП микроконтроллера STM32F103 то есть от 0 до 4096. 3. Для STM32 серии CortexM3 имеется библиотека DSP которая поставляется как отдельная библиотека от ST а так же есть в составе CMSIS например можно задействовать ее в Keil. Так как F103 не содержит DSP - инструкций, как я понимаю все алгоритмы выполняются на стандартной арифметике. 4. И вот тут у меня начинаются вопросы.... 5. Я хочу применить FIR фильтр из состава библиотеки. Но какой использовать? Если логически подумать, так как входные данные целочисленные то мне нужна функция arm_fir_fast_q15, но она ругается на коэффициенты. Так как они имеют вид: -0.0085006295830239147, -0.039315452455814658, 0.020190437531132147, 0.0076176048595180471, (взял первые парочку чтоб не копировать весь массив.) Если применять функцию arm_fir_f32 то коэффициенты ей подходят, но ведь данные мы имеем целочисленные и выход нужен целочисленный. 6. И еще один вопрос, в примере из CMSIS FIR фильтр реализован где в функцию arm_fir_f32 передается массив выборок равный 32. Можно ли пользоваться этими фильтрами передавая на вход всего одну выборку соответственно и получая один результат за итерацию чтобы не накапливать массив для постобработки. Может кто пользуется этими библиотеками, расскажите пожалуйста как правильно использовать, если не затруднит. За ранее благодарен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 1 июля, 2015 Опубликовано 1 июля, 2015 (изменено) · Жалоба /** * @brief Processing function for the floating-point FIR filter. * @param[in] *S points to an instance of the floating-point FIR structure. * @param[in] *pSrc points to the block of input data. * @param[out] *pDst points to the block of output data. * @param[in] blockSize number of samples to process. * @return none. */ void arm_fir_f32( const arm_fir_instance_f32 * S, float32_t * pSrc, float32_t * pDst, uint32_t blockSize); f32 означает тип данных. Количество передается в blockSize. Заглячнул в код CMSIS... когда увидел цикл, /* Copy numTaps number of values */ tapCnt = numTaps - 1u; /* Copy data */ while(tapCnt > 0u) { *pStateCurnt++ = *pState++; /* Decrement the loop counter */ tapCnt--; } Смотреть расхотелось навсегда... Фильтр для своей работы в любом случае требует массива значений - предшествующих текущему моменту. Вот такое использую в своих проектах: // Ограничение алгоритма генерации параметров фильтра - нечётное значение Ntap. // Кроме того, для функций фильтрации с использованием симметрии коэффициентов, требуется кратность 2 половины Ntap #define NtapValidate(n) ((unsigned) (n) / 4 * 4 + 1) #define NtapCoeffs(n) ((unsigned) (n) / 2 + 1) #define Ntap_rx_AUDIO NtapValidate(241) // single samples, floating-point implementation static FLOAT_T FIRCoef_rx_AUDIO [NPROF] [NtapCoeffs(Ntap_rx_AUDIO)] = { { 0 }, { 0 } }; static FLOAT_T FIRScale_rx_AUDIO [NPROF] = { 1, 1 }; static FLOAT_T filter_fir_rx_AUDIO(FLOAT_T NewSample) { const FLOAT_T * const k = FIRCoef_rx_AUDIO [gwprof]; enum { Ntap = Ntap_rx_AUDIO, NtapHalf = Ntap / 2 }; // буфер с сохраненными значениями сэмплов static FLOAT_T x [Ntap * 2] = { 0, }; static uint_fast16_t fir_head = 0; // shift the old samples fir_head = (fir_head == 0) ? (Ntap - 1) : (fir_head - 1); x [fir_head] = x [fir_head + Ntap] = NewSample; uint_fast16_t bh = fir_head + NtapHalf; // Начало обрабатываемой части буфера uint_fast16_t bt = bh; // Позиция за концом обрабатываемого буфера // Calculate the new output uint_fast16_t n = NtapHalf; // Выборка в середине буфера register FLOAT_T v = k [NtapHalf] * x [bh]; // sample at middle of buffer do { { const FLOAT_T kv = k [-- n]; v += kv * x [-- bh]; v += kv * x [++ bt]; } { const FLOAT_T kv = k [-- n]; v += kv * x [-- bh]; v += kv * x [++ bt]; } } while (n != 0); // Обеспечиваем масштабирование к ранее расчитанному усилению фильтра (1.0) return v * FIRScale_rx_AUDIO [gwprof]; } Перевести на целочисленный вариант легко. Придется накапливать в 64 битах (для q31), при использовании результата учесть разрядность рассчитанных коэффициентов ругается на коэффициенты. Так как они имеют вид: -0.0085006295830239147, -0.039315452455814658, 0.020190437531132147, 0.0076176048595180471 Множите перед использованием на 32768 (в случае Q15). Результат фильтрации делите на 32768 Библиотечная функция arm_fir_fast_q15 использует SIMD инструкции для работы с парами 16-ти битных чисел за одну операцию, данные для фильтрации можете располагать как в моей функции (массив двойной длинны, без необходимости копирования массива данных для сдвига). Изменено 1 июля, 2015 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pl161187smi 0 2 июля, 2015 Опубликовано 2 июля, 2015 · Жалоба Большое спасибо за разъяснение и за пример реализации фильтра. Фильтр для своей работы в любом случае требует массива значений - предшествующих текущему моменту. Да, я понимаю что для работы фильтра нужен массив предшествующих данных который равен порядку фильтра. Меня интересовал вопрос именно в передаче нового значения в фильтр за раз в виде одной выборки а не пакетно. Но как я вижу из Вашей реализации Вы тоже передаете одну последнюю выборку, значит вариант с кормлением фильтра одной новой выборкой и получением одного нового результата естественного с задержкой равной порядку фильтра за одну итерацию возможен. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться