"Нерегулярный" НЕинтеро-таймер значения прерывания времени (e.глин. 22.67US/44.1 кГц)

nicolas_soundforce
Чт 13 июля 2017 г., 7:42 утра
Заседание,

Я использовал чертежи почти исключительно в последние месяцы с этим ядром. Это было потрясающе, большое спасибо всем участникам, чтобы улучшить этот проект.

Мой вопрос: можно ли сделать синюю таблетку прерываться с таймером 22.67us ? Я строю игрока с волновым файлом и хочу кормить ЦАП с образцами каждые 22.67US, чтобы достичь скорости дискретизации 44.1 кГц. На данный момент он работает в 22 и 23 нас, но он не воспроизводит на оригинальной скорости.

Я использую один из 3 таймеров.

заранее спасибо,
Николас.

астер
Чт 13 июля 2017 г. 9:08 утра
Посмотрите здесь, это может быть полезно
https: // libstock.Микро.com/projects/vi ... калькулятор

Пито
Чт 13 июля 2017 г. 9:51
STM32F103 не обладает фракционным PLL или предварительным масштабами/разделителями, только целочисленные.
Таким образом, единственный способ получить что-то лучше, чем 22-23US,-это поиграть с настройками часов процессора, например, целое число дает вам лучший результат.

Дэнниф
Чт 13 июля 2017 г. 10:01
Чтобы достичь скорости дискретизации 44.1 кГц. На данный момент он работает в 22 и 23 нас Вместо того, чтобы думать об этом с точки зрения времени, с точки зрения частоты: какая частота вам нужна MCU, чтобы вы могли попасть в это 44.Номер 1 кГц с целочисленным дивидором?

Тогда это становится намного проще.

Пито
Чт 13 июля 2017 г. 10:18 утра
Есть специальные кристаллические частоты, чтобы получить 44.1 кГц для аудио с целочисленными разделителями:
https: // en.Википедия.org/wiki/crystal_o ... запрашивателя
Таким образом, вы можете заменить кристалл и получить идеальный звук :)

nicolas_soundforce
Чт 13 июля 2017 г. 10:41
Спасибо за первые ответы,
калькулятор очень интересный. К сожалению, код предназначен для библиотеки ST (я думаю), и я не компилируюсь с ядром STM32Duino Core. Но это здорово, чтобы получить ценности прескалера и авторелуазации регистров. С автоматической загрузкой 1632 года я могу приблизиться, как 44 117647058823529 кГц, поэтому период в 22.666666 США. Этого, наверное, достаточно для моего приложения.

Но изменение часов процессора действительно, вероятно, гораздо лучшая идея. Я мог бы легко запустить 48 МГц и вместо этого использовать 48 кГц (еще один стандарт Freq Freq Audio). Просто с перезагрузкой 999.

Я надеюсь, что моя программа тоже работает в 48 МГц. Я также мог бы попытаться опустить процессор до 96 МГц.

РЕДАКТИРОВАТЬ: Глупый меня, для 48 кГц я могу запустить на 72 МГц и использовать перезагрузку 1500.

Для тех, кто заинтересован в математике:

Период события обновления рассчитывается следующим образом:
Update_event = TIM_CLK/((PSC + 1)*(arr + 1)*(rcr + 1)))
TIM_CLK = 72 МГц
ПРЕСКАЛЕР = 0
Автозагрузка = 1499
Нет счетчика повторения rcr = 0
Update_event = 72*(10^6)/((0 + 1)*(1499 + 1)*(1))
Update_event = 48000 Гц

nicolas_soundforce
Чт 13 июля 2017 г. 10:56 утра
Для тех, кто заинтересован, мне все еще нужно проверить это (сейчас у меня нет аппаратного обеспечения), но, согласно Hardwaretimer.CPP, это должно быть правильным

Чтобы установить прескалер:
Таймер2.SetPrescaleFactor (0);

Чтобы установить значение AutorEload:
Таймер2.SetoverFlow (1499);

Переполнение 1633 года даст мне ряд 44090 630740967544397 Гц, что является ошибкой 0,021%. Я должен проверить, но я думаю, что это, вероятно, хорошо для моего приложения.

Спасибо за указатели!

Пито
Чт 13 июля 2017 г. 11:03
Я строю волновой файловый игрок и хочу накормить ЦАП с образцами Кстати, в чертеже нет внутренних ЦАП в чертеже.. С F103 вы должны идти с большими пакетами.. :(
Или используйте внешний ЦАП, или попробуйте с ШИМ и низким проходом..

nicolas_soundforce
Чт 13 июля 2017 г., 11:30 утра
[Пито - Чт 13 июля 2017 г. 11:03] - Я строю волновой файловый игрок и хочу накормить ЦАП с образцами Кстати, в чертеже нет внутренних ЦАП в чертеже.. С F103 вы должны идти с большими пакетами.. :(
Или используйте внешний ЦАП, или попробуйте с ШИМ и низким проходом..
Действительно, я строю доску с PT8211 и сейчас тестирую время с другой доской с MCP4822.

Chismicro
Чт 13 июля 2017 г. 13:18
Я также немного экспериментировал с аудио приложениями на STM32F103.
Эн.г я попробовал это усилитель i2s от adafruit, но я не мог его запустить.
Требуется довольно точное время сигнала i2S, а Bluepill STM32F103 не имеет периферийного устройства i2s.

Здесь Я провел несколько экспериментов с игроком DAC WAV Sigma Delta.
Он играет только одну секунду из WAV, отобранного с 8 кГц и, чем аварии ...

Как мне грустно ... эксперимент ...

строка 28: имя файла
строка 39: dacsamplingrate_hz 8000

Racemaniac
Чт 13 июля 2017 г. 14:22
Что касается ЦАП, если вы не возражаете против 12 -битной точности, MCP4725 (который вы можете найти очень дешевый онлайн) отлично в сочетании с Bluepill.
Я разместил код для него в последнем посте этой темы: http: // www.STM32duino.com/viewtopic.PHP?t = 1048
Это позволяет вам достичь скорости отбора проб до 60 кГц, используя этот ЦАП (но делает это путем разгрузки порта I2C, на официальной максимальной скорости порта I2C вы ограничены около 20 кГц).
Но у меня был хороший успех, используя это так, и это очень дешевое решение, чтобы получить хороший звук из чертежа :).
И это также очень быстрый код, вообще нет накладных расходов :).

victor_pv
Чт 13 июля 2017 г., 17:05
Николас я написал драйвер I2S, совместимый с Teensy/Arduino.
Он размещен в отдельной ветке в разделе библиотеки на форуме.
Я протестировал его с помощью ЦАП PT8211 I2S, они доступны для центов и не нужны отдельные часы, кроме данных.
Я начал использовать это по рекомендации от Мадиаса, когда он начал писать код I2S, и я начал ему помогать. Позже я добавил в этот код, чтобы превратить его в библиотеку.
Драйвер I2S использует DMA, поэтому нагрузка на процессор минимальна. В настоящее время только для передачи данных из буфера приложения в буфер драйвера, но вы можете изменить драйвер, чтобы вместо этого он использовал буфер приложения непосредственно для DMA, а на этой точке загрузка ЦП была бы 0 от драйвера, и только из вашего приложения Загрузка буфера новыми данными.

Драйверу I2S требуется MCU с i2s (RCT или выше), поэтому не будет работать на Maple Mini.
Но технически можно просто использовать порт SPI для некоторых i2s, если вы установите таймер для запуска событий DMA для порта SPI, а затем установите канал времени для переключения на каждой передаче.
Таким образом, событие таймера может привести к переключению PIN -коммутатора на каждом событии перекрытия, чтобы указать слева и справа, и в то же время таймер может запустить новую передачу DMA в порт SPI, а порт отправляет данные.
Я не пробовал это, но я думаю, что теория звучит и должна работать.

Яромир
Чт 13 июля 2017 г. 18:09
[nicolas_soundforce - Чт 13 июля 2017 г., 7:42 утра] - я строю волновый файл и хочу накормить ЦАП с образцами каждые 22.67US, чтобы достичь скорости дискретизации 44.1 кГц. На данный момент он работает в 22 и 23 нас, но он не воспроизводит на оригинальной скорости.
Настройте прерывание до 23US, после того, как два прерывания сократят цикл до 22US, затем вернитесь к 23US. Время прерывания должно выглядеть 23-23-22-23-23-22-23-23-22-23-23-22 и т. д... у тебя есть идея. Средняя скорость прерывания составит 22,667US, но эта установка также внесет джиттер (фазовый шум). Это в вашем решении о том, сколько это будет проблема, мое ощущение, что все будет в порядке.
Вы можете использовать другие фракции, чем 2/3 для достижения более точной настройки.

nicolas_soundforce
Чт 13 июля 2017 г. 22:11
[victor_pv - Чт 13 июля 2017 г., 17:05] - Николас я написал драйвер I2S, совместимый с Teensy/Arduino.
Он размещен в отдельной ветке в разделе библиотеки на форуме.
Я протестировал его с помощью ЦАП PT8211 I2S, они доступны для центов и не нужны отдельные часы, кроме данных.
Я начал использовать это по рекомендации от Мадиаса, когда он начал писать код I2S, и я начал ему помогать. Позже я добавил в этот код, чтобы превратить его в библиотеку.
Драйвер I2S использует DMA, поэтому нагрузка на процессор минимальна. В настоящее время только для передачи данных из буфера приложения в буфер драйвера, но вы можете изменить драйвер, чтобы вместо этого он использовал буфер приложения непосредственно для DMA, а на этой точке загрузка ЦП была бы 0 от драйвера, и только из вашего приложения Загрузка буфера новыми данными.

Драйверу I2S требуется MCU с i2s (RCT или выше), поэтому не будет работать на Maple Mini.
Но технически можно просто использовать порт SPI для некоторых i2s, если вы установите таймер для запуска событий DMA для порта SPI, а затем установите канал времени для переключения на каждой передаче.
Таким образом, событие таймера может привести к переключению PIN -коммутатора на каждом событии перекрытия, чтобы указать слева и справа, и в то же время таймер может запустить новую передачу DMA в порт SPI, а порт отправляет данные.
Я не пробовал это, но я думаю, что теория звучит и должна работать.
Привет, Виктор, я тоже читаю твои посты в I2S PT8211. На данный момент я придерживаюсь синей таблетки, но я проверю вашу библиотеку, если обновлю до другого чипа. Ваша идея звучит хорошо, я постараюсь заставить ее работать.

nicolas_soundforce
Чт 13 июля 2017 г. 22:19
[nicolas_soundforce - Чт 13 июля 2017 г. 10:41]] - Для тех, кто заинтересован, мне все еще нужно проверить это (сейчас у меня нет аппаратного обеспечения), но, согласно Hardwaretimer.CPP, это должно быть правильным

Чтобы установить прескалер:
Таймер2.SetPrescaleFactor (0);

Чтобы установить значение AutorEload:
Таймер2.SetoverFlow (1499);

Переполнение 1633 года даст мне ряд 44090 630740967544397 Гц, что является ошибкой 0,021%. Я должен проверить, но я думаю, что это, вероятно, хорошо для моего приложения.

Спасибо за указатели!
ОК, после тестирования:
Таймер2.SetPrescaleFactor (0); неправильно

Библиотека подтверждает, что:
void hardwaretimer :: setprescalefactor (uint32 фактор) {
timer_set_prescaler (это->dev, (uint16) (фактор - 1));
}

Параметр 0 приведет к -1 предварительно. Таймер2.SetPrescaleFactor (1); Дайте хорошие результаты, как и ожидалось.

Но перезагрузка 1633 года приводит к замедлению воспроизведения звука.Я на 100% уверен, что файл 44.1 кГц, и я получаю подтверждение в байте № 24, 25, 26 & 27. На данный момент я не знаю, почему 44.Аудиофайл 1 кГц не воспроизводит синхронизацию, когда каждый образец выталкивается каждые 22.68US (1/(72000000/1633)). И это не немного, это далеко. Я должен установить автоматическую перезагрузку на 1500, чтобы она звучала правильно.

Я измерил микросхемы между прерыванием таймера время от времени, и это правильно около 22US. Так почему же звук замедляется...

victor_pv
Пт 14 июля 2017 г., 4:30 утра
[nicolas_soundforce - Чт 13 июля 2017 г. 22:19] -
[nicolas_soundforce - Чт 13 июля 2017 г. 10:41]] - Для тех, кто заинтересован, мне все еще нужно проверить это (сейчас у меня нет аппаратного обеспечения), но, согласно Hardwaretimer.CPP, это должно быть правильным

Чтобы установить прескалер:
Таймер2.SetPrescaleFactor (0);

Чтобы установить значение AutorEload:
Таймер2.SetoverFlow (1499);

Переполнение 1633 года даст мне ряд 44090 630740967544397 Гц, что является ошибкой 0,021%. Я должен проверить, но я думаю, что это, вероятно, хорошо для моего приложения.

Спасибо за указатели!
ОК, после тестирования:
Таймер2.SetPrescaleFactor (0); неправильно

Библиотека подтверждает, что:
void hardwaretimer :: setprescalefactor (uint32 фактор) {
timer_set_prescaler (это->dev, (uint16) (фактор - 1));
}

Параметр 0 приведет к -1 предварительно. Таймер2.SetPrescaleFactor (1); Дайте хорошие результаты, как и ожидалось.

Но перезагрузка 1633 года приводит к замедлению воспроизведения звука.Я на 100% уверен, что файл 44.1 кГц, и я получаю подтверждение в байте № 24, 25, 26 & 27. На данный момент я не знаю, почему 44.Аудиофайл 1 кГц не воспроизводит синхронизацию, когда каждый образец выталкивается каждые 22.68US (1/(72000000/1633)). И это не немного, это далеко. Я должен установить автоматическую перезагрузку на 1500, чтобы она звучала правильно.

Я измерил микросхемы между прерыванием таймера время от времени, и это правильно около 22US. Так почему же звук замедляется...
Вы подтвердили, если файл моно/стерео и 8/16 битов? Возможно, вы выводите образцы для 2 каналов, которые заставили бы его играть на полгоспи. Похоже, не так, но стоит подтвердить.
У меня есть свободная версия библиотеки TMRPCM, и у меня не было проблем с выводом с то, что казалось правильным скоростью, возможно, на 1 или 2, но не так много, как вы.

Кстати, таймер отсчитывает от 0 до значения перезагрузки, поэтому вам необходимо загрузить ARR за 1 меньше, чем вы рассчитываете. Итак, для 44100 вы хотите (округление до ближайшего целого числа):
(72000000/44100) -1 ~ = 1632
Но это не будет иметь значения, как то, что вы описываете.

nicolas_soundforce
Сб 15 июля 2017 г. 13:02
Хорошо. Я обнаружил, что моя проблема заключалась в том, что SD -карта недостаточно быстра.
Но когда я заполняю массив таким же большим количеством байтов, синие таблетки могут забрать и воспроизвести его обратно, она синхронизируется/в комплекте с перезагрузкой 1633.

Я уже вырубил новую прототипную печатную плату для Bluepill, Pt8211, Filter и Op Amp, а также флэш -чип Winbond.
В Start Up я скопирую все байты данных с SD -карты на Flash -чип, надеюсь, это будет играть красиво и быстро и позволит мне одновременно транслировать 2 канала.

Спасибо всем, что задумались со мной.

[/u]
[victor_pv - Пт 14 июля 2017 г. 4:30] -
[nicolas_soundforce - Чт 13 июля 2017 г. 22:19] -
[nicolas_soundforce - Чт 13 июля 2017 г. 10:41]] - Для тех, кто заинтересован, мне все еще нужно проверить это (сейчас у меня нет аппаратного обеспечения), но, согласно Hardwaretimer.CPP, это должно быть правильным

Чтобы установить прескалер:
Таймер2.SetPrescaleFactor (0);

Чтобы установить значение AutorEload:
Таймер2.SetoverFlow (1499);

Переполнение 1633 года даст мне ряд 44090 630740967544397 Гц, что является ошибкой 0,021%. Я должен проверить, но я думаю, что это, вероятно, хорошо для моего приложения.

Спасибо за указатели!
ОК, после тестирования:
Таймер2.SetPrescaleFactor (0); неправильно

Библиотека подтверждает, что:
void hardwaretimer :: setprescalefactor (uint32 фактор) {
timer_set_prescaler (это->dev, (uint16) (фактор - 1));
}

Параметр 0 приведет к -1 предварительно. Таймер2.SetPrescaleFactor (1); Дайте хорошие результаты, как и ожидалось.

Но перезагрузка 1633 года приводит к замедлению воспроизведения звука.Я на 100% уверен, что файл 44.1 кГц, и я получаю подтверждение в байте № 24, 25, 26 & 27. На данный момент я не знаю, почему 44.Аудиофайл 1 кГц не воспроизводит синхронизацию, когда каждый образец выталкивается каждые 22.68US (1/(72000000/1633)). И это не немного, это далеко. Я должен установить автоматическую перезагрузку на 1500, чтобы она звучала правильно.

Я измерил микросхемы между прерыванием таймера время от времени, и это правильно около 22US. Так почему же звук замедляется...
Вы подтвердили, если файл моно/стерео и 8/16 битов? Возможно, вы выводите образцы для 2 каналов, которые заставили бы его играть на полгоспи. Похоже, не так, но стоит подтвердить.
У меня есть свободная версия библиотеки TMRPCM, и у меня не было проблем с выводом с то, что казалось правильным скоростью, возможно, на 1 или 2, но не так много, как вы.

Кстати, таймер отсчитывает от 0 до значения перезагрузки, поэтому вам необходимо загрузить ARR за 1 меньше, чем вы рассчитываете. Итак, для 44100 вы хотите (округление до ближайшего целого числа):
(72000000/44100) -1 ~ = 1632
Но это не будет иметь значения, как то, что вы описываете.

Пито
Сб 15 июля 2017 г. 13:36
Ребята, не цитируйте все предыдущие посты, так как потоки будут длиной 10000 км в длину..
Сосредоточьтесь на нескольких словах, чтобы процитировать вместо этого, если это необходимо (редко это)..

victor_pv
Вт 25 июля 2017 г. 11:28
[nicolas_soundforce - Сб 15 июля 2017 г. 13:02] - Хорошо. Я обнаружил, что моя проблема заключалась в том, что SD -карта недостаточно быстра.
Но когда я заполняю массив таким же большим количеством байтов, синие таблетки могут забрать и воспроизвести его обратно, она синхронизируется/в комплекте с перезагрузкой 1633.

Я уже вырубил новую прототипную печатную плату для Bluepill, Pt8211, Filter и Op Amp, а также флэш -чип Winbond.
В Start Up я скопирую все байты данных с SD -карты на Flash -чип, надеюсь, это будет играть красиво и быстро и позволит мне одновременно транслировать 2 канала.

Спасибо всем, что задумались со мной.
У меня есть эскиз, который я часто использую для тестирования библиотечных и основных изменений, и делает следующее без проблем, поэтому библиотека SDFAT должна быть достаточно быстрой, насколько вы используете буфер разумного размера:
-Читать 8bit/16bit Mono/Stereo WAV -файлы из SDCARD с SDFAT (с помощью DMA)
-Воспроизведение его обратно с ШИМ на 1/2 каналах таймера с прерыванием со скоростью частоты образца WAV или с передачами DMA на таймер.
-Отображает некоторую информацию в LCD SPI, ILI9163
-Отображает вращающийся куб на экране, я забыл с какой частотой кадров.
-Отображает общее время процессора %, используемое всем вышеперечисленным. Это колеблется в зависимости от WAV (8/16bit и моно/стерео), и использую ли я прерывания таймера, или DMA.

Я запустил вышеизложенное в картах класса 4, и я также считаю, что класс 2 также.

Независимо от того, использую ли я прерывания таймера для загрузки 1 образец за раз, или использую DMA для загрузки образцов из оперативной памяти в каналы таймера, в процессоре есть достаточно времени, чтобы сделать все вышеперечисленное и иметь левые циклы.
Библиотека SDFAT работает лучше всего с буфером по меньшей мере 512 баллов, так как это размер блока. Чтение меньше, чем это означает, что все равно придется читать 1 полный блок.
Использование DMA как можно больше экономит много времени процессора.
Также я запускаю вышеизложенное в RTO, но использую один буфер, поэтому перезагрузка от SDFAT в буфер должен завершить за время между 2 образцами, и я не заметил никакого щелчка или замораживания в звуке или вращающемся кубическом дисплее.

Если вы используете двойную буферизацию, чтобы отделить чтение SDFAT от воспроизведения образцов, вы сможете избежать любого щелчка, поскольку в этом случае SDFAT будет иметь все время во время игры 1 буфера, чтобы перезагрузить другой буфер. Но, честно говоря, я думаю, что должно быть что -то еще, что приводит к щелчке, так как я могу перезагрузить 512bytes в своем буфере по цене 44 кГц.

nicolas_soundforce
Чт, 3 августа 2017 г., 10:04
[victor_pv - Вт 25 июля 2017 г. 11:28 вечера] - У меня есть эскиз, который я часто использую для тестирования библиотечных и основных изменений, и делает следующее без проблем, поэтому библиотека SDFAT должна быть достаточно быстрой, насколько вы используете буфер разумного размера:
-Читать 8bit/16bit Mono/Stereo WAV -файлы из SDCARD с SDFAT (с помощью DMA)
-Воспроизведение его обратно с ШИМ на 1/2 каналах таймера с прерыванием со скоростью частоты образца WAV или с передачами DMA на таймер.
-Отображает некоторую информацию в LCD SPI, ILI9163
-Отображает вращающийся куб на экране, я забыл с какой частотой кадров.
-Отображает общее время процессора %, используемое всем вышеперечисленным. Это колеблется в зависимости от WAV (8/16bit и моно/стерео), и использую ли я прерывания таймера, или DMA.

Я запустил вышеизложенное в картах класса 4, и я также считаю, что класс 2 также.

Независимо от того, использую ли я прерывания таймера для загрузки 1 образец за раз, или использую DMA для загрузки образцов из оперативной памяти в каналы таймера, в процессоре есть достаточно времени, чтобы сделать все вышеперечисленное и иметь левые циклы.
Библиотека SDFAT работает лучше всего с буфером по меньшей мере 512 баллов, так как это размер блока. Чтение меньше, чем это означает, что все равно придется читать 1 полный блок.
Использование DMA как можно больше экономит много времени процессора.
Также я запускаю вышеизложенное в RTO, но использую один буфер, поэтому перезагрузка от SDFAT в буфер должен завершить за время между 2 образцами, и я не заметил никакого щелчка или замораживания в звуке или вращающемся кубическом дисплее.

Если вы используете двойную буферизацию, чтобы отделить чтение SDFAT от воспроизведения образцов, вы сможете избежать любого щелчка, поскольку в этом случае SDFAT будет иметь все время во время игры 1 буфера, чтобы перезагрузить другой буфер. Но, честно говоря, я думаю, что должно быть что -то еще, что приводит к щелчке, так как я могу перезагрузить 512bytes в своем буфере по цене 44 кГц.
Привет, Виктор,

ты прав. Я попробовал разные карты, и не повезло, что это на самом деле не стало лучше. Я могу запустить SDCARD на 36 МГц с помощью SD Fat Library, я могу читать 2 байта в 4/5 США. Я отправляю 2 байта на один канал PT8211 с еще одним 4US. В общей сложности процесс занимает 9US, должно быть достаточно времени, чтобы вписаться в значение таймера 22US. У меня действительно нет кликов, это просто воспроизводит слишком медленно. И я действительно положитель.

Я даже пытался разгонять на 96 МГц и 128 МГц с правильными ценностями прескалера, но это не помогло.

О библиотеке SD FAT я заметил, что #Define USE_STM32F1_DMAC 1 теперь включена в SDSPISTM32F1.CPP. Мне нужно 3948us, чтобы прочитать 512 байт!!! И вы можете сделать это между 2 образцами... Я должен сделать что -то не так.

Я прикрепил свою программу как .Zip, и у вас когда -нибудь было время, чтобы быстро взглянуть, что вы были бы фантастическими...

Я вытаскиваю волосы уже около 2 недель...

Стивестронг
Чт, 3 августа 2017 г., 11:58
Ребята,
Пожалуйста, перестаньте цитировать весь предыдущий пост
Поскольку он становится очень нечитаемым, он просто тратит много места, и я больше не вижу, в чем именно была оригинальная проблема...

victor_pv
Чт, 3 августа 2017 г., 17:17
[nicolas_soundforce - Четверг 3 августа 2017 г. 10:04] -
Привет, Виктор,

ты прав. Я попробовал разные карты, и не повезло, что это на самом деле не стало лучше. Я могу запустить SDCARD на 36 МГц с помощью SD Fat Library, я могу читать 2 байта в 4/5 США. Я отправляю 2 байта на один канал PT8211 с еще одним 4US. В общей сложности процесс занимает 9US, должно быть достаточно времени, чтобы вписаться в значение таймера 22US. У меня действительно нет кликов, это просто воспроизводит слишком медленно. И я действительно положитель.

Я даже пытался разгонять на 96 МГц и 128 МГц с правильными ценностями прескалера, но это не помогло.

О библиотеке SD FAT я заметил, что #Define USE_STM32F1_DMAC 1 теперь включена в SDSPISTM32F1.CPP. Мне нужно 3948us, чтобы прочитать 512 байт!!! И вы можете сделать это между 2 образцами... Я должен сделать что -то не так.

Я прикрепил свою программу как .Zip, и у вас когда -нибудь было время, чтобы быстро взглянуть, что вы были бы фантастическими...

Я вытаскиваю волосы уже около 2 недель...
Основная проблема в том, что вы читаете 2 байта за раз. Это чрезвычайно неэффективно.
Блок SDCARD составляет 512bytes. Все ниже, чем это, уже неэффективно, поскольку вы делаете больше чтений, чем необходимо для достижения 512 байт. Но читать 2 байта за раз действительно экстремально. Я уверен, что у вас еще остается немного оперативной памяти, чтобы использовать как минимум 128 -битный буфер, если возможно, еще больше.
Прочитайте больше байтов в большой буфер, а затем играйте в них 2 в момент времени, если хотите.
Что касается перезагрузки таймера, я не могу проверить его, не увидев воспроизводимые файлы.
Я сделал паршивое преобразование библиотеки TMRPCM и оглядываясь на свои файлы (https: // github.com/vicopropv/arduino_stm ... TMRPCM.CPP) Я использовал 285*5 для 44.100 кГц, стерео 8 бит,
Это будет стоимость перезагрузки 1425.
Как вы упомянули что -то около 44 кГц выше, я думаю, что вы можете проверить с этой ценностью.
Или не могли бы вы объяснить, как вы достигнете значения 1633, которое вы используете для ARR?

Не стесняйтесь смотреть на мой код и одолжить любую часть, которая вам нравится.
С тех пор я сделал несколько копий в моих локальных файлах и использую DMA, поэтому только использование ЦП при перезагрузке буфера. Моя библиотека играет с импульсами ШИМ, но периоды для таймера должны быть такими же.

nicolas_soundforce
Чт, 3 августа 2017 г., 18:53
@Victor, согласно этому документу: http: // www.ул.com/content/ccc/resource/ ... 042534.PDF

Я основал 1633 на расчете: 72 000 000 /1633 = 44090,63
Я хочу отскочить вопрос обратно ;) Каков ваш процесс, чтобы получить 1425 ?

Я изменю программу для чтения буфера 512 и посмотрю, как она идет.

victor_pv
Чт, 3 августа 2017 г., 19:14
[nicolas_soundforce - Четверг 3 августа 2017 г. 18:53] - @Victor, согласно этому документу: http: // www.ул.com/content/ccc/resource/ ... 042534.PDF

Я основал 1633 на расчете: 72 000 000 /1633 = 44090,63
Я хочу отскочить вопрос обратно ;) Каков ваш процесс, чтобы получить 1425 ?

Я изменю программу для чтения буфера 512 и посмотрю, как она идет.
Вы правы, я допустил ошибку, рассчитав, когда я читал код, это 6x285, это было 1710.
Я думаю, что те значения, в которых слегка скорректировались, потому что воспроизведение не звучало правильно с расчетными значениями.
Эта линия и вперед рассчитывали его для любой частоты, я не предварительно расслаивал ее, и был таким же:
https: // github.com/vicopropv/arduino_stm ... м.CPP#L340

Единственное отличие состоит в том, что я далее разделял, что в нескольких циклах генерируют ШИМ с более высокой частотой, чем верхняя частота образца, чтобы уменьшить шум, используя функцию таймеров, но не имеет ничего общего с тем, как вы его используете, поэтому 72000000 /sample_frequency - это то же самое, что и я.

Чтение в буфере определенно улучшит вещи. Также используйте двойную буферизацию, поэтому, хотя ISR играет в 1 буфер, вы можете перезагрузить другой без какого -либо ограничения, чтобы пополнить его в период между 2 образцами.
Даже пара маленьких буферов 2 x 128bytes будет иметь большое значение.

Еще одна вещь. Выньте это из ISR:
Файл1.Читать (BUF1, 2);

В ISR вы должны сбросить данные буфера в порт и использовать флаг, чтобы указать, когда буфер пуст и может быть заполнен, а затем где -то в вашем цикле () предусмотреть проверку этого флага и наполнение пустого буфера, который пусто.
Если вы сохраните чтения в ISR, у вас все равно будут проблемы каждый раз, когда вызов занимает больше времени, чем период между 2 образцами, я думаю, 600us при 44 кГц.

nicolas_soundforce
Пт, 04 августа 2017 г., 21:58
@Victor, спасибо за совет. Рад узнать с моей логикой в ​​период таймера звук.
Идея двойного буфера идеальна. Я могу запустить программу с загрузки буфера № 1 в настройке () и избежать задержки запуска. Если я загружаю буфер № 2 в цикл, он никоим образом не мешает прерываниям таймера ? Хорошо ли, чтобы библиотека SD Fat постоянно прервалась »по таймеру ISR ?

Также просто проверяю, DMA встроен в последнюю версию SD FAT в настоящее время ?

Спасибо за вашу помощь!

nicolas_soundforce
Сб 05 августа 2017 г. 13:17
Виктор!! Это работает! Новая печатная плата и двойной буфер исправили все мои проблемы. Аудио супер гладко при 96 МГц с 2 буферами 512. Хотя он немного запускает синхронизацию, когда пытается синхронизировать его с исходным аудио на компьютере. Скорее всего, потому что выборка FREQ на самом деле 96000000/2175 = 44137 Гц

Для любого, кто пытается сделать это:

Если вы не опечатываете и работаете на уровне 72 МГц, просто используйте 1633 в качестве прескалера.
Я использую DAC PT8211 Cheap 16BITS, но 12 бит MCP4822 также подойдет хорошо.

Timer init (для 44.1K): while (1) { digitalWrite(LED, 1); digitalWrite(LED, 0); }

victor_pv
Сб 05 августа 2017 14:57
@Nicolas, чтобы ответить на некоторые из ваших вопросов.
Последний SDFAT включен DMA для Libmaple Core.
О прерывании этого, я думаю, что во время инициализации карты есть некоторые критические часы времени. Но после этого, поскольку мы используем DMA, требуется небольшая нагрузка на процессор, чтобы читать блоки, и у меня никогда не было проблем с прерывами, если прерывания короткие.
Кроме того, USB -порт и таймер Sycick.
Это одна из причин, чтобы держать ISR настолько коротким, насколько это возможно, не влиять на другой код, который чувствителен к времени, даже другие прерывания, которые могут потребоваться обслуживанием. Что ISR теперь может занять всего 20 или 30 циклов процессора.

Я Gla, вы получили Pt8211, работающий нормально с таймером. Есть еще больше, что вы могли бы сделать с таймером и DMA.
Вы можете установить таймер для запуска запроса DMA в используемом вами канале (канал 1), а DMA выполняет загрузку из буфера в порт SPI.
Я использую его для PWM, но для SPI точно так же. Затем вместо того, чтобы использовать прерывание таймера для каждого образца, вы используете прерывание DMA в конце передачи DMA, которое запускает только один раз каждый раз, когда опустошен буфер.
Таким образом, еще меньше прерываний и нагрузки на процессор, и процессор может делать все остальное между.
Я не знаю, что еще делает ваш эскиз, но если он выполняет какую -то обработку, вы можете получить больше времени процессора для вашего кода, делая это.

nicolas_soundforce
Солнце 06 августа 2017 г., 17:33
Интересный! Мой код не делает ничего другого, кроме как запустить воспроизведение аудиофайлов при прерывании GPIO.

Я думаю, что нашел ваш код с RTOS и экраном ILI9341 в потоке PT8211. Я посмотрю на это.

victor_pv
Пн, 07 августа 2017 2:17
Эта вилка имеет одну из последних версий, хотя я не помню, если я загрузил там самые последние изменения, но определенно должна включать деталь, в которой она устанавливает канал DMA для загрузки значений в 2 регистра канала таймера на каждом событии обновления таймера :
https: // github.com/vicopropv/arduino_stm ... IES/TMRPCM

Поскольку вы играете в стерео с SPI, вам нужно будет настроить его немного по -другому, но не так много. Что -то подобное должно работать (например, для 44100 Гц):

Установить канал таймера - это режим сравнения вывода, а для Flipflip. Вы используете это в качестве штифта WS для PT8211.
Установите ARR таймер на значение, которое производит вдвое больше частоты образцов (88200 Гц) (поэтому он будет производить 2 импульса на интервал, один для левого и один для правого канала).
Установите канал таймера, сравните значение с значением в качестве счетчика таймера AAR. Таким образом, выходной штифт канала будет пролететь вправо в качестве перезагрузки счетчика таймера. Таким образом, выход канала переворачивается от 0 до 1 на половине частоты при перезагрузке счетчика таймера, поэтому получение 44100 Гц.
Затем установите канал DMA, подключенный к событию обновления таймера для выполнения передачи между буфером и регистром SPI CR.
Наконец -то включите генерацию DMA Timer и позвольте таймеру считать.

Многое из этого похоже на то, как мой код TMRPCM работает с таймером, только я делаю перегрузку таймера при 44100 Гц, потому что таймер имеет специальную функцию для генерации 2 запросов DMA одновременно, поэтому я могу загрузить 2 таймер с одним запросом. Но это не работает для порта SPI, потому что периферийное устройство SPI выводит оба байта сразу за другим, а не синхронизировано с выходным сигналом Timer, который необходимо синхронизировать каналы с Pt8211.

victor_pv
Пн, 07 августа 2017 2:19
[nicolas_soundforce - Солнце 06 августа 2017 17:33] - Интересный! Мой код не делает ничего другого, кроме как запустить воспроизведение аудиофайлов при прерывании GPIO.
Если вам не нужно делать что -либо еще со временем процессора, чем воспроизводить файлы WAV, то вам действительно не нужно усложнять свою жизнь с любыми вещами DMA, если вы не хотите делать для развлечения ;)

nicolas_soundforce
Вторник 8 августа 2017 г. 13:23
Да, может быть, я постараюсь узнать, как это работает. Я хотел бы попробовать какой -нибудь аудио DSP, используя ту же доску + ADC. Но это выглядит сложным с точки зрения DMA-Noob. Я могу найти много примеров для библиотеки HAL, но не так много с STM32Duino. Я получил твой пример, мне нужно пройти через это несколько раз.

уходящий бот
Чт, 07 сентября 2017 г., 19:42
[nicolas_soundforce - Сб 05 августа 2017 г. 13:17] -
Для любого, кто пытается сделать это:

Если вы не опечатываете и работаете на уровне 72 МГц, просто используйте 1633 в качестве прескалера.
Я использую DAC PT8211 Cheap 16BITS, но 12 бит MCP4822 также подойдет хорошо.

.....
сэр,

Я пытаюсь использовать пример, который вы опубликовали выше, но с трудом собирают. Есть ли определенные операторы #include, которые мне нужно, чтобы запустить ваш код?

У меня есть SD -карта на SPI 1, STMDuino Bootloader на «синей таблетке» и динамик на TIM1_CH1 и TIM1_CH2.

Дэнниф
Чт, 07 сентября 2017 г., 19:55
Довольно легко.

1. Поместите таймер в режим сравнения выхода. Прерывание включено.

2. Разрабатывать математику. Например, 22.67us - это комбинация 1x 22US и 2x 23US.

3. В вашем ISR, Advance The Output Compare Register с 22US, 23US и 23US. А затем вернуться к 22US, ....

4. Сделанный.

уходящий бот
Чт, 07 сентября 2017 г. 20:39
Спасибо за ответ. Ниже приведен беспорядок, но все, что я пытаюсь сделать, получите ваш пример для компиляции и воспроизведения. Я использую Arduino IDE. Теперь это будет компилироваться с операторами Decable и #include, которые я добавил. У меня есть несжатая 8 -битная, 8 кГц, моно, WAV под названием Song0002.WAV на SD -карту. на SPI 1. простой динамик на PA8 (TIM1_CH1). Я пытаюсь заставить эту волну сыграть.

const uint8_t LED = PA2; void setup() { pinMode(LED, OUTPUT); static volatile uint32_t * const reg = (volatile uint32 * const)&GPIOA->regs->BSRR; __asm ( ".align 4\n" // align code on a 16 bit boundary ); while (1) { *reg = 0b1 << 2 << 16 | 0b0 << 2; *reg = 0b1 << 2 << 16 | 0b1 << 2; } } void loop() { }

Дэнниф
Чт, 07 сентября 2017 г., 23:04
Способ усложнить для меня.

Иди сюдаhttps: // github.com/dannyf00/использование вывода- ... ER/STM32F1 и возьмите соответствующие файлы, скажем, tmr2oc.H, если вы используете TIM2.

Код был бы чем -то вроде этого:
test_snprintf:9: error: 'snprintf' was not declared in this scope

уходящий бот
Пт. 08 сентября 2017 г. 20:39
Спасибо за помощь. Я только начинаю с этого устройства, и я немного потерян из -за того, как эта отличная информация распространяется на этом форуме.

Я думал, что пример, опубликованный Николас. Я верю, что теперь я понимаю, что пример использует внешний ЦАП. Таким образом, в основном основной цикл () отвечает за пополнение каждых 512 байтовых двойных буферов, в то время как прерывание отправляет 2 8-битные данные PCM (с помощью SPI_2.Передача) в ЦАП PT8211. Это делается со скоростью, пропорциональной скорости дискретизации файла wav из информации заголовка файла.


Можно ли использовать ЦАП, который поддерживает I2, чтобы иметь связь DMA «между SDCARD» и DAC для непосредственной загрузки данных PCM? Я полагаю, что Виктор сказал, что новая библиотека SDFAT поддерживает это, а также опубликовала о PT8211.
(ViewTopic.PHP?f = 3&t = 2328&начало = 20#P32520)
(http: // www.STM32duino.com/viewtopic.PHP ... 211#P33300)

Информация распространяется на форуме. Но это швы, такие как Виктор, написал функцию DMA в последнем обновлении TMRPCM LIB. Эта функция может быть извлечена из TMRPCM.CPP и используется в примере Nicolas опубликовано?

Я пытаюсь понять поток сигнала данных из файла WAV в ЦАП с DMA и без него. Используют ли как PT8211, так и SD -карта DMA? Или каким -то образом Pt8211 использует i2s, а SD -карта использует DMA? Или просто сделайте DMA на SD -карте и SPI_2.(передача); к ЦАП?

Приведенный ниже код из примера, размещенного на странице 3 этого потока.
#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) [...] int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); [...] #endif /* !__STRICT_ANSI__ */

nicolas_soundforce
Пт 29 сентября 2017 г. 10:44
Дорогой "уходящий бот",

Моя программа не полагается на TMRPCM. Он просто читает волновой файл с SD -карты и отправляет байты на PT8211.
Программа сделана для 16 бит 44.1 кГц файлы. Вам нужно изменить его, чтобы сделать воспроизведение 8 бит 8 кГц.

Может быть, сначала забудьте о DMA, вам это действительно не нужно, особенно для файлов 8 кГц.

Удачи!

ВХОД & ВЫХОД

STM32Duino - Вопросы архитектуры