Автор Тема: Формирование сигналов (принцип DDS и PWM)  (Прочитано 34859 раз)

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
В инете существует множество проектов, связанных с формированием сигналов произвольной формы - синус, меандр, пила и т.д. только с применением микроконтроллеров . Например   пианино формирование "многоголосной" (поли) синусоиды через ШИМ, а также множество различных генераторов формирующих сигналы по принципу DDS.
Все эти принципы можно реализовать на ФК.  Вот я и подумал, а не сделать ли примеры как для PIC, так и для AVR???, таким образом можно будет сравнить возможности одних и других. Естественно не обойдется без двух-трех строчек на Си и Ассемблере, но я думаю это не вызовет большого неудобства.

Для поиска "синусоида", "синус на AVR", "синус на PIC", "DDS", "Генератор НЧ PIC", "Генератор НЧ AVR", "Генератор НЧ на МК", "синус на микроконтроллере", "AVR DDS signal".

baevnikol

  • Jr. Member
  • **
  • Сообщений: 58
    • Просмотр профиля
Re:Формирование сигналов (через DDS и PWM)
« Ответ #1 : Май 17, 2011, 15:40:09 »
6 Лет назад я собрал частотомер на PIC16F84 и LCD2x16 написал програму на асемблере по самоучителю Кораблева и все работает отлично . В FLOWCODE я много рас пытался чтото сделать и нечего не получается (Разве диодиками поморгать)

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (через DDS и PWM)
« Ответ #2 : Май 17, 2011, 15:45:36 »
baevnikol пишет:
Цитировать
6 Лет назад я собрал частотомер на PIC16F84 и LCD2x16 написал програму на асемблере по самоучителю Кораблева и все работает отлично . В FLOWCODE я много рас пытался чтото сделать и нечего не получается (Разве диодиками поморгать)

Кстати, на форуме есть программа частотомера на PIC16F84, написанная на ФК.
А также есть программа, позволяющая измерять временной интервал с точностью до 10 в минус 7 степени (0,000.000.1).
Ну и в будущем - генератор на АВР (синус, меандр, треугольник...) до 100 КГц

baevnikol

  • Jr. Member
  • **
  • Сообщений: 58
    • Просмотр профиля
Re:Формирование сигналов (через DDS и PWM)
« Ответ #3 : Май 17, 2011, 16:02:27 »
Меня интересует вариант .По примеру P Rroteusa /

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (через DDS и PWM)
« Ответ #4 : Май 17, 2011, 16:10:32 »
baevnikol пишет:
Цитировать
Меня интересует вариант .[/file]

Вариант чего?? Пиши всегда полностью и понятно вопросы...

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (через DDS и PWM)
« Ответ #5 : Май 17, 2011, 20:26:31 »
Мне не хочется описывать теорию о DDS, она известна, и желающие могут с ней ознакомиться любым способом.
Рассмотрение примеров формирования сигналов на МК начнем с ПИКов.
Начну как бы из далека…
Для точного расчета параметров сигнала необходимо знать временные параметры работы МК (циклы, время выполнения команд). Однако, такой подход к построению генератора на ПИКах довольно неудобен при программировании на СИ.
Таким образом, времязадающим элементом должен выступить внутренний таймер МК. Сигналы прерывания от него и будут теми циклами, которые будут определять параметры сигнала (частоту).
Удобным для применения представляется таймер TMR2.
Программа ФК есть блок определяющий тип и параметры прерывания.
В этом блоке можно определить прерывание по TMR2. Этот таймер интересен своей гибкостью и возможностями по настройке частоты прерывания.
Ниже приведено описание TMR2.
 

А также пример включения этого прерывания.

 
В примере показано применение прерывания по TMR2. Подпрограмма прерывания формирует импульс с частотой 78125 Гц. На графике хорошо видно, что длительность импульса равна 4,2 мкс. Длительность паузы, которая формирует импульс – 3 мкс, остальное время 1,2 мкс – это время на переключение порта.
Поскольку период сигнала равен 12,8 мкс, то оставшееся время равно 8,6 мкс.
Попытаемся увеличить длительность паузы до 5 мкс.
Зачем нам это нужно?
Посмотрите на следующий пример.
 

На графике видно, что периодичность сигнала исчезла, значит, в работе прерывания происходят сбои. Но, почему? Что же произошло?
Ведь оставалось еще 8,6 мкс, а увеличили паузу мы всего на 2 мкс.
Происходит это по двум причинам, из-за того что так написано прерывание в ФК (но мы попытаемся это исправить) и из-за работы компилятора который сохраняет (а затем восстанавливает) очень большой стек при уходе на подпрограмму (вот здесь мы ничего не сможем сделать, но в дальнейшем мы это попытаемся обойти, но только на AVR).
Таким образом, эти причины нужно всегда учитывать.

Продолжение следует…

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (принцип DDS и PWM)
« Ответ #6 : Май 18, 2011, 13:04:52 »
Сегодня мы рассмотрим, как написать прерывание через Custom и слегка модернизировать его.
Я уже описывал в ветке Измерение скорости пули
как написать свое прерывание и уменьшить время на вход и выход в/из прерывания.
Но я повторюсь для этого примера.
Откройте любой из выше приведенных примеров и зайдите в исходник на СИ, который сгенерирован ФК. Найдите место, где определено прерывание.
Ниже я прокомментировал определение прерывания, обязательно найдите в ДАТУ на МК и изучите эти регистры (intcon, t2con, pie1).
Функции:
st_bit (регистр, бит) – установить бит в единицу.
cr_bit (регистр, бит) – сбросить бит в ноль.

//Interrupt
//Interrupt: Enable TMR2
   st_bit(intcon,PEIE);      // разрешить прерывание
   st_bit(t2con,T2CKPS0);   // предделитель на 4
   cr_bit(t2con,T2CKPS1);
   st_bit(t2con,TMR2ON);   // включить таймер
   t2con = t2con & 0x07;   // постделитель в 1
   // pr2=16-1;         // регистр периода (сравнения)
   st_bit(intcon,GIE);      // разрешить глобально прерывания
   st_bit(pie1, TMR2IE);   // разрешить прерывание от TMR2


Затем скопируйте эту часть кода и  вставьте в форму Custom – Enable Code.


А вот так генерируется (создается программой ФК) код обработки прерывания:

//Handler code for [TMR2]
   #ifndef MX_INTHANDLER_pir1_TMR2IF
   #define MX_INTHANDLER_pir1_TMR2IF
   if (ts_bit(pir1, TMR2IF) && ts_bit(pie1, TMR2IE))
   {

      FCM_To_port();
      cr_bit(pir1, TMR2IF);
   }

Выделенные строки мы упраздним (в данном случае они не нужны, в программе будет только одно прерывание и нет необходимости его селектировать).
Оставшиеся две строки перепишем следующим образом:

FCM_%n(); // так будет вызываться определенная вами подпрограмма
pir1.TMR2IF=0; // тоже самое, но работает быстрее (только для ПИКов).


Эти строки вставляем в Custom – Handler Code.
Определяем имя прерывания, например, my_TMR_2.
Нажимаем окей и закрываем блок.

В стандартном блоке прерывания для TMR2 значения для регистра pr2 (регистра периода (сравнения)) определены всего пятью значениями (так сделали Матриксы), однако это 8 разрядный регистр и может принимать значения в диапазоне от 0 до 255 (значения типа 0 и 1 особого смысла не имеют). Таким образом, частоту прерывания можно устанавливать более «плавно». Запустите ПИК калькулятор и посмотрите это.
 

В дальнейшем мы будем пользоваться этим регистром.
Для того чтобы оперативно пользоваться такими возможностями вынесем определение регистра pr2 в отдельный блок СИ. Смотрите программу.
 
После запуска программы в Протеусе, видно, что пауза 5 мкс отрабатывается корректно.

Продолжение следует, а пока, чтобы вам не было скучно, исследуйте эту программу.
 

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (принцип DDS и PWM)
« Ответ #7 : Май 19, 2011, 10:09:31 »
В основу формирования синусоидального сигнала положен принцип DDS.

Задача DDS — получить на выходе сигнал синусоидальной формы заданной частоты. В DDS формирование выходного сигнала происходит в цифровой форме. Это означает, что в структуре DDS должен быть ЦАП. В любом случае на выходе ЦАП должен присутствовать ФНЧ для подавления образов выходного спектра, повторяющихся с периодичностью FCLK (anti-aliasing filter).
В качестве ЦАП я применил схему 2R2 (она быстрее работает в Протеусе).
Для получения синусоидального сигнала на вход ЦАП необходимо подать последовательность отсчетов функции sin, следующих с частотой дискретизации FCLK.
Закон изменения функции sin во времени сложен и цифровыми методами просто не реализуется. Можно, конечно, используя полиномиальное представление, вычислять значения функции sin с помощью АЛУ. Однако такой метод не будет быстродействующим для данных типов МК. Поэтому наиболее подходящим методом формирования отсчетов функции sin является табличный метод.
Я привожу пример расчета 64 значений синуса.
 

Вот так это выглядит на рисунке
 






Таблица синуса размещается в ПЗУ (но можно и в ОЗУ, если позволяет ресурс МК).
(Я специально разместил массив в ПЗУ, чтобы дать навыки работы на СИ. Кроме того, определять (наполнять) массив в ФК не совсем благодарное дело (да и возможности определить массив в РОМ и сэкономить память в ФК нет). Попробуйте самостоятельно переписать этот массив в массив ОЗУ в ФК и вы увидите разницу.)

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


Загрузите пример и проверьте, то что показано на рисунке.
 

Частота прерывания определена как  65789,47 Гц. Приращение переменной Diskret, можно изменять с единичным шагом. При Diskret = 1 частота синуса будет равна 1027,96 Гц, при 2 -  в два раза больше.




Продолжение следует.

Taska

  • Hero Member
  • *****
  • Сообщений: 1801
    • Просмотр профиля
Re:Формирование сигналов (принцип DDS и PWM)
« Ответ #8 : Май 19, 2011, 11:39:42 »
mim объясни пожалуйста как работает эта строка
i+=FCV_DISKRET;
Я то понимаю что она плюсует к переменной i переменную DISKRET, только одного не пойму как она обнуляется, по идее она ведь должна досчитать до 63 и обнулиться.

Порисовал нолики с единичками - въехал когда она досчитает до победы то сама обнулится, вывод то все равно по маске.

Сам спросил -сам ответил

mim

  • Hero Member
  • *****
  • Сообщений: 2700
    • Просмотр профиля
Re:Формирование сигналов (принцип DDS и PWM)
« Ответ #9 : Май 19, 2011, 12:14:31 »
Максим пишет:
Цитировать
Сам спросил -сам ответил

Абсолютно верно, обнуление по переполнению, и означивание по маске. Таким образом счетчик будет считать только до 63 (до обнуления, он просчитает до 63 - 1023 раза). Такой способ применяется очень часто и работает быстрее, чем если бы было условие счета до 63 и обнуление.