Для мікроконтролерів і не тільки Алгоритм DDS - синтез точної довільної частоти
| Запис від AZM на субдомені electronics-and-mechanics |
| Всі записи на субдомені: Електроніка та механіка (записки від AZM) |
| Для мікроконтролерів і не тільки: Алгоритм DDS – синтез точної довільної частоти на мікроконтролері (генерація сигналу довільної форми потрібною частотою з точністю до часток герца) |
| Бує так, що потрібно згенерувати частоту 1750 Гц з великою точністю або 254.4 Гц, а тактова частота мікроконтролера 8 МГц і як не поділи 8000000 на 1750 або на 254.4, все те цілого не знайти. Тим гірше, якщо потрібно не просто генерувати частоту, а скажемо синусоїду, виводячи її на найпростіший ЦАП на 5 резисторах. |
На перший погляд здається, що можна отримати з тактової частоти F будь-яку іншу частоту тільки з ряду F/N де N ціле. Якщо ж потрібно генерувати, наприклад, синусоїдальний сигнал, скажімо з 11 точками на коливання, то картина стає ще сумнішою: F/11/N, де знову ж таки N ціле. Простіше кажучи, може здатися, що з 8 МГц ми можемо згенерувати лише прямокутник з частотами: 4МГц; 2,666МГц; 2МГц; 1,6 МГц; 1,333 МГц; . і немає жодної можливості згенерувати наприклад частоту 2212 Гц, адже для цієї частоти N = 3616.636528028933, а найближчі частоти для цілого N будуть: 2212.39 та 2211.78. Для деяких додатків такої точності цілком достатньо, але що робити, якщо нам потрібна точно частота 2212 Гц? Рішення є!
Синтез точної частоти з використанням накопичувача суматора
Що якщо ми будемо не рахувати від 0 до N_дільник, а при досягненні N змінювати стан виходу порту для генерації частоти, а почнемо додавати до якоїсь змінної деяким значенням M і змінюватимемо стан порту щоразу, як ця змінна будедосягати якоїсь великої величини, скажімо, 1875000000? Візьмемо реальний випадок: Таймер викликає переривання 31250 разів на секунду (8000000/256). Якщо ми будемо використовувати рахунок від 0 до N_дільник, то у кращому випадку, у нас є 31250 крок. Якщо ж ми почнемо рахувати від 0 до 1875000000, щоразу додаючи до змінної якесь значення, то у нас є 1875000000 кроків або в 60000 разів більше!
Як приклад наступний код: Іншими словами, додаючи 132720000 до нашої змінної 31250 разів на секунду, ми досягатимемо значення 1875000000 якраз 2212 разів на секунду.
Звичайно, ми можемо вибрати менше максимальне значення, ніж 1875000000 або більше. Чим це число більше, тим вища точність вихідної частоти, що менше, то нижче.
Синтез точної частоти із довільною формою вихідного сигналу
Тепер найцікавіше - виведення сигналу як точної частоти, а й довільної форми (синус, трикутник, пила). Поясню на прикладі, у коді:
Ось так просто. Деякі пояснення: "CounterToGeneratorSignal>>10" це те ж саме що "CounterToGeneratorSignal / 134217728" і відкинути дробову частину, поділ на зрушеннях. Відповідно: "CounterToGeneratorSignal>>1" аналогічно "CounterToGeneratorSignal / 2" "CounterToGeneratorSignal>2" аналогічно "CounterToGeneratorSignal / 4" "CounterToGeneratorSignal / 4" eneratorSignal /8" "CounterToGeneratorSignal>>4" аналогічно "CounterToGeneratorSignal /16" далі, думаю, зрозуміли.
Тобто все працює так: до змінної додається ADD_VAL_TO доти, доки не настане переповнення, воно настане на значенні 4294967296, тобто 4294967295 і далі процес повторюється. Загалом, все те ж, що і вПерший приклад, тільки тут оптимізовано. Якщо розібралися з першим прикладом, то із цим проблем бути не повинно.
Що стосується використання порту C, то щоб отримати з 4 його молодших ніжок ЦАП (цифро-аналоговий перетворювач), потрібно лише зібрати схему:
