f
信号発生器AD9833をRaspberry Piに接続して鳴らします。 WiringPiライブラリのSPI通信で制御します。 AD9833はAmazonで購入できる信号発生器です。 Amazonのページから仕様を抜粋すると、
下3つは実は意味がわかりません。ここでは波形発生器として使います。
AD9833のデータシートは
「プログマブル波形発生器AD9833」をご覧ください。
Arduinoで鳴らす方法は「Arduinoで信号発生器9833を鳴らす」をご覧ください。
Raspberry Piの初期設定は「Raspberry Piの初期設定」 をご覧ください。
+5VとGround、さらに3本のSPIに関わる信号線をつなぎます。MOSIは接続しません。 波形出力にノイズが乗っていたのでフィルターを入れています。また、出力は0V-5VでしたのでDCをカットするようにしています。
RaspberryPi : AD9833 GPIO11 : SCK : SCLK GPIO9 : MOSO : No Connection GPIO10 : MOSI : SDATA GPIO8 : CE0 : FSYNC
AD9833は1つの16ビットの制御ビットで制御されます。このうち、波形の種類を選択しているのは下の赤で囲った OPBITEN, DIV2, MODEの3つのビットです。
正弦波は0x0000, 三角波は0x0002、矩形波は0x0020と設定します。 下の表ではDACデータのMSB/2、DACデータのMSBと書かれている欄は矩形波を表しています。 DACデータのMSB/2、DACデータのMSBの違いは周期が異なります。 DACデータのMSB/2は周期が倍、すなわち周波数が1/2になります。通常はDACデータのMSBを使えば良いと思います。
周波数を設定するためには下のsetFrequencyに書いたように、 制御ビットのB28を1にし、その後、周波数を2ワードで送信します。 下のプログラムでは、calcFreqで周波数(Hz)から周波数の32ビットのレジスタの値に変換しています。 32ビットで表された周波数は16ビットの2ワード、MSB/LSBの順で送信します。
16ビットのデータをSPI通信で送信する場合は、spiSendに示しているようにMSB/LSBの順で送信します。
#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <wiringPiSPI.h> #define AD_MCLK 25000000UL ///< Clock speed of the AD9833 reference clock in Hz #define AD_2POW28 (1UL << 28) ///< Used when calculating output frequency // 波形選択レジスター #define MODE_OFF 0x00c0 #define MODE_SINE 0x0000 #define MODE_SQ1 0x0028 #define MODE_SQ2 0x0020 #define MODE_TRNG 0x0002 // 周波数を設定 #define SEL_FREQ0 0x2000 enum shape_t{ SP_OFF=0, SP_SINE, SP_SQ1, SP_SQ2, SP_TRYG, SP_NUM }; uint16_t mSHAPE[SP_NUM]={ MODE_OFF, MODE_SINE, MODE_SQ1, MODE_SQ2, MODE_TRNG, }; // 周波数(Hz)からAD9833のレジスターの値に変換 uint32_t calcFreq(float f) { return (uint32_t)((f * AD_2POW28/AD_MCLK) + 0.5); } uint16_t calcPhase(float a) // 位相(deg)からAD9833のレジスターの値に変換 { return (uint16_t)((512.0 * (a/10) / 45) + 0.5); } // 1wordをAD9833へ送る(MSB First) void spiSend(uint16_t reg) { unsigned char buf[2]; buf[0] = (unsigned char)(reg>>8); //MSB` buf[1] = (unsigned char)(reg&0xFF); //LSB wiringPiSPIDataRW(0,buf,2); } // n wordをAD9833へ送る(MSB First) void spiSendn(uint16_t *reg, uint16_t n) { unsigned char *buf=(unsigned char*)malloc(n*sizeof(uint16_t)); for(uint16_t i=0; i<n; i++){ buf[i*2] = (unsigned char)(reg[i]>>8); //MSB buf[i*2+1] = (unsigned char)(reg[i]&0xFF); //LSB } wiringPiSPIDataRW(0,buf,n*sizeof(uint16_t)); } //波形の形状 //周波数(Hz)を設定する void setFrequency(uint16_t shape,float freq) { uint32_t _regFreq = calcFreq(freq); uint16_t reg[3]; reg[0]=(SEL_FREQ0 | mSHAPE[shape]); reg[1]=(0x4000 | (uint16_t)(_regFreq & 0x3fff)); //LSB reg[2]=(0x4000 | (uint16_t)((_regFreq >> 14) & 0x3fff)); //MSB printf("%04x\n",reg[0]); spiSendn(reg,3); } void delay(unsigned milliseconds) { clock_t pause; clock_t start; pause = milliseconds * (CLOCKS_PER_SEC / 1000); start = clock(); while( (clock() - start) < pause ); } int main() { wiringPiSPISetup(0, 500000); delay(100); spiSend(0x0100); delay(100); spiSend(MODE_OFF); //OFF delay(1000); while(1){ setFrequency(SP_SINE,200); delay(5000); setFrequency(SP_SQ1,100); delay(5000); setFrequency(SP_SQ2,50); delay(5000); setFrequency(SP_TRYG,100); delay(5000); } }