adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 21 минуту назад, jcxz сказал: то какой смысл считать фазу точнее? Если генераторы независимые, то смысла нет. А если генератор общий, то проблем с синхронизацией будет меньше. Кста, если частоту I2S сделать равной степени двойки (например, 65536), то и с делениями полегчает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба Кста, все может получиться и на 8МГц кварце: - /M = /8 - PLL2SN = x384 - PLL2SR = 5 - I2SPR_I2SDIV = 50 - I2SPR_ODD = 0 8M / 8 * 384 / 5 / 50 / 2 = 48k * 16 Обращаю внимание, что предделитель I2S не обязан быть степенью двойки (как у SPI, например) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 24 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 4 hours ago, Dima1060 said: ... как при частоте квантования ЦАП = 46875Гц получить ровно 8 кГц? Там же получается нецелое число точек на период. Очень просто, если вспомнить формулу Эйлера из школьной математики.. )) И не нужны будут ни таблицы, ни полиномы. Нужно будет сделать всего четыре умножения и два сложения на каждый семпл сигнала.. Если, конечно, нужно вычислить всего несколько десятков семплов для нескольких периодов синусоидального сигнала с частотой 8 кГц.. #include "stdafx.h" #include <math.h> #include <stdio.h> double pi = 3.1415926535897932384626433832795; // Амплитуда сигнала [В]: double amp = 10.0; // Частота импульса [Гц]: double fp = 8.0e3; // Круговая частота импульса [Рад/с]: double wp = 2*pi*fp; // Частота дискретизации [Гц]: double fs = 46875; // Длительность импульса равна двум периодам [сек]: double tp = 2.0/fp; // Период дискретизации [сек]: double dt = 1.0/fs; // Общее число семплов в импульсе: int ns = (int)(tp/dt); // Значения параметров: double cosw = cos(wp*dt); double sinw = sin(wp*dt); // Начальные значения семплов импульса: double cost = amp; double sint = 0.0; double St,cc,ss,cs,sc; int _tmain(int argc, _TCHAR* argv[]) { for (int i = 0; i < ns+1; i++) { // Точные значения сигнала: St = amp*sin(wp*dt*i); printf("cos(%03d) = %+f\tsin(%03d) = %+f\terr = %e\n",i,cost,i,sint,abs(St-sint)); cc = cost*cosw; ss = sint*sinw; cs = cost*sinw; sc = sint*cosw; // Новые значения семплов импульса: cost = cc-ss; sint = cs+sc; } return 0; } А вот результат вычислений: cos(000) = +10.000000 sin(000) = +0.000000 err = 0.000000e+000 cos(001) = +4.780788 sin(001) = +8.783170 err = 0.000000e+000 cos(002) = -5.428813 sin(002) = +8.398094 err = 1.776357e-015 cos(003) = -9.971589 sin(003) = -0.753268 err = 9.992007e-016 cos(004) = -4.105597 sin(004) = -9.118337 err = 0.000000e+000 cos(005) = +6.045991 sin(005) = -7.965299 err = 1.776357e-015 cos(006) = +9.886517 sin(006) = +1.502256 err = 2.664535e-015 cos(007) = +3.407078 sin(007) = +9.401693 err = 1.776357e-015 cos(008) = -6.628814 sin(008) = +7.487244 err = 8.881784e-016 cos(009) = -9.745269 sin(009) = -2.242708 err = 6.661338e-015 cos(010) = -2.689198 sin(010) = -9.631626 err = 0.000000e+000 cos(011) = +7.173971 sin(011) = -6.966644 err = 7.105427e-015 Понятно, что в программе на МК все вычисления нужно делать в fixed-points. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 4 минуты назад, blackfin сказал: Если, конечно, нужно вычислить всего несколько десятков семплов для нескольких периодов синусоидального сигнала с частотой 8 кГц.. Неа, нужно будет многократно рассчитывать значения - может и погрешность набежать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 24 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 3 minutes ago, adnega said: Неа, нужно будет многократно рассчитывать значения - может и погрешность набежать. ТС вполне конкретно указал, что ему нужны 2-3 периода: 6 hours ago, Dima1060 said: Ну например стимул состоящий из 2-3 периодов с частотой 8 кГц, повторяющийся с частотой 20Гц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба Цитата повторяющийся с частотой 20Гц. Только если в начале каждого стимула обнулять расчеты. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 173 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 5 часов назад, jcxz сказал: Нет. Никаких таблиц не нужно. Считаем синус полиномом... Хотел бы посмотреть на более менее вменяемое описание сути метода... Т.е. не на злом языке математики, а на простом человеческом с немудреными формулами Не встречалось такое? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 24 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 14 minutes ago, adnega said: Только если в начале каждого стимула обнулять расчеты. Это же очевидно, Ватсон! )) 9 minutes ago, Arlleex said: Хотел бы посмотреть на более менее вменяемое описание сути метода... Т.е. не на злом языке математики, а на простом человеческом с немудреными формулами Не встречалось такое? Интерполяционные формулы Ньютона Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 9 минут назад, Arlleex сказал: Хотел бы посмотреть на более менее вменяемое описание сути метода... Я, думаю, так может быть: sin(T + t) = sin(T) * cos(t) + cos(T) * sin(t) T - табличные значения, t - отклонение от табличного значения. sin(t) = t - t^3/3! + t^5/5! - ... = (((1/5!)t^2 - 1/3!)t^2 + 1)t cos(t) = 1 - t^2/2! + t^4/6! - ... = ((1/6!)*t^2 - 1/2!)t^2 + 1 Как у jcxz сделано самому интересно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба Попробовал размотать код от jcxz: получается полином 6-ой степени (для ряда Тейлора странные коэффициенты), причем A0 != 0 поэтому sin(0) будет != 0. Что!? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 5 hours ago, blackfin said: А вот результат вычислений: Что-то у меня не сходится, второй период получается больше чем первый. Я что-то не так посчитал, вернее, переформулирую так: по каким причинам конец синусоиды достигнет нуля раньше, чем ЦАП отправит точку с амплитудой ноль? 6 hours ago, adnega said: Кста, все может получиться и на 8МГц кварце: - /M = /8 - PLL2SN = x384 - PLL2SR = 5 - I2SPR_I2SDIV = 50 - I2SPR_ODD = 0 8M / 8 * 384 / 5 / 50 / 2 = 48k * 16 Обращаю внимание, что предделитель I2S не обязан быть степенью двойки (как у SPI, например) Не понял половины делителей, что Вы написали, у меня минимальная погрешность на 8 МГц кварце получается при таких настройках: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 17 июля, 2021 Опубликовано 17 июля, 2021 · Жалоба 1 час назад, Dima1060 сказал: Не понял половины делителей, что Вы написали, у меня минимальная погрешность на 8 МГц кварце получается при таких настройках: А какие именно делители не понятны? /M=8 это делитель перед PLL2S. он у вас тоже 8. PLL2SN - это *N в блоке PLL2S - у вас x197, а должен быть x384. PLL2SR - это /R в блоке PLL2S - у вас /2, а должен быть /5. Таким образом частота I2S у вас будет не 98.5МГц, а 76.8МГц. Затем в настройках I2S нужно задать делитель 100, но в регистрах он разбит на две части - см. описание I2SPR Поскольку передаются два канала, то делитель I2S должен быть не 100 (как я указал выше), а 50=25*2+0. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 18 июля, 2021 Опубликовано 18 июля, 2021 · Жалоба 21 hours ago, adnega said: А какие именно делители не понятны? Quote When the master clock is generated (MCKOE in the SPI_I2SPR register is set):FS = I2SxCLK / [(32*2)*((2*I2SDIV)+ODD)*4)] when the channel frame is 32-bit wide Считаем: 76800/[(32*2)*((2*25)+0)*4)] = 76800/[64*50*4] = 6 кГц Но судя по таблице 127 (у Вас почему то это 126, может RM на другой процессор?) можно получить точность 0,0186%, если задать умножитель PLLI2SN = 258, а делители PLLI2SR и I2SDIV по 3 (I2SODD = 1), но у меня это тоже не сходится... Хотя нет, все правильно, на I2S точность 0,01% показывает CubeMX, а я же использую не его, а модуль SAI! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 18 июля, 2021 Опубликовано 18 июля, 2021 · Жалоба 9 минут назад, Dima1060 сказал: Считаем: 76800/[(32*2)*((2*25)+0)*4)] = 76800/[64*50*4] = 6 кГц Но судя по таблице 127 (у Вас почему то это 126, может RM на другой процессор?) можно получить точность 0,0186%, если задать умножитель PLLI2SN = 258, а делители PLLI2SR и I2SDIV по 3 (I2SODD = 1), но у меня это тоже не сходится Я считал для двух каналов по 16 бит и без master clock. Тогда так: HSE=8M делитель HSE /M = /5 на входах PLL 1.6M MainPLL: *N = *210, /P = /2, /Q = /7 1.6M * 210 = 336M VCO, 336M / 2 = 168M PLLCLK, 336M / 7 = 48M USB. PLLI2S: *N = *192, /R = 5 1.6M * 192 = 307.2M VCO, 307.2M / 5 = 61.44M I2SCLK 61440k / (32 * 2 * (2 * 2 + 1) * 4) = 61440k / (64 * 5 * 4) = 48k Сойдет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 173 19 июля, 2021 Опубликовано 19 июля, 2021 · Жалоба 17.07.2021 в 19:10, blackfin сказал: Интерполяционные формулы Ньютона И вот зачем мне эта ссылка? Мало того, что для "въезда" она не годится, так еще и по объему формул больше чем их описания. Про синус ни слова. У нас в универе когда-то был замечательный препод, который на очень простых аналогиях и "на пальцах" разжевывал весьма сложные вещи. Он придерживался мнения (как и я сейчас), что большинство вот таких статей, где формул больше чем словесного описания сути, пишутся учеными для таких же ученых. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться