DDS-Signalgenerator per USB

Wechseln zu: Navigation, Suche

von M. Dittrich

Dieser Artikel nimmt am Artikelwettbewerb Infineon XMC Design Contest 2014 teil.
Banner.png

Einleitung[Bearbeiten]

Wer kennt es nicht, eine Simulation bringt schönste Ergebnisse und der Testaufbau zeigt starke abweichungen. Solche Probleme könnte man umgehen wenn man frühzeitig an realen Bauteilen testen könnte. Ein Signalgenerator wäre das Werkzeug der Wahl! Der Trend elektrischer Geräte geht mehr und mehr in Richtung USB. So laufen moderne Logic Analyzer, genau wie moderne Messgeräte über USB. Lösung ist ein DDS, dies steht für Direct Digital Synthesis und ist ein Verfahren zur Erzeugung periodischer Signale. Dies kann sowohl ein Sinus-, Dreieck- oder Rechtecksignal sein. Nimmt man nun noch einen PWM-Kanal dazu, so hat man wirklich alles wünschenswerte an Signalen parat.

Dieses Projekt beschreibt wie man sich einen qualitativ sehr hochwertigen Signalgenerator für unter 25€ selbst zusammenbauen kann.
Mehr zum Thema DDS findet ihr hier.

Wer jetzt noch der Meinung ist, ein digitaler Signalgenerator sollte auch Protokolle wie I2C oder SPI ausgeben können, der darf gerne weiterlesen! Es gibt eine extended edition welche dies unterstützt. Preislich kommen dann noch eine Platine und ein paar Bauteile für ca. 25€ dazu.

Hardware[Bearbeiten]

Die verwendete Hardware ist ein Infineon XMC2Go und ein AD9833 Modul.

XMC2Go[Bearbeiten]

XMC2Go Kit with XMC1100

Die von Infineon entwickelte Hardware basiert auf dem XMC1100 32-bit ARM® Cortex™-M0 Prozessor:

  • 32MHz CPU
  • 64k Flash
  • 16k RAM
  • On-Board J-Link Debugger

Besonders von Bedeutung ist das XMC4200 Debug IC. Dies ermöglicht uns Breakpoints im Programm zu definieren, welches ein stückweises Abarbeiten des Programmablaufs ermöglicht. Es ist dabei möglich zwischen jedem Schritt die Werte von Variablen zu beobachten und somit Fehler im Programmcode schnell zu entdecken.

AD9833[Bearbeiten]

AD9833 Modul

Der von Analog Devices entwickelte Chip hat folgende Eckdaten:

  • 25MHz Clock
  • 28bit Resolution
  • 2,3V to 5,5V Power supply
  • 12,65mW Power consumption at 3V

In diesem Projekt können damit Frequenzen bis zu 10MHz generiert werden. Man sollte noch erwähnen, das bei der Umrechnung nach Integer Rundungsfehler auftreten. Ein Beispiel:

\frac{2^{28\;bit}}{25\cdot 10^6\;Hz}=10,73741824s

Gerundet ergibt dies 11, jedoch als Integer nur 10! Dieses Beispiel sollte zeigen das es nicht immer möglich ist die Frequenz exakt vorzugeben.

GPIO[Bearbeiten]

Das Kürzel GPIO steht für General Purpose Input/Output und kennzeichnet Pins welche man wahlweise als als Ein- oder Ausgang konfigurieren kann. Das XMC2Go hat 14 Ports welche diverse Funktionen übernehmen können. Was genau sieht man hier. In diesem Projekt werden die folgenden Pins verwendet:

  • T1 = P0.6
  • LED1 = P1.0
  • LED2 = P1.1

Mehr dazu und zu den folgenden Punkten findet ihr im XMC2Go Users Manual.

PWM[Bearbeiten]

Das Kürzel PWM steht für Pulse-Width Modulation und beschreibt ein Rechtecksignal mit einstellbarem Tastgrad (engl. Duty Cycle). Zum Betrieb dieses Moduls wird lediglich die Frequenz und der Tastgrad angegeben. In diesem Projekt wird der folgende Pin verwendet:

  • PWM = P0.5

Auf die Programmierung des Moduls wird später genauer eingegangen.

SPI[Bearbeiten]

Das Kürzel SPI steht für Serial Peripheral Interface und beschreibt ein Modul zur seriellen Datenübertragung. Zum Betrieb dieses Moduls werden maximal 4 GPIO Pins benötigt:

  • SDI/MISO = P0.6
  • SDO/MOSI = P0.7
  • CLK/SCLK = P0.8
  • CS/SS/FSYNC = P0.9

Man unterscheidet jedoch zwischen Vollduplex, Halbduplex und Simplex. Wenn Daten nur in der Richtung XMC -> AD9833 gesendet werden sollen, spricht man auch von MTSR also Master Transmit Slave Receive. Dies wird dann als Simplex Kommunikation beschrieben und benötigt lediglich die SDO, CLK und CS Pins des XMC's. Halbduplex wäre der Fall das man Master <-|-> Slave (senden oder empfangen) kann und Vollduplex wäre für Master <-&-> Slave (gleichzeitig senden und empfangen). Hierbei benötigt man die SDI, SDO, CLK und CS Pins des XMC's. Mehr dazu findet ihr hier.

UART[Bearbeiten]

Das UART Modul ist anfangs sehr komplex, es zeigt sich jedoch als sehr nützlich. Wenn man die interne USB <-> UART Bridge verwenden möchte, konfiguriert man wie folgt:

  • Tx = P2.1
  • Rx = P2.2

Man beachte das diese Pins auf dem XMC2Go nicht herausgeführt wurden! Nach Inbetriebnahme kann man mit beliebigen Terminal-Programmen mit dem XMC kommunizieren. Ich empfehle hierzu HTerm.

Extended Edition[Bearbeiten]

Vorteil der Extended Edition sind nicht nur die zusätzlichen Funktionen sondern auch ein schickes Gehäuse. Jedoch reicht in diesem Fall der Hardwareumfang des XMC2Go nicht mehr ganz aus. Der Grund warum zusätzliche Hardware von nöten ist, ist einfach begründet: Der XMC2Go verfügt nur über zwei USIC Channel. Einer wird für die Kommunikation über UART reserviert, der andere für die Kommunikation über SPI. Dies ist aber keineswegs schlecht weil eh ein Kurzschlußschutz der GPIO Pins benötigt wird! Diese fähigkeit sowie die Spannungsfestigkeit bis 5V aller GPIO's bringt der SC18IS600 Chip mit sich.

Zusammengefasst ergibt uns die Erweiterung folgende Schnittstellen:

  • PWM out
  • AD in
  • GPIO in/out
  • SPI in/out
  • I2C in/out

Das erweitert die Einsetzbarkeit dieses Werkzeugs enorm!

NXP SC18IS600 Chip[Bearbeiten]

Bei diesem IC handelt es sich um ein SPI zu I2C Umsetzer. Desweiteren ergänzt dieser Chip ein vorhandenes System um sechs GPIO Pins, von denen zwei quasi-bidirectional sein können.

Software[Bearbeiten]

Als Entwicklungsumgebung bietet Infineon DAVE3 an. Der vorteil dieser IDE ist eine grafische Benutzeroberfläche. Diese bietet vorgefertigte Apps, quasi Templates, zur schnellen Initialisierung verschiedenster Module.

App Connectivity[Bearbeiten]

Dave apps.png
DAVE3 App Connectivity (extended version)
DAVE3 App Connectivity (basic version)

Frequency Calculation[Bearbeiten]

/*/ Calculation of the 28bit stream /*/
long CalcFreqValue(uint32_t hz) {
	uint64_t temp;
	uint32_t freq;
	temp = hz*(pow(2,28)/25e6);
	freq = temp;
	return freq;
}

Phase Calculation[Bearbeiten]

/*/ Calculation of the 14bit stream /*/
int CalcPhaseValue(uint32_t deg) {
	uint32_t phase;
	phase = deg*(pow(2,11)/180);
	return phase;
}

UART Communication[Bearbeiten]

/*/ If data received via UART /*/
if((USIC0_CH0->TRBSR & 0x00000008) == 0) {
	bool stop_bit = 0;
	uint8_t cnt = 0;
	uint8_t pos = 0;

	/*/ Turn on LED1 to show there are incoming data /*/
	LED(1, 1);
	
	/*/ Clear all Arrays to avoid Errors /*/
	bzero(&Buffer, sizeof(Buffer));
	bzero(&Freq, sizeof(Freq));
	bzero(&Phase, sizeof(Phase));
	bzero(&Value, sizeof(Value));

	/*/ Store FIFO data into Buffer[0...n] /*/
	while(!stop_bit) {
		Buffer[pos] = (USIC0_CH0->OUTR & 0x0000FFFF);
		if(Buffer[pos] == '\0')
			stop_bit = 1;
		pos++;
	}
	.
	.
	.
}

SPI Communication[Bearbeiten]

/*/ Clear status flags /*/
void SPI001_Clear() {
	SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
	SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
}

/*/ Wait until data has been sent /*/
void SPI001_WaitForOK() {
	uint8_t Status1 = 0;
	uint8_t Status2 = 0;
	do {
		Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
		Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
	} while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));
}

