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

Нецелая системная частота STM32F4

21 минуту назад, jcxz сказал:

то какой смысл считать фазу точнее?

Если генераторы независимые, то смысла нет. А если генератор общий, то проблем с синхронизацией будет меньше.

Кста, если частоту I2S сделать равной степени двойки (например, 65536), то и с делениями полегчает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кста, все может получиться и на 8МГц кварце:

- /M = /8

- PLL2SN = x384

- PLL2SR = 5

- I2SPR_I2SDIV = 50

- I2SPR_ODD = 0

8M / 8 * 384 / 5 / 50 / 2 = 48k * 16

Обращаю внимание, что предделитель I2S не обязан быть степенью двойки (как у SPI, например)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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.

:biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, blackfin сказал:

Если, конечно, нужно вычислить всего несколько десятков семплов для нескольких периодов синусоидального сигнала с частотой 8 кГц..

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, adnega said:

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

 

 ТС вполне конкретно указал, что ему нужны 2-3 периода:

6 hours ago, Dima1060 said:

Ну например стимул состоящий из 2-3 периодов с частотой 8 кГц, повторяющийся с частотой 20Гц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата

повторяющийся с частотой 20Гц.

Только если в начале каждого стимула обнулять расчеты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, jcxz сказал:

Нет. Никаких таблиц не нужно. Считаем синус полиномом...

Хотел бы посмотреть на более менее вменяемое описание сути метода...
Т.е. не на злом языке математики, а на простом человеческом с немудреными формулами:biggrin:

Не встречалось такое?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, adnega said:

Только если в начале каждого стимула обнулять расчеты.

Это же очевидно, Ватсон! ))

 

 

9 minutes ago, Arlleex said:

Хотел бы посмотреть на более менее вменяемое описание сути метода...
Т.е. не на злом языке математики, а на простом человеческом с немудреными формулами:biggrin:

Не встречалось такое?

Интерполяционные формулы Ньютона

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 сделано самому интересно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал размотать код от jcxz: получается полином 6-ой степени (для ряда Тейлора странные коэффициенты), причем A0 != 0 поэтому sin(0) будет != 0. Что!?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, blackfin said:

А вот результат вычислений:

Что-то у меня не сходится, второй период получается больше чем первый. Я что-то не так посчитал, вернее, переформулирую так: по каким причинам конец синусоиды достигнет нуля раньше, чем ЦАП отправит точку с амплитудой ноль?

Sinus.png

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 МГц кварце получается при таких настройках:

 

Clock1.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

2103028119_.thumb.png.692c2fe889c51ce8c950d6ac64d47bd0.png

1842628409_.thumb.png.5703a099c6611f9c274c3709bf370ef8.png

605817237_.thumb.png.0b7c6b8e823eb30c0bc60fe44585ab6a.png

 

Поскольку передаются два канала, то делитель I2S должен быть не 100 (как я указал выше), а 50=25*2+0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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!

 


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Сойдет?


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17.07.2021 в 19:10, blackfin сказал:

И вот зачем мне эта ссылка? Мало того, что для "въезда" она не годится, так еще и по объему формул больше чем их описания. Про синус ни слова. У нас в универе когда-то был замечательный препод, который на очень простых аналогиях и "на пальцах" разжевывал весьма сложные вещи. Он придерживался мнения (как и я сейчас), что большинство вот таких статей, где формул больше чем словесного описания сути, пишутся учеными для таких же ученых.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...