Генератор AD9833 + ПП8-8(8А) (Arduino)

Ранее в http://rcl-radio.ru/?p=120649 рассматривался пример взаимодействия переключателя программного поворотного ПП8-8(8А) с микроконтроллерами типа Atmega8, Atmega48, Atmega88, Atmega168, Atmega328 (Arduino Nano), на этой странице будет показан практический пример использования такого переключателя совместно с модулем AD9833.

AD9833 — генератор сигналов с низким энергопотреблением. Позволяет генерировать сигналы с частотой до 12.5 МГц синусоидальной, треугольной и прямоугольной формы. Управление осуществляется с использованием трехпроводного интерфейса SPI.

Основные характеристики микросхемы:

  • Цифровое программирование частоты и фазы.
  • Потребляемая мощность 12.65 мВт при напряжении 3 В.
  • Диапазон выходных частот от 0 МГц до 12.5 МГц.
  • Разрешение 28 бит (0.1 Гц при частоте опорного сигнала 25 МГц).
  • Синусоидальные, треугольные и прямоугольные выходные колебания.
  • Напряжение питания от 2.3 В до 5.5 В.
  • Трехпроводной интерфейс SPI.
  • Расширенный температурный диапазон: от –40°C до +105°C.
  • Опция пониженного энергопотребления.

Более подробно об генераторе на AD9833 можно узнать на странице http://rcl-radio.ru/?p=78387.

Переключатель программный поворотный ПП8-8(8А) позволяет задавать необходимую частоту генератора на базе AD9833 в диапазоне от 0 до 9 999 999 Гц, а так же менять форму выходного сигнала.

Форма сигнала (синус, меандр, треугольник) задается крайним слева переключателем. Генератор фактически может выдавать частоту до 12,5 МГц, на что рассчитан программный переключатель при использовании всех секций, но чтобы не делать отдельную кнопку для изменения формы сигнала, было принято решение ограничить частоту генератора до 10 МГц и отвести под переключатель формы сигнала одну из секций переключателя.

Установленная частота выводится на дисплей LCD1602 c I2C модулем.

//AD9833
#define CS    PC0
#define CLK   PC1
#define DATA  PC2

#include <Wire.h> 
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей
unsigned long itog,itog_old,data[8];
long f=1000;
long b,h_bit,l_bit,f_lcd,f_ust;
const long f25 = 24999420;// частота кварца, если нет эталонного частотомера установите частоту 25000000 Гц
int form,sig,sig_old;

void setup() {
  lcd.init();lcd.backlight();Wire.begin();
  PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3);
  DDRC |=(1<<CS)|(1<<CLK)|(1<<DATA);
  PORTC |=(1<CLK)|(1<<CS)|(1<<DATA);
  _delay_ms(500);
  ad_AD9833();
}

void loop() {
  for(int i=0;i<=7;i++){
  DDRD =(1<<i);
  PORTD = (1<<i);
  data[i] = PINB & 0b1111;
  }
  itog = data[6]*1000000+data[5]*100000+data[4]*10000+data[3]*1000+data[2]*100+data[1]*10+data[0];
  sig = data[7];
  if(itog_old!=itog || sig_old!=sig){
    f=itog;
    ad_AD9833();
    }

  itog_old = itog;
  sig_old = sig;
  
  lcd.setCursor(0,0);lcd.print("F ");
  lcd.print(data[6]);
  lcd.print(".");lcd.print(data[5]);lcd.print(data[4]);lcd.print(data[3]);
  lcd.print(".");lcd.print(data[2]);lcd.print(data[1]);lcd.print(data[0]);
  lcd.print(" Hz ");
  lcd.setCursor(2,1);
  lcd.print("AD9833");
  lcd.setCursor(11,1);
  switch(data[7]){ // форма сигн.
  case 0: lcd.print("DAC");WriteAD9833(0x2028);break;
  case 1: lcd.print("SIN");WriteAD9833(0x2000);break;
  case 2: lcd.print("TRI");WriteAD9833(0x2002);break;
  case 3: lcd.print("DAC");WriteAD9833(0x2028);break;
  case 4: lcd.print("SIN");WriteAD9833(0x2000);break;
  case 5: lcd.print("TRI");WriteAD9833(0x2002);break;
  case 6: lcd.print("DAC");WriteAD9833(0x2028);break;
  case 7: lcd.print("SIN");WriteAD9833(0x2000);break;
  case 8: lcd.print("TRI");WriteAD9833(0x2002);break;
  case 9: lcd.print("DAC");WriteAD9833(0x2028);break;
  }
  delay(100);
}

void WriteAD9833(int data){        // SPI
  PORTC |=(1<<CLK);PORTC &=~(1<<CS);
     for(int i = 15; i >= 0; i--){
        PORTC |=(1<<CLK);
       if(((data>>i)&0x01)==1){PORTC |=(1<<DATA);}else{PORTC &=~(1<<DATA);}
        PORTC &=~(1<<CLK);_delay_ms(1);}
        PORTC |=(1<<CS);
  }

void ad_AD9833(){
  b = f*pow(2,28)/f25;
  if(b<16383){l_bit = b + 0x4000 ;h_bit = 0x4000;}
  else{h_bit = (b>>14) + 0x4000;l_bit = b - (h_bit<<14) + 0x4000;}
  WriteAD9833(0x2100);// 0010 0001 0000 0000 - Reset + DB28
  WriteAD9833(l_bit); // 0100 0000 0000 0000 - Freq0 LSB 
  WriteAD9833(h_bit); // 0100 0000 0000 0000 - Freq0 MSB 
  WriteAD9833(0xC000);// 1100 0000 0000 0000 - Phase0 
  WriteAD9833(0x2028);// 0010 0000 0000 0000 - Exit Reset
  }   

Как отмечалось в начале скетч полностью совместим с микроконтроллерами Atmega8, Atmega48, Atmega88, Atmega168, Atmega328 (Arduino Nano).

Тестирование

 

Comments

    1. Еще ряд добавить не получится (можно, но сложнее), скетч рассчитан на работу с целым портом D, он весь занят. Если только переключение режимов работы перенести кнопочное управление.

      1. Спасибо. Получается, можно в переменную «itog» добавить индекс массива data[7]*10000000? Извиняюсь, а порты D12, D13 не могут быть использованы?

  1. Спасибо. Получается, можно в переменную «itog» добавить индекс массива data[7]*10000000? Извиняюсь, а порты D12, D13 не могут быть использованы?

  2. Получается, можно в переменную «itog» добавить индекс массива data[7]*10000000?

    — да все верно

    а порты D12, D13 не могут быть использованы?

    — для добавления еще одной декады , нет, а как входы для кнопок, да.

Добавить комментарий

Войти с помощью: