Увеличение количества цифровых выходов

Buldakov
Offline
Зарегистрирован: 17.01.2016

Необходимо с выхода Arduino получить 16 цифровых выходов с синхронной передачей информации на выход. Выходы планируется подавать на 16 битный параллельный ЦАП типа PCM54. Используется 8 выходов Arduino. Планируется использовать 4 восьмиразрядных регистра. Сначала байт данных пишется в 1 регистр. Затем байт пишется во второй регистр. Затем одновременно из 1 и 2 регистров пишется в 3 и 4 регистры. Получается довольно много микросхем для пайки.

Посоветуйте какой нибудь готовый модуль из китая. Модуль на микросхеме MCP23017. Не проходит по быстродействию. Частота изменения 16 битного слова около 400 кгц.

rkit
Offline
Зарегистрирован: 23.11.2016

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

b707
Offline
Зарегистрирован: 26.05.2017

Buldakov пишет:

Необходимо с выхода Arduino получить 16 цифровых выходов с синхронной передачей информации на выход.

Можно использовать 2 полных порта Ардуино Мега. Если писать половину 16битного слова сразу в целый порт - получится примерно настолько же "одновременно", как в описанном вами варианте с 4-мя регистрами.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

74HC595  2 штуки.   И всем одновременно подать OE.

Ну а скорости на SPI предостаточно......

Buldakov
Offline
Зарегистрирован: 17.01.2016

rkit пишет:

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

Есть не последовательный , а параллельный выход 8 разрядов. Микросхемы последовательного ЦАП не дадут такого быстродействия. Частота опроса будет около 8 мгц. а еще надо туда данные писать. И данные должны писаться в ЦАП с маленьким джитером. Таймер контроллера это обеспечить не сможет.

Если писать половину 16 битного слова сразу в целый порт - то тоже ничего не получится. поскольку между старшим и младшим байтами будет задержка порядка 1 - 2 тактов частоты и она будет периодически случайным образом меняться. Хотя этот вариант лучше, поскольку не надо будет 4 регистра, а достаточно будет только двух.

b707
Offline
Зарегистрирован: 26.05.2017

Buldakov пишет:

Если писать половину 16 битного слова сразу в целый порт - то тоже ничего не получится. поскольку между старшим и младшим байтами будет задержка порядка 1 - 2 тактов частоты

Можно взять плату super blue pill STM32 - у нее в отличии от обычной bluepill выведены на пины два полных 16-битных порта , так что теоретически можно выводить одновременно сразу 16 бит. Да и побыстрее она будет

rkit
Offline
Зарегистрирован: 23.11.2016

Buldakov пишет:

Есть не последовательный , а параллельный выход 8 разрядов. Микросхемы последовательного ЦАП не дадут такого быстродействия. Частота опроса будет около 8 мгц. а еще надо туда данные писать. И данные должны писаться в ЦАП с маленьким джитером. Таймер контроллера это обеспечить не сможет.

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

Реальный ватник
Offline
Зарегистрирован: 02.12.2019

Используйте PCA9555. Работает по квадратной шине (I2C), на выходе получаете параллельный 16-ти битный код. Поддеживает 400kHz I2C. У китайца стоит недорого.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Спасибо. Классная микросхема. Не знал о ней. Только одно маленькое замечание. 400 кГц надо получить с разрядностью 16 бит. Итого по шине I2C будет около 7 мГц.

Но похоже выход найден. Попробую пойти другим путем. Использовать парочку W27C020 вместо arduino. А  arduino будет только управлять этими ПЗУ.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov, на обычной дуине вы не вытяните  400 16-битных килосемплов ни при каком варианте.  МК же помимо вывода в порт нужно будет ещё  чем-то заниматься?   stm32 из #5  самый разумный вариант. И обязательно через DMA выводить.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Вариант из 5 поста довольно сложно программировать.

А вопросом задался получить из Arduino управление внешним ЦАП для генератора. Если использовать 16 бит ЦАП при частоте 400 кГц возможно получить достаточно хороший синус с частотой 1кГц. Но если ограничить синусоиду по времени из 256 тактов то возможно сделать простой дешифратор из 8 бит в 16 бит.

Ну примерно планирую так:

Делаем генератор на SI5351 с изменяемой частотой тактирования . Далее этот сигнал с генератора заводим на прерывание Arduino. По этому прерыванию Arduino выдает 8 битный код угла фазы синуса, который преобразуется дешифратором в 16 битный код уровня ЦАП. Затем угол фазы увеличивается и при следующем прерывании все повторяется. Хотя в данном случае Arduino будет использоваться только для управления SI5351 и как обычный счетчик. В принципе ее можно заменить на счетчик типа CD4040

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov, мне кажется вы опять не учитываете нагрузку МК. Предположим вам нужно получить 1 кГц синус, состоящего из 256 отсчётов. Соответственно тактировать нужно со скоростью 256 000 Гц, это уже достаточно что б забить прерываниями весь ресурс мк.  Ничем другим он уже заниматься не сможет, а это всего лишь 1кГц.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Похоже что это так. Значит придется заменить контроллер двоичным счетчиком. У него быстродействие будет больше. И остается что контроллер будет управлять только генератором Si5351. Просто в таком варианте придется использовать более сложный дешифратор. А я уже его заказал. Придется заказывать новый.

Logik
Offline
Зарегистрирован: 05.08.2014

dimax пишет:

Buldakov, на обычной дуине вы не вытяните  400 16-битных килосемплов ни при каком варианте.  

Та ладно! там жеж целых 40 тактов. Паралельно в порт 8бит, дернули защелку регистра, вторые 8бит в порт, защелку второго регистра. Тактов 15. Все в прерывании таймера, обработчик пишем на чистом ассемблере. Неизвестно правда откуда эти байты брать, ТС любезно от таких "мелочей" нас оберегает. Но в простейшем случае реально. Остальные прерывания отключаем, пару тактов останется на основной код. Так что Buldakov вытянет, если асм выучит.

dimax пишет:

 МК же помимо вывода в порт нужно будет ещё  чем-то заниматься?   

А ХЗ. Не пишет же.

ПС. ситуация - как всегда. Либо писать хорошо, либо наращивать железо.

 

Buldakov
Offline
Зарегистрирован: 17.01.2016

Вроде уже все написал. Ардуино будет управлять только SI5351. И при запуске будет 1 раз писать в нее стартовую частоту. Больше ничего делать не надо. Только генерить фиксированную частоту.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov, т.е. вы хотите массив синуса хранить в ПЗУ 27C0X, и перебирать его адресную шину обычной логикой, управляемой от si5351? Стоит ещё раз всё просчитать, возможно так будет быстрее меги, но всё равно медленнее STM32.  ПЗУ-шки эти древние, и быстродействием  совсем не блещут.  Обойти по скорости  стм32 могут только спец.чипы dds-синтезаторов ad98** .

Гриша
Offline
Зарегистрирован: 27.04.2014

я вот только не понял.. нужен синус с фиксированной частотой 400 кГц и для этого такой геморой? кварцевый генератор на 400 кГц и П-контур на нормальный ОУ - пайки минимум.  

А осциллограф нужен в любом случае...

глянул в инете инфу мдя... П-контур просто так не посчитаешь - редко кто пользует... проще полосовой фильтр или резонансный контур посчитать. 

Buldakov
Offline
Зарегистрирован: 17.01.2016

dimax пишет:

Buldakov, т.е. вы хотите массив синуса хранить в ПЗУ 27C0X, и перебирать его адресную шину обычной логикой, управляемой от si5351? Стоит ещё раз всё просчитать, возможно так будет быстрее меги, но всё равно медленнее STM32.  ПЗУ-шки эти древние, и быстродействием  совсем не блещут.  Обойти по скорости  стм32 могут только спец.чипы dds-синтезаторов ad98** .

Да хочу хранить в ПЗУ. ПЗУ типа 573рф4 действительно медленные. Частота около 2 мГц. Если взять w27c512 то у них время задержки около 45 нс. Если взять 27с512 то около 35 нс. Итого частота около 20 мГц и выше. DDS типа AD98** имеют периодическое обрезание фазы. И типа каждые 100 тактов синусоиды будет выброс.

Синус с частотой 400кгц не нужен. Нужен синус с частотой 1 кгц. Уровень гармоник на этой частоте нужен  минус 130-140 ДБ. Звуковушки с такими параметрами очень редкие и дорогие.

nik182
Offline
Зарегистрирован: 04.05.2015

И что? Сможете подобрать резисторы для ЦАП что бы обеспечить  130-140 ДБ ?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov пишет:

 Если взять 27с512 то около 35 нс. Итого частота около 20 мГц и выше.

35нс это время отклика на команды. Но что бы выдать семпл нужно пройти целую церемонию команд и пауз между ними. Я не берусь сейчас озвучивать конкретные цифры, ибо не знаю их.  Просто советую вам всё просчитать по даташиту перед тем как что либо начинать.

Buldakov пишет:

DDS типа AD98** имеют периодическое обрезание фазы. И типа каждые 100 тактов синусоиды будет выброс.

Не встречал подобной инфы.  У меня самодельный прибор NWT-7 на ad9851, никаких выбросов не замечал.

SLKH
Offline
Зарегистрирован: 17.08.2015

nik182 пишет:

И что? Сможете подобрать резисторы для ЦАП что бы обеспечить  130-140 ДБ ?

и измерить полученный уровень гармоник ? 

SLKH
Offline
Зарегистрирован: 17.08.2015

Гриша пишет:

я вот только не понял.. нужен синус с фиксированной частотой 400 кГц и для этого такой геморой? кварцевый генератор на 400 кГц и П-контур на нормальный ОУ - пайки минимум.  

А осциллограф нужен в любом случае...

глянул в инете инфу мдя... П-контур просто так не посчитаешь - редко кто пользует... проще полосовой фильтр или резонансный контур посчитать. 

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

("И как бы между прочим сказала невпопад")  в -140 db я не верю. 

 

Реальный ватник
Offline
Зарегистрирован: 02.12.2019

Buldakov пишет:

Спасибо. Классная микросхема. Не знал о ней. Только одно маленькое замечание. 400 кГц надо получить с разрядностью 16 бит. Итого по шине I2C будет около 7 мГц.

друг любезный, 400 kHz это на линии SCL. Кроме того, 400 kHz это 2,5 мкс. РСМ54 это просто ЦАП диапазона 20-20000 Hz. Мне просто непонятно зачем Вам менять параллельный код каждые 2,5 мкс, если минимальное время установления значения на выходе РСМ составляет 3 мкс. Вы, возможно, что-то не правильно поняли. Не изобретайте колесо, попробуйте РСА9555 и у Вас получится, наверняка.

SLKH
Offline
Зарегистрирован: 17.08.2015
Buldakov
Offline
Зарегистрирован: 17.01.2016

По поводу DDS. Хочу сделать что то типа по ссылке

http://ra3ggi.qrz.ru/UZLY/dds.htm

рис 3. Недостаток данной схемы обойти используя генератор на SI5351. на рис 4 приведена схема DDS типа AD98**. Включая и ссылку на плату микросхемы AD9833. Здесь вылезает другая ошибка в виде усечения кода фазы См. ниже по тексту статьи

Усечение кода фазы является внутренней операцией DDS и извне изменить ничего нельзя. Отбрасывание младших битов приводит к возникновению ошибки в представлении фазы. Как следствие, это приводит к появлению погрешности амплитуды при преобразовании фазы в амплитуду, которое имеет место в DDS. Более того, эта погрешность является периодической, так как в зависимости от кода частоты состояния аккумулятора фазы повторяются чаще или реже.

Это приводит к искажениям порядка минус 60 дБ.

По поводу измерения уровня гармоник это не проблема. Гораздо сложнее получить сигнал с таким уровнем.  Звуковушка дает порядка минус 110 дБ и зависит от Цапа. Генератор Виктора дает порядка -150 дБ гармоник.

По поводу 400 кГц. Это частота работы ЦАП, а не на линии SLC.

Buldakov
Offline
Зарегистрирован: 17.01.2016

И в продолжении темы. Допустим я хочу записать 6 бит в разряды со 2 по 7 командой (взято из описания

DDRD = DDRD | B11111100;

PORTD = B10101000; // устанавливает HIGH на цифровых выводах 7,5,3

эти строки понятно. А если я напишу

PORTD = B10101001; // устанавливает HIGH на цифровых выводах 7,5,3,0.Но 0 и 1 бит настроены на текущее состояние и я буду при этом в 0 бит что то пытаться писать.Вроде будет либо писаться не туда , либо совсем ничего не будет писаться. Как лучше поступить в данном случае?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov,  Сколько отсчётов вы хотите на период?   Другими словами какого размера будет таблица синуса в пзу?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov, при команде PORTD= xxx порт полностью перезапишется новым числом.  Что бы что-то не затереть нужны команды '|='  для установки бита  ,  '&='  для снятия

Buldakov
Offline
Зарегистрирован: 17.01.2016

Таблица синуса какого размера будет пока не знаю. Это будет видно только потом.  Частота соответственно какая будет - тоже не знаю. Начну с 16 значений. измерю искажения - затем увеличу таблицу в 2 раза. Посмотрю результат. Я пока не имею понятия на чем остановятся искажения? Есть несколько вариантов: 1 Уровень искажений упадет до уровня шумов ЦАП. 2. Уровень будет выше шумов ЦАП. 3. Уровень будет ниже. 4. Уровень не будет зависить.

nik182
Offline
Зарегистрирован: 04.05.2015

Ступеньки легко считаются. Рисуем чистый синус, рисуем ступеньки ЦАП - отношение разницы площадей к площади синуса  Ваши децибелы. Можно прикинуть сколько надо минимум шагов в идеальном случае.. 

Buldakov
Offline
Зарегистрирован: 17.01.2016

То есть если я правильно понял нужно посчитать определенный интеграл от синуса и от ступенек. И добиться минимальной разницы? Тогда возникает другой вопрос. Если я увеличу частоту квантования по времени при 8 битном ЦАП То гармоники должны по теории уменьшиться? Вроде когда считаешь определенный интеграл численным методом - от числа точек разбиения точность зависит? С математикой я всегда был не очень силен.

И если это так, то наверное лучше взять какой нибудь контроллер типа STM32F103C8T6

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nik182 пишет:

Можно прикинуть сколько надо минимум шагов в идеальном случае.. 

Профессиональные генераторы дают в синусе до 128килоточек на период :) Интересно, есть способ математически рассчитать сколько точек нужно для -140db ?

Гриша
Offline
Зарегистрирован: 27.04.2014

Buldakov пишет:

Частота изменения 16 битного слова около 400 кгц.

Buldakov пишет:

По поводу 400 кГц. Это частота работы ЦАП, а не на линии SLC.

....

А можно повторить для тех, кто в танке?! синус с фиксированной частотой? Я так ничего и не понял про чАстоту конечного продукта, за-то про чИстоту целая поэма.

какие требования к выходному сигналу: размах, чАстота... про чИстоту слышали...

UPD. И еще в довесок. Параллельный ЦАП это такая песня, что не вышептать... посчитайте сперва требования к сопротивлениям для 16 бит ЦАП.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Гриша пишет:

я вот только не понял.. нужен синус с фиксированной частотой 400 кГц и для этого такой геморой? кварцевый генератор на 400 кГц и П-контур на нормальный ОУ - пайки минимум.  

А осциллограф нужен в любом случае...

глянул в инете инфу мдя... П-контур просто так не посчитаешь - редко кто пользует... проще полосовой фильтр или резонансный контур посчитать. 

и чего его там считать-то, Бунимович поможет )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

nik182 пишет:

Можно прикинуть сколько надо минимум шагов в идеальном случае.. 

Профессиональные генераторы дают в синусе до 128килоточек на период :) Интересно, есть способ математически рассчитать сколько точек нужно для -140db ?

это настолько большая величина, что не знаю, чем померить можно, в моё время эксплуатационника, максимум был -130 )))

nik182
Offline
Зарегистрирован: 04.05.2015

Формула оказалась совсем простая. Посчитал численными методами, там конечно свои ошибки округления, но получилось что на четверть периода 16, 64, 1024 и 128000 точек дают гармоник 21, 33, 57 и 99 дБ. Как получить 130 дБ загадка. 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov пишет:

По поводу измерения уровня гармоник это не проблема. Гораздо сложнее получить сигнал с таким уровнем.  Звуковушка дает порядка минус 110 дБ и зависит от Цапа. Генератор Виктора дает порядка -150 дБ гармоник.

А можно поподробнее про то, как вы сможете измерить такой уровень гармоник,  и что это за "генератор Виктора"?

SLKH
Offline
Зарегистрирован: 17.08.2015

Гриша пишет:

Buldakov пишет:

Частота изменения 16 битного слова около 400 кгц.

Buldakov пишет:

По поводу 400 кГц. Это частота работы ЦАП, а не на линии SLC.

....

А можно повторить для тех, кто в танке?! синус с фиксированной частотой? Я так ничего и не понял про чАстоту конечного продукта, за-то про чИстоту целая поэма.

какие требования к выходному сигналу: размах, чАстота... про чИстоту слышали...

UPD. И еще в довесок. Параллельный ЦАП это такая песня, что не вышептать... посчитайте сперва требования к сопротивлениям для 16 бит ЦАП.

 

Насколько я понимаю, это из области "ТёплыйЛЗ", а там метрологические параметры не особо приветствуются. Гораздо важнее чистота меди в квартирной проводке 220 вольт.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Вот ссылка на народный генератор. Схема генератора Виктора в шапке.

https://www.audio-perfection.com/forum/showthread.php?tid=231

Здесь как установить и настроить программу для измерений искажений. Программа SpectraPlus. В качестве примера используется EMU0204.

http://forum.vegalab.ru/showthread.php?t=70151

Программа для расчета фильтра. Правда старая версия. Считает параметры для пассивных и активных фильтров. Можно задать тип и класс фильтра.

http://www.cqham.ru/fs8.htm

 

Logik
Offline
Зарегистрирован: 05.08.2014

nik182 пишет:

Формула оказалась совсем простая. Посчитал численными методами, там конечно свои ошибки округления, но получилось что на четверть периода 16, 64, 1024 и 128000 точек дают гармоник 21, 33, 57 и 99 дБ. Как получить 130 дБ загадка. 

Да ктоже ступеньки с ЦАПа сразу берет. Фильтронуть надо. Фишка в том что при высокой частоте дискретизации фильтры простые аналоговые низких порядков отлично справятся. Можете прикинуть результат грубо зная крутизну дБ/октава и число октав.

nik182
Offline
Зарегистрирован: 04.05.2015

Конечно надо ставить выходные фильтры. Простой RC даёт +6 дБ. Если подобран под частоту.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Если я хочу записать байт в ЦАП. Какие линии платы Arduino nano лучше использовать и для каких бит? Линии А4 и А5 будут заняты для SI5351. И будет занят вход по прерыванию 0.

Пока собрал для проверки 8 битный ЦАП на 572ПА1 и на счетчиках 555ие19. Пилу вроде рисует. Программу примерно хочу организовать так: Настраиваем и запускаем генератор. По фронту этого сигнала происходит запись информации в регистр 555ир27 для хранения и передачи в ЦАП. По этому же сигналу вызывается INT 0 и данные пишутся в порт Arduino. По следующему фронту они опять запишутся в 555ир27.

Такой схемой достигается синхронная запись информации в ЦАП. Задержки в тактах вызова прерывания в данном случае не влияют . Максимальное быстродействие будет определяться только скоростью работы прерывания.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Buldakov пишет:

Если я хочу записать байт в ЦАП. Какие линии платы Arduino nano лучше использовать и для каких бит? Линии А4 и А5 будут заняты для SI5351. И будет занят вход по прерыванию 0.

Пока собрал для проверки 8 битный ЦАП на 572ПА1 и на счетчиках 555ие19. Пилу вроде рисует. Программу примерно хочу организовать так: Настраиваем и запускаем генератор. По фронту этого сигнала происходит запись информации в регистр 555ир27 для хранения и передачи в ЦАП. По этому же сигналу вызывается INT 0 и данные пишутся в порт Arduino. По следующему фронту они опять запишутся в 555ир27.

Такой схемой достигается синхронная запись информации в ЦАП. Задержки в тактах вызова прерывания в данном случае не влияют . Максимальное быстродействие будет определяться только скоростью работы прерывания.

Если мы говорим об ардуине на базе Атмеги 328 (uno, nano etc) то использование любых других пинов кроме D0-D7 приведет к тому, что байт придется писать в два захода, как минимум.  

Buldakov
Offline
Зарегистрирован: 17.01.2016

Значит тогда возникает другой вопрос. Как перенаправить INT0 с порта PD2? на другой вывод

Green
Offline
Зарегистрирован: 01.10.2015

Никак. Использовать PCINT.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Решил для начала проверить быстродействие прерывания. Получилось что то около 340 кГц максимум. После этого прерывание не успевает отрабатывать. Вот код которым проверял быстродействие:

//------------------------------------------------------------------------------------//
#include "CyberLib.h"                                                                 //
#include "si5351.h"                                                                   //
#include "Wire.h"                                                                     //
Si5351 si5351;                                                                        //
//------------------------------------------------------------------------------------//
double        freq         = 340000.0;          //стартовая частота Гц                //
//------------------------------------------------------------------------------------//
bool          i2c_found;                                                              //
unsigned long vfo;                                                                    //
bool k1=0;                                                                            //
//------------------------------------------------------------------------------------//
void setup()                                                                          //
{                                                                                     //
vfo= freq*10;                                                                         //
//------------------------------------------------------------------------------------//
i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);//initialize the Si5351        //
si5351.set_correction(22800, SI5351_PLL_INPUT_XO);     //корректировка частоты 25 MHz //
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);                                        //
//------------------------------------------------------------------------------------//
si5351.set_freq((vfo*SI5351_FREQ_MULT)/10, SI5351_CLK0);                              //
si5351.set_freq((vfo*SI5351_FREQ_MULT)/10, SI5351_CLK1);                              //
si5351.set_freq((vfo*SI5351_FREQ_MULT)/10, SI5351_CLK2);                              //
//------------------------------------------------------------------------------------//
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_8MA);//set Out to 2MA, 4MA, 6MA or 8MA //
si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA);//set Out to 2MA, 4MA, 6MA or 8MA //
si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA);//set Out to 2MA, 4MA, 6MA or 8MA //
//------------------------------------------------------------------------------------//
si5351.output_enable(SI5351_CLK0,1); //Включаем  0 выход                              //
si5351.output_enable(SI5351_CLK1,0); //Выключаем 1 выход                              //
si5351.output_enable(SI5351_CLK2,0); //Выключаем 2 выход                              //
//---Настройка шины на вывод----------------------------------------------------------//
pinMode (13, OUTPUT);                //Назначаем вывод 13 в режим вывода              //
//---Настройка таймера 0--------------------------------------------------------------//
TCCR0B=0;TIMSK0=0;                   //Отключаем таймер 0                             //
//---Настройка прерывания int 0-------------------------------------------------------//
pinMode     (2, INPUT);              //Назначаем вывод 2 в режим ввода                //
digitalWrite(2, HIGH);               //Включаем подтягивающий резистор                //
EIMSK   =  (1<<INT0);                //разрешение прерываний int 0                    //
EICRA   =  (1<<ISC01) | (1<<ISC00);  //настройка прерывания int 0 по фронту импульса  //
//------------------------------------------------------------------------------------//
}                                                                                     //
//---Прерывание по int 0--------------------------------------------------------------//
ISR (INT0_vect){                                                                      //
if (k1==0) D13_Low;                                                                   //
if (k1==1) D13_High;                                                                  //
if (k1==0) k1=1;else k1=0;                                                            //
}                                                                                     //
//------------------------------------------------------------------------------------//
void loop()
{
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Buldakov пишет:

Решил для начала проверить быстродействие прерывания. Получилось что то около 340 кГц максимум. После этого прерывание не успевает отрабатывать. Вот код которым проверял быстродействие:

 

Что бы добиться более высокой частоты надо писать обработчик прерывания на ассемблере. Но проще взять STM32 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Buldakov пишет:

Решил для начала проверить быстродействие прерывания. Получилось что то около 340 кГц максимум. После этого прерывание не успевает отрабатывать.

И это МК ещё не чем другим не занят. Если вы будете пересылать байты в порт, то скорость упадёт ещё раз в 100, вернее будут идти только прерывания, ничего другого мк делать не будет.  stm32 и  DMA только в этом спасение.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Программу вроде написал. Выдает 1 кГц. количество отсчетов около 180000 в секунду.

Результат не очень. Синус по осцилографу довольно красивый. По гармоникам - ужас. Уровень второй гармоники -25 дБ. Уровень 3, 4, 5,6,7  минус 15 дБ.

Тему думаю можно закрывать.

//--08.12.2019------------------------------------------------------------------------//
#include "arduino.h"                                                                  //
#include "si5351.h"                                                                   //
Si5351 si5351;                                                                        //
//------------------------------------------------------------------------------------//
double f_gen = 1000.0;                                                                //
int    n     = 40;                             // Количество точек квантования = Пи/2 //
int    c     = 256;                            //Разрядность ЦАП                      //
//------------------------------------------------------------------------------------//
bool          i2c_found;                                                              //
bool          b7,b6,b5,b4,b3,b2,b1,b0;                                                //
byte          port_b[256],port_d[256];                                                //
int           i,out;                                                                  //
int           a1,ka,u,z,j;                                                            //
unsigned long vfo;                                                                    //
double        pid,b,y,z3,freq;                                                        //
//------------------------------------------------------------------------------------//
//  Эти две строки пишем в начале файла                                               //
static int serial_fputchar(const char ch,FILE *stream) { Serial.print(ch); return ch;}//
static FILE *serial_stream = fdevopen(serial_fputchar, NULL);                         //
//------------------------------------------------------------------------------------//
void setup()                                                                          //
{                                                                                     //
freq=n*4*f_gen;                                                                       //
vfo= freq*10;                                                                         //
//------------------------------------------------------------------------------------//
i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);//initialize the Si5351        //
si5351.set_correction(22800, SI5351_PLL_INPUT_XO);     //корректировка частоты 25 MHz //
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);                                        //
//------------------------------------------------------------------------------------//
si5351.set_freq((vfo*SI5351_FREQ_MULT)/10, SI5351_CLK0);                              //
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA);//set Out to 2MA, 4MA, 6MA or 8MA //
si5351.output_enable(SI5351_CLK0,1); //Включаем  0 выход                              //
//---Настройка шины на вывод----------------------------------------------------------//
pinMode (13, OUTPUT);                //Назначаем вывод 13 в режим вывода              //
pinMode (12, OUTPUT);                //Назначаем вывод 12 в режим вывода              //
pinMode (11, OUTPUT);                //Назначаем вывод 11 в режим вывода              //
pinMode (10, OUTPUT);                //Назначаем вывод 10 в режим вывода              //
pinMode ( 9, OUTPUT);                //Назначаем вывод  9 в режим вывода              //
pinMode ( 8, OUTPUT);                //Назначаем вывод  8 в режим вывода              //
pinMode ( 7, OUTPUT);                //Назначаем вывод  7 в режим вывода              //
pinMode ( 6, OUTPUT);                //Назначаем вывод  6 в режим вывода              //
//------------------------------------------------------------------------------------//
stdout = serial_stream; // эта строка первая в setup для инициализации Serial         //
Serial.begin(9600);// Start serial                                                    //
//------------------------------------------------------------------------------------//
pid = 3.1415926;                                                                      //
a1 = (c - 2) / 2;                                                                     //
ka = a1 - 2;                                                                          //
u = n * 4;            //Количество точек квантования на всей синусоиде = 2*Пи         //
//------------------------------------------------------------------------------------//
for (i=0;i<=(u - 1);i=i+1)                                                            //
{                                                                                     //
b = (2 * pid * i) / u;                                                                //
y = a1 + ka * sin(b);                                                                 //
z = round(y);                                                                         //
z3 = abs(z - y);                                                                      //
//------------------------------------------------------------------------------------//
b7 = z & 0b10000000;                                                                  //
b6 = z & 0b01000000;                                                                  //
b5 = z & 0b00100000;                                                                  //
b4 = z & 0b00010000;                                                                  //
b3 = z & 0b00001000;                                                                  //
b2 = z & 0b00000100;                                                                  //
b1 = z & 0b00000010;                                                                  //
b0 = z & 0b00000001;                                                                  //
out=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0*1;                                     //
//------------------------------------------------------------------------------------//
printf("%03d", i );Serial.print("  ");                                                //
Serial.print(y   );Serial.print("  ");                                                //
Serial.print(z3  );Serial.print("  ");                                                //
printf("%03d",z  );Serial.print("  ");                                                //
printf("%02X",z  );Serial.print("  ");                                                //
printf("%02X",out);Serial.print("  ");                                                //
Serial.print  (b7);                                                                   //
Serial.print  (b6);                                                                   //
Serial.print  (b5);                                                                   //
Serial.print  (b4);                                                                   //
Serial.print  (b3);                                                                   //
Serial.print  (b2);                                                                   //
Serial.print  (b1);                                                                   //
Serial.println(b0);                                                                   //
//------------------------------------------------------------------------------------//
bitWrite(port_b[i], 5, b7);                                                           //
bitWrite(port_b[i], 4, b6);                                                           //
bitWrite(port_b[i], 3, b5);                                                           //
bitWrite(port_b[i], 2, b4);                                                           //
bitWrite(port_b[i], 1, b3);                                                           //
bitWrite(port_b[i], 0, b2);                                                           //
bitWrite(port_d[i], 7, b1);                                                           //
bitWrite(port_d[i], 6, b0);                                                           //
//------------------------------------------------------------------------------------//
}   //конец i                                                                         //
//---Настройка таймера 0--------------------------------------------------------------//
TCCR0B=0;TIMSK0=0;                   //Отключаем таймер 0                             //
//---Настройка прерывания int 0-------------------------------------------------------//
pinMode     (2, INPUT);              //Назначаем вывод 2 в режим ввода                //
digitalWrite(2, HIGH);               //Включаем подтягивающий резистор                //
EIMSK   =  (1<<INT0);                //разрешение прерываний int 0                    //
EICRA   =  (1<<ISC01) | (1<<ISC00);  //настройка прерывания int 0 по фронту импульса  //
//------------------------------------------------------------------------------------//
}                                                                                     //
//---Прерывание по int 0--------------------------------------------------------------//
ISR (INT0_vect){                                                                      //
//------------------------------------------------------------------------------------//
PORTB = port_b[i];                                                                    //
PORTD = port_d[i];                                                                    //
i=i+1;                                                                                //
if (i>=u) i=0;                                                                        //
}                                                                                     //
//------------------------------------------------------------------------------------//
void loop()                                                                           //
{                                                                                     //
}                                                                                     //
//------------------------------------------------------------------------------------//

 

nik182
Offline
Зарегистрирован: 04.05.2015

С расчётом сильно не расходится. 180000 в секунду это 45 на четверть периода. Расчёт 64 на четверть периода дал 33 дБ. Да ещё резисторы кривенькие... Активными фильтрами надо обработать.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Что самое интересное это после фильтра. Резисторов у меня нет. Есть К571ПА1. Поскольку собирал на макетной плате помех было много. Поставил проверить аналоговый генератор. Та же фигня. Похоже дело было в драйверах звуковушки. Ну ладно главное схему опробовал. Придет цап и попробую спаять платку и попробую еще раз.