|
DSP на STM32F4 |
|
|
|
Aug 25 2016, 07:59
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Здравствуйте! Помогите разобраться с DSP на STM32F429. Никогда раньше этой темой не занимался, не понимаю в какую сторону начинать копать. Задача такая: мне нужно генерировать белый шум, фильтровать его разными фильтрами и выдавать на аудио ЦАП (48 кГц). Фильтры нужны режекторный второго порядка и полосовой, четвертого порядка, с БИХ. Фильтры я посчитал в матлабе, приготовился уже реализовывать в целочисленной арифметике. Но в этом процессоре есть блок вычислений с плавающей точкой. Я с этим никогда дела не имел. В референс мануале описание этого блока не нашел. Есть некая библиотека CMSIS DSP, в которой реализованы фильтры, но я так понял она мне не подойдет, поскольку там какая то странная структура реализованного IIR фильтра и работает он с какими то блоками данных. А мне надо просто сгенерировать Х, посчитать Y, запомнить Х-1 и Y-1 для следующего отчета. Скажите, какое преимущество мне даст работа с float и вообще, могу ли я так просто, без всяких библиотек взять и расписать свои фильтры во float?
|
|
|
|
|
Aug 25 2016, 08:24
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Atlantis- @ Aug 25 2016, 10:59)  Скажите, какое преимущество мне даст работа с float и вообще, Сам Матлаб может дать вам характеристики фильтра с учетом квантования. Целочисленная порой сильно уступает ПТ даже одинарной точности. Цитата(Atlantis- @ Aug 25 2016, 10:59)  могу ли я так просто, без всяких библиотек взять и расписать свои фильтры во float? Я вообще написал фильтр на asm CODE //--------------------------------------------- // fpu_iir //--------------------------------------------- .thumb .thumb_func .global fpu_iir .type fpu_iir, %function fpu_iir: .cfi_startproc cbnz r1, fpu_iir_load bx lr fpu_iir_load: push {r0-r4, lr} VPUSH {s0-s7} // load f VLDR.F32 s1, [r3, #0] // G VLDR.F32 s2, [r3, #4] // a1 VLDR.F32 s3, [r3, #8] // a2 VLDR.F32 s4, [r3, #12] // b VLDR.F32 s5, [r3, #16] // tn-1 VLDR.F32 s6, [r3, #20] // tn-2 fpu_iir_loop: // load ldr r4, [r0], #4 // s0 <- x VMOV.F32 s0, r4 // calc tn VMUL.F32 s7, s1, s0 // G * x VFMS.F32 s7, s2, s5 // -a1 * tn-1 VFMS.F32 s7, s3, s6 // -a2 * tn-2 // calc y VADD.F32 s0, s7, s6 // tn-2 VFMA.F32 s0, s4, s5 // b * tn-1 // save t VMOV.F32 s6, s5 // tn-2 VMOV.F32 s5, s7 // tn-1 // y -> r0 VMOV.F32 r4, s0 // store str r4, [r2], #4 subs r1, #1 bne fpu_iir_loop VSTR.F32 s5, [r3, #16] // tn-1 VSTR.F32 s6, [r3, #20] // tn-2 VPOP {s0-s7} pop {r0-r4, pc} .size fpu_iir, .-fpu_iir .cfi_endproc
|
|
|
|
|
Aug 25 2016, 08:45
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(adnega @ Aug 25 2016, 11:24)  Я вообще написал фильтр на asm На asm то понятно, компилятор никуда не денется. А на Си если писать, для операций с float надо что-то настраивать, подключать? Или просто задать коэффициенты float a,b; float x,y; и пошел их перемножать, складывать, вычитать, а компилятор сам подставит нужные команды, для работы с плавающей точкой? Под компилятором я подразумеваю Keil.
|
|
|
|
|
Aug 25 2016, 09:30
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(aaarrr @ Aug 25 2016, 11:50)  Ничего не надо настраивать, только ядро правильное указать. Да, я попробовал перемножить два int-a и два float-a, посмотрел дизассемблер, там отличие только в том, что в первом случае команда MULS, а во втором VMUL.F32 Судя из статьи, VMUL.F32 выполняется за 1 такт, как и обычное умножение. Круто! Тогда у меня еще один вопрос, на входе у меня генератор белого шума, который выдает int, а на выходе, для ЦАП мне надо 24-битное число. Как в первом случае быстро преобразовать int (сдвинутый на 6 разрядов, чтобы на входе тоже было 24 бита) во float, а во втором случае float в int? И я правильно понимаю, что используя float вместо int я нисколько не потеряю в скорости выполнения программы? Даже выиграю, с учетом того, что не надо будет масштабировать результат?
|
|
|
|
|
Aug 25 2016, 11:46
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(adnega @ Aug 25 2016, 13:40)  Есть команды МК для преобразований int во float и обратно. какие? где можно про них подробней почитать? Цитата(adnega @ Aug 25 2016, 13:40)  Сдвиг на 6 разрядов можно заменить на умножение на константу 2^6 То есть, сдвиг на 6 разрядов выполняется за 6 тактов, а умножение на константу - за один, хитро. Но деление на константу выполняется за 14 тактов Еще у меня в фильтре получается очень большое соотношение частоты дискретизации и частоты среза. Чтобы правильно посчитать фильтр надо иметь высокую точность. Как прикинуть, хватит ли мне float-а, зная порядок коэффициентов фильтра?
|
|
|
|
|
Aug 25 2016, 12:04
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(DASM @ Aug 25 2016, 14:53)  Насколько мой склероз помнит - тут нужно ресэмплинг делать и использовать CIC фильтры, длиннющие FIR/IIR в данном случае совсем не гуд. Как это обойти - другой вопрос. В матлабе я рассчитал коэффициенты длиной 13 бит Quantized Numerator. Одновременно там рассчитываются некие идеальные коэффициенты Reference numerator, которые получаются длиннее. Так вот у меня вопрос, как прикинуть, нельзя ли эти Reference numerator записать в виде float, хватит ли точности float?
|
|
|
|
|
Aug 25 2016, 12:36
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(DASM @ Aug 25 2016, 15:31)  Так у флоат 24 бита мантиссы, как оно может быть менее точным, чем 13 бит? Чтобы оперировать 13-битными числами мне пришлось считать фильтр на пониженной частоте квантования, а потом ее повышать. А для float я хочу сразу делать фильтр на высокой частоте квантования.
|
|
|
|
|
Aug 25 2016, 13:09
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(DASM @ Aug 25 2016, 15:40)  Понятно. Математик из меня никакой, может просто промоделируете в Матлабе или SystemVue это? Я не знаю как заставить считать матлаб во float. Свои фильтры, целочисленные, я в маткад моделировал. Но там все понятно, раз коэффициенты 13 бит, такая точность и будет. А как там точность float задать я не знаю. Ну запишу я в свою модель идеальные коэффициенты из матлаба, он их посчитает как то, может с двойной точностью. А контроллер то будет с одинарной точностью считать.
|
|
|
|
|
Aug 25 2016, 13:48
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(DASM @ Aug 25 2016, 16:35)  Не знаю что и сказать, SystemVue позволяет считать и флоат и дабл и фиксед с любой точностью коэфф. и кол-ва бит. Матлаб, уверен, тоже. Да, я нашел где в матлабе посчитать коэффициенты с Single-precision floating-point Хорошо, теперь, если я буду подавать на вход фильтра с такими коэффициентами случайный 24-битный сигнал, у меня на выходе будет всегда получаться 24-битное число и никакие переполнения невозможны? Я просто никогда не работал с плавающей точкой, у целых чисел понятно когда появится переполнение, а тут - не очень.
|
|
|
|
|
Aug 26 2016, 06:04
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(sigmaN @ Aug 25 2016, 21:26)  Что нужно знать про арифметику с плавающей запятой https://habrahabr.ru/post/112953/да, я читал эту статью Цитата(sigmaN @ Aug 25 2016, 21:26)  Особо полезно прочесть вот эту часть 4. Подводные камни в арифметике с плавающей запятой а в чем польза? какой вывод можно сделать из этого пункта? не считать фильтры во float-ах?
|
|
|
|
|
Aug 26 2016, 06:18
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Atlantis- @ Aug 26 2016, 09:04)  а в чем польза? какой вывод можно сделать из этого пункта? не считать фильтры во float-ах? Считать, но правильно. Зачастую фильтрация - это сложение с накоплением произведений пар чисел. Нужно все перемножить. Полученные значения расставить по возрастанию. Суммировать от меньшего к большему. Так ошибка будет минимальна.
|
|
|
|
|
Aug 26 2016, 09:37
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(adnega @ Aug 26 2016, 09:18)  Считать, но правильно. Зачастую фильтрация - это сложение с накоплением произведений пар чисел. Нужно все перемножить. Полученные значения расставить по возрастанию. Суммировать от меньшего к большему. Так ошибка будет минимальна. Не понял, как суммировать от меньшего к большему? Коэффициенты фильтра у меня отличаются в два раза, а входной сигнал - рандомный. Знак тоже не угадаешь. Или что мне сначала сравнивать произведения между собой, а потом складывать?
|
|
|
|
|
Aug 26 2016, 11:41
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(khach @ Aug 26 2016, 11:06)  Начинать писание своего фильтра надо с того что скачать CMSIS-DSP последней версии, выбрать подходящий фильтр и скомпилить его. В этой библиотеке реализован только решетчатый фильтр IIR, а мне надо обычный.
|
|
|
|
|
Aug 27 2016, 16:25
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(sigmaN @ Aug 26 2016, 19:41)  https://www.keil.com/pack/doc/CMSIS/DSP/htm...scade_d_f1.html Можно реализовтаь фильтр любого порядка. Если нужен первый то делаете b2=0 and a2=0. Впрочем там всё хорошо описано по ссылке Спасибо, это я как то пропустил... Изучаю, не понял одно требование Цитата Pay careful attention to the sign of the feedback coefficients. Some design tools use the difference equation y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2] In this case the feedback coefficients a1 and a2 must be negated when used with the CMSIS DSP Library. Что то странное, у меня только а1 отрицательный, а2 - положительный. Или это правильно переводится как "а1 и а2 должны нейтрализовываться" и у меня все правильно?
Сообщение отредактировал Atlantis- - Aug 27 2016, 16:33
|
|
|
|
|
Aug 28 2016, 08:37
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Читаем описание функци, реализует она следующее: Цитата Algorithm Each Biquad stage implements a second order filter using the difference equation: y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] Ниже заостряется внимание на том, что некоторые программы для моделирования фильтров подразумевают, что уравнение будет другим Цитата Some design tools use the difference equation y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2] Видите разницу? в первом случае +a1 +a2 а во втором -a1 -a2 Соответственно вам подсказывают, что если вы пользуетесь как раз таким софтом, то коэффициенты a1 и a2 must be negated. Если по русски то перед применением коэффициенты a1 и a2 умножьте на -1, таким образом изменив их знак )
--------------------
The truth is out there...
|
|
|
|
|
Aug 29 2016, 11:56
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Аааа, вон оно как...понял, спасибо большое! Пока сам написал реализацию пары уравнений работающих с float, проверил анализатором спектра - похоже на правду. Смущает несколько моментов: 1) результат вычислений получается float, для вывода на ЦАП, естественно, преобразую его к int - теряется дробная часть, это нормально? 2) Отрицательные значения. Я подаю на вход фильтра белый шум, 24-битный. Соответственно, после фильтра у меня тоже должно получаться 24-битный результат. Но! Отрицательные значения в процессоре - это инвертированное положительное число + 1. А для ЦАП отрицательное значение получается простой инверсией положительного числа. Я отлавливаю в итоговом результате, если 23-й бит = 1, то я из всего числа вычитаю единицу. Это правильно? 3) Мне коэффициенты надо с компьютера передавать, а они у меня float теперь. Тут мне посоветовали, домножать, потом делить. Но как мне передать например число 0.99577337503433228 ? Чтобы целое получить, надо домножить на 10^17 и что потом с ним делать? Оно же даже в int не влезет.
|
|
|
|
|
Aug 29 2016, 14:24
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Порылся в интернете, на последний вопрос вроде нашел ответ. Сделал так, результат сходится Код float float_value=0.6543278; char float_bytes[sizeof(float)]; float *ptr; float new_value;
//разбиение на байты float_bytes[0] = *((char *)&float_value + 0);//0x07 float_bytes[1] = *((char *)&float_value + 1);//0x82 float_bytes[2] = *((char *)&float_value + 2);//0x27 float_bytes[3] = *((char *)&float_value + 3);//0x3F //http://floatingpoint.ru/online/dec2float.php - проверка
//собрали из байт float ptr = (float*)float_bytes; new_value = *ptr;
|
|
|
|
|
Aug 29 2016, 19:11
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата 1) результат вычислений получается float, для вывода на ЦАП, естественно, преобразую его к int - теряется дробная часть, это нормально? Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/ Цитата 2) Отрицательные значения. Я подаю на вход фильтра белый шум, 24-битный. Соответственно, после фильтра у меня тоже должно получаться 24-битный результат. Но! Отрицательные значения в процессоре - это инвертированное положительное число + 1. А для ЦАП отрицательное значение получается простой инверсией положительного числа. Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля? Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет. А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768 Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить. У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят. Что с этим делать это решать вам(зависит от задачи). Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу. В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0. DAC_REGISTER = 32768 + filter_data[i]; И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод. Цитата 3) Мне коэффициенты надо с компьютера передавать, а они у меня float теперь. Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя. Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника  Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано. Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2
--------------------
The truth is out there...
|
|
|
|
|
Aug 30 2016, 07:22
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(sigmaN @ Aug 29 2016, 22:11)  Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить Цитата(sigmaN @ Aug 29 2016, 22:11)  Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля? Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет. А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768 Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить. У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят. Что с этим делать это решать вам(зависит от задачи). Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу. В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0. DAC_REGISTER = 32768 + filter_data[i]; И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод. ЦАП - CS4344, пробовал на AD1852. Ни в том ни в другом даташите не нашел, как же представлять отрицательные числа. Но это как то должно наверно быть обозначено? Для AD1852 написал тестовую синусоиду, сначала я не парился, думал, что максимальное отрицательное значение - это 0х000000. Проверил - какая то фигулька получилась, а не синусоида. Потом вот просто начал инвертировать положительные значения - получилась синусоида, размах вроде как и должен быть. А для CS4344 я просто подал тот же массив - получилась синусоида, ну и хорошо. А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП? Цитата(sigmaN @ Aug 29 2016, 22:11)  Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя. Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника  Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано. Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2Да мне главное правильно собрать float из байтов на микроконтроллере. А разобрать его на компе - чисто для проверки. Хотя зачем, я могу даже сразу вручную разобрать все нужные float-ы на байты, на этом сайте http://floatingpoint.ru/online/dec2float.php Хранить и передавать в виде байт. Тем более коэффициенты у меня все уже вычислены. Наверно так будет наиболее надежно))
|
|
|
|
|
Aug 30 2016, 11:15
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить Именно так. Цитата А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП? Ну какие могут быть отрицательные значения при однополярном питании? В принципе я вам направление для мысли дал. Разбирайтесь....
--------------------
The truth is out there...
|
|
|
|
|
Aug 30 2016, 12:00
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (sigmaN @ Aug 30 2016, 14:15)  Ну какие могут быть отрицательные значения при однополярном питании? TC использует аудио цап ацп. Сейчас они все двуполярные по коду и однополярные по питанию. В ацп даже цифровой фильтр на несколько гц встраивают, чтобы фильтровать смещение нуля (аналоговое, как я понимаю).
|
|
|
|
|
Aug 31 2016, 12:16
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Нашел ответ на свой вопрос Цитата The AD1852 accepts serial audio data in MSB first, twos-complement format.
|
|
|
|
|
Sep 1 2016, 10:24
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну вот, значит отрицательные числа представлены так-же как и в процессоре осталось только разобраться с MSB first... B в MSB имеется ввиду Bit или Byte? если Byte то получается Big Endian, а проц у вас Little endian.... https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2Может быть поэтому во время эксперимента у вас не получалась синусоида....
--------------------
The truth is out there...
|
|
|
|
|
Sep 1 2016, 17:34
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (sigmaN @ Sep 1 2016, 13:24)  если Byte то получается Big Endian, а проц у вас Little endian.... Это забота аппаратного аудио интерфейса в процессоре, если ТС его использует. Более вероятна проблема выбора 32 бит данных через 16 бит порты в некоторых "оптимизированных" платформах
|
|
|
|
|
Sep 5 2016, 13:51
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Сделал полосовые фильтры, проверил - все нормально. А с режекторным какая то засада, не понимаю, где может быть ошибка? Делаю вот так: Код struct { float a0; float a1; float a2; float b1; float b2; int k; int k1; int k2; float X[4]; float Y[4]; int Y1; } NotchedFilter; в прерывании I2S Код //выдаю данные hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1; hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1; //считаю следующий отсчет // noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*noise.NotchedFilter.X[noise.NotchedFilter.k2] + // noise.NotchedFilter.a1*noise.NotchedFilter.X[noise.NotchedFilter.k1] + noise.NotchedFilter.a0*noise.NotchedFilter.X[noise.NotchedFilter.k] - // noise.NotchedFilter.b1*noise.NotchedFilter.Y[noise.NotchedFilter.k1] - noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2]; noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*(noise.NotchedFilter.X[noise.NotchedFilter.k2] + noise.NotchedFilter.X[noise.NotchedFilter.k]) + noise.NotchedFilter.a1*(noise.NotchedFilter.X[noise.NotchedFilter.k1] - noise.NotchedFilter.Y[noise.NotchedFilter.k1]) - noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2]; noise.NotchedFilter.Y1 = noise.NotchedFilter.Y[noise.NotchedFilter.k];//оптимизировал а0=а2, а1=b1 noise.NotchedFilter.k = (noise.NotchedFilter.k + 1)&BUFFMASK; noise.NotchedFilter.k1 = (noise.NotchedFilter.k - 1)&BUFFMASK;//посчитали индекс Xk-1 noise.NotchedFilter.k2 = (noise.NotchedFilter.k - 2)&BUFFMASK;//посчитали индекс Xk-2 что тут может быть не так? проверил под отладкой - k меняется как и должно, сам посчитал один отсчет - сошлось с показанием процессора.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|