Посмотрите а сторону PIC18 и модуля NCO - вот некоторый ответ от ИИ --------------------------------------------
---------------------------------------------
Да, ваша идея абсолютно верна, и она является классическим методом борьбы с неопределённостью начальной фазы в DDS/NCO.
Запись половины максимального значения в аккумулятор — это,
по сути, установка начального фазового сдвига в 180°, что гарантирует предсказуемость первого шага.
🎯 Почему ваше решение работает Проблема, которую вы описали, называется неопределённостью начальной фазы.
Когда частота равна нулю, аккумулятор «заморожен» в каком-то состоянии, которое вы не контролировали.
При подаче частоты, скажем, 1, аккумулятор начнёт прибавлять это значение к текущему.
Если он был в 0, то первый переход произойдёт почти сразу (через 2^N / 1 тактов).
Если он был близок к максимуму, переход произойдёт почти мгновенно, но «в другую сторону» (через переполнение).
Запись 0x8000 (половина диапазона) в аккумулятор перед стартом делает начальную фазу детерминированной.
Теперь вы точно знаете, что для достижения нуля или максимума потребуется ровно половина диапазона счёта.
Это превращает недетерминированную задержку в детерминированную, которую можно либо предсказать, либо скомпенсировать в алгоритме.
📌 Как это реализовать на PIC18F27Q84 (NCO) Модуль NCO в PIC18F27Q84 — это аппаратный периферийный модуль, а не программный DDS.
У него есть свои особенности.
Регистры NCO: Модуль имеет регистры для частоты (NCOxINCL) и регистр для начального значения аккумулятора (NCOxACCL и NCOxACCH).
Ваш алгоритм действий:
Установите частоту в NCOxINCL равной нулю (или оставьте как есть).
Перед запуском или перед подачей ненулевой частоты запишите 0x8000 в NCOxACCL и 0x00 (или старшую часть) в NCOxACCH.
Это установит аккумулятор в середину диапазона.
Подайте новое значение частоты в NCOxINCL.
Теперь первый выходной импульс (или изменение состояния выхода) произойдёт через строго определённое количество тактов,
которое зависит только от поданной частоты и известного начального состояния.
⚠️ Что нужно учесть
Разрядность: В PIC18F27Q84 модуль NCO обычно 20-битный (проверьте точную разрядность в вашем даташите).
«Половина» — это 0x80000 для 20 бит, но в 8-битных регистрах это нужно записывать побайтово.
Мертвое время на запись: Сам факт записи в регистры через шину (SPI или внутреннюю) занимает время.
Если вам нужна абсолютная детерминированность, запись фазы и запись частоты должны быть выполнены либо
в разные моменты (сначала фаза, потом частота), либо учтено время этой записи.
Аппаратный NCO vs Программный DDS: Если вы пишете программный DDS в таймере прерывания,
то ваше решение с записью половины работает идеально.
Для аппаратного NCO это работает так же, но нужно помнить, что запись в регистры NCO может быть не мгновенной и зависеть от тактовой частоты периферии.
💎 Итог Ваше решение — правильный инженерный подход.
Оно не делает задержку нулевой, но делает её предсказуемой и постоянной.
Это именно то, что обычно требуется в системах, где важна не столько скорость,
сколько стабильность фазы и детерминизм.
Для реализации на PIC18F27Q84 просто добавьте в код инициализации NCO предварительную запись
половины диапазона в регистры аккумулятора NCOxACCx перед стартом генерации.