Archives par mot-clé : G7UVW

Librairie pour piloter un DDS AD9850 avec un LaunchPad/MSP430 ou un Arduino

[GTranslate]

Je partage avec vous un de mes premiers résultats dans la mise au point d’une balise WSPR autonome agile avec générateur de signal à DDS (http://xv4y NULL.radioclub NULL.asia/boutique/?slug=product_info NULL.php&products_id=33). Voici en effet une petite librairie qui simplifiera vos projets pour piloter un DDS de chez Analog Devices comme le AD9850. Vous pouvez aussi facilement concevoir un VFO pour vos montages personnel Bitx (http://xv4y NULL.radioclub NULL.asia/category/ham-radio/materiel/bitx/) ou Bingo.

Cette librairie est assez simple puisqu’elle comporte quelques fonctions pour initialiser le circuit et lui programmer une fréquence. Un paramètre permet de passer le circuit en mode Power Down et de le réveiller au cas où. Cela permet d’économiser de l’énergie et même de faire une forme de CW si votre DDS génère le signal directement.

La communication se fait en mode série via 4 broches d’un micro-contrôleur MSP430G2553 par exemple. Bien entendu il faut aussi fournir l’alimentation et la masse. Fait intéressant, l’AD9850 est très flexible et supporte 3,3V ou 5V pour son alimentation. Comme la librairie est aussi très simple et n’utilise qu’un mode de communication logicielle elle est virtuellement portable sur toutes les familles de micro-contrôleurs. Le code est écrit pour les environnement de développements basés sur Wiring comme par exemple Arduino ou Energia.

Vous pouvez télécharger la librairie complète sur la page de téléchargements (http://xv4y NULL.radioclub NULL.asia/boutique/docs/).

Le code pour le fichier de header AD9850.h

/*
 AD9850.h - Library for adding simple AD9850 control capabilities on MSP430

 Copyright 2012 Yannick DEVOS under GPL 3.0 license
 Any commercial use or inclusion in a kit is subject to author approval

 ====
 Revision history :
 v1.00    2012-12-16
 First release

 ====
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You can download a copy of the GNU General Public License at <http://www.gnu.org/licenses/>

 ///////////////////////////////// How to use the lib

 * Create an instance of the object with the pin for CLOCK, LOAD, DATA and RESET

 AD9850 myDDS (P1_5, P2_0, P2_1, P2_2);	 Example for LaunchPad

 * Initialize the AD9850 and do a reset

 myDDS.begin();
 myDDS.reset();

 */

// Core library
#if defined (__AVR_ATmega328P__) || defined(__AVR_ATmega2560__) // Arduino specific
#include "WProgram.h" // #include "Arduino.h" for Arduino 1.0
#elif defined(__32MX320F128H__) || defined(__32MX795F512L__) // chipKIT specific 
#include "WProgram.h"
#elif defined(__AVR_ATmega644P__) // Wiring specific
#include "Wiring.h"
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) || defined(__MSP430G2231__) // LaunchPad specific
#include "Energia.h"
#elif defined(MCU_STM32F103RB) || defined(MCU_STM32F103ZE) || defined(MCU_STM32F103CB) || defined(MCU_STM32F103RE) // Maple specific
#include "WProgram.h"	
#endif

// ensure this library description is only included once
#ifndef AD9850_h
#define AD9850_h

// library interface description
class AD9850
{
	// user-accessible "public" interface
public:
	AD9850(uint8_t pinClock, uint8_t pinLoad, uint8_t pinData, uint8_t pinReset);
	void begin();
	void reset();
	void SetFrequency(unsigned long frequency, boolean powerdown);	// Set the frequency and send PowerDown command if needed
	// A few private methods
private:
};

#endif

Le code pour le fichier de déclaration des routines AD9850.cpp

/*
 AD9850.h - Library for adding simple AD9850 control capabilities on MSP430

 Copyright 2012 Yannick DEVOS under GPL 3.0 license
 Any commercial use or inclusion in a kit is subject to author approval

 Based on work by G7UVW

 ====
 Revision history :
 v1.00    2012-12-16
 First release

 ====
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You can download a copy of the GNU General Public License at <http://www.gnu.org/licenses/>

 */

// include this library's description file
#include <AD9850.h>
//#include <legacymsp430.h>

#define DDS_CLOCK 125000000

// Constructor /////////////////////////////////////////////////////////////////
uint8_t _DDSpinClock;
uint8_t _DDSpinLoad;
uint8_t _DDSpinData;
uint8_t _DDSpinReset;

AD9850::AD9850(uint8_t pinClock, uint8_t pinLoad, uint8_t pinData, uint8_t pinReset)
{
	_DDSpinClock = pinClock;
	_DDSpinLoad = pinLoad;
	_DDSpinData = pinData;
	_DDSpinReset = pinReset;

};

// Methods /////////////////////////////////////////////////////////////////

void AD9850::begin()
{
    pinMode (_DDSpinClock, OUTPUT); 
    pinMode (_DDSpinLoad,  OUTPUT); 
    pinMode (_DDSpinData,  OUTPUT); 
    pinMode (_DDSpinReset, OUTPUT);

	digitalWrite(_DDSpinReset, LOW);
	digitalWrite(_DDSpinClock, LOW);
	digitalWrite(_DDSpinLoad, LOW);
	digitalWrite(_DDSpinData, LOW);		
}

void AD9850::reset()
{
	//reset sequence is:
	// CLOCK & LOAD = LOW
	//  Pulse RESET high for a few uS (use 5 uS here)
	//  Pulse CLOCK high for a few uS (use 5 uS here)
	//  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

	// data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
	// toggle the LOAD line here.

    digitalWrite(_DDSpinClock, LOW);
    digitalWrite(_DDSpinLoad, LOW);

	digitalWrite(_DDSpinReset, LOW);
	delay(5);
	digitalWrite(_DDSpinReset, HIGH);  //pulse RESET
	delay(5);
	digitalWrite(_DDSpinReset, LOW);
	delay(5);

	digitalWrite(_DDSpinClock, LOW);
	delay(5);
	digitalWrite(_DDSpinClock, HIGH);  //pulse CLOCK
	delay(5);
	digitalWrite(_DDSpinClock, LOW);
	delay(5);
	digitalWrite(_DDSpinData, LOW);    //make sure DATA pin is LOW

	digitalWrite(_DDSpinLoad, LOW);
	delay(5);
	digitalWrite(_DDSpinLoad, HIGH);  //pulse LOAD
	delay(5);
	digitalWrite(_DDSpinLoad, LOW);
	// Chip is RESET now
}

void AD9850::SetFrequency(unsigned long frequency, boolean powerdown)
{
	unsigned long tuning_word = (frequency * 4294967296 ) / (DDS_CLOCK*10);  // As frequency is in tens of Hertz, we need to multiply by 10
	digitalWrite (_DDSpinLoad, LOW); 

	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 8);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 16);
	shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, tuning_word >> 24);
	if (powerdown)
		shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, B00000100);	// If powerdown is true then send PowerDown command
	else
		shiftOut(_DDSpinData, _DDSpinClock, LSBFIRST, 0x0);

	digitalWrite (_DDSpinLoad, HIGH); 
}