/*/ Shifting 2x 14bit /*/
Data[1] = (CalcFreqValue(DesiredFreq) & 0x3FFF) + 0x4000;
Data[2] = (CalcFreqValue(DesiredFreq) >> 14) + 0x4000;

/*/ Shifting 12bit /*/
Data[5] = (CalcPhaseValue(DesiredPhase) & 0x3FFF) + 0xC000;

/*/ Send data to Chip /*/
SPI001_Clear();
EnableStartOfFrame(SPI001_Handle0);
for(int i=0; i<sizeof(Data)/sizeof(Data[0]); i++) {
	SPI001_WriteData(&SPI001_Handle0,&Data[i],SPI001_STANDARD);
}
SPI001_WaitForOK();
EnableEndOfFrame(SPI001_Handle0);

Special GPIO Pins[Bearbeiten]

This is a user defined Area. You can write any kind of code inside this Prototype or leave it blank if it's not used.
In this case, the <io:***> Parameter is unused.

Example: <io:255> gives the following

uint8_t Special[] = {2, 5, 5, \0}

Testing with HTerm[Bearbeiten]

For first Tests we can use HTerm. Take advantage of the following settings:

  • 115200 Baud
  • 8 Data bits
  • 1 Stop bit
  • Parity: none

Example ASC-Command: s,f:2000000,p:180,io:63 <NULL on Enter>
Or the same in short form: s,2000000,180,63 <NULL on Enter>
Result: Sine Wave, 2MHz, 180° Phase shift, 6-bit special GPIO register

Windows Application[Bearbeiten]

Die Software wurde in Microsoft® VisualStudio C# programmiert und ist auch als Sourcecode im Downloadbereich zu finden. Es wurde während der Programmierung besonders auf ein sauberes exception handling geachtet um Programmabstürze zu verhindern.
Die special GPIO Version gibt dem Nachbauer außerdem die Chance seinen eigenen Code auf einfache Weise zu ergänzen um z.B. Ausgänge zu schalten welche weitere Funktionen triggern uvm.

Xmcontrol v1.0.4.png Xmcontrol v1.1.2.png
XMControl v1.0.4 (basic version)
XMControl v1.1.2 (basic version incl. special GPIO register)

Fertigung[Bearbeiten]

Die Fertigung der Einzelteile beschränkt sich auf die extended edition, da es nur für diese Version externe Hardware benötigt. Daher kann dieser Schritt für den Bau der basic edition übersprungen werden.

Leiterplatte[Bearbeiten]

Die Platine wurde in Eagle entworfen. Diese beinhaltet einen 1AD8368 VGA/AGC amplifier und einen 1SC18IS600 IO-Interface Chip.

Schaltplan des XMC2Go/AD9833
Schaltplan des SC18IS600
Schaltplan des AD8368
Board komplett
Platine (roh)
Platine (bestückt)


1optional

Gehäuse[Bearbeiten]

Bei dem Gehäuse habe ich mich, passend zum Wettbewerb, an ein 3D-gedrucktes Teil aus ABS gehalten. Dieses wurde mir netterweise von Claudio H. (siehe Beitrag) angefertigt. Entworfen wurde das Gehäuse in SolidWorks. Dabei wurde auch die Montagefähigkeit überprüft, da die Platine schräg eingeklappt wird. Die STL-Dateien findet man ebenfalls im Downloadbereich.

Gehäuse leicht angeschliffen
Gehäuse Innenansicht
Gehäuse nach Aceton-Dampf-Behandlung

Bilder zum Projekt[Bearbeiten]

Basic Edition
Extended Edition
Ohne Gehäuseoberteil
Messung Sinussignal 1000Hz [500µs/cm]
Messung Dreiecksignal 1000Hz [500µs/cm]
Messung Rechtecksignal 100kHz [5µs/cm]

Downloads[Bearbeiten]

XMC2Go Sourcecode (basic, newest)
XMControl Sourcecode (basic, newest)
XMControl GUI v1.1.2 (basic)
XMControl GUI v1.0.4 (basic)
Eagle CAD-Daten v1.2 (extended)
Gehäuse STL-Daten (extended)

Weblinks[Bearbeiten]

http://de.wikipedia.org/wiki/Direct_Digital_Synthesis
http://de.wikipedia.org/wiki/Serial_Peripheral_Interface
http://de.wikipedia.org/wiki/Duplex
http://de.wikipedia.org/wiki/Kippschwingung
http://de.wikipedia.org/wiki/Pulsweitenmodulation
http://www.infineonforums.com/forums/8-XMC-Forum