mbedでプログラムを書いて、SPI DACのMCP4922とNucleo F446RE内蔵DACの処理時間を比較してみた。
どちらも12bit。
/* * 内蔵DACとMCP4922に出力するテスト * * 2017.06.21 * */ #include "mbed.h" #include "rtos.h" #define SPI_CLOCK (24000000) SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK); // mosi, miso, sclk DigitalOut Cs(D10, 1); AnalogOut InternalDac(PA_4); DigitalOut CheckPinD2(D2); DigitalOut CheckPinD3(D3); // v: 0..0x0fff void OutMCP4922(uint16_t v) { //v &= 0x0fff; // Channel A Cs = 0; SpiM.write(v >> 8 | 0x30); // 0x30: DAC_A(0) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1) SpiM.write(v & 0xff); Cs = 1; } // v: 0..0xffff void OutInternalDac(uint16_t v) { InternalDac.write_u16(v); } int main() { SpiM.format(8, 0); SpiM.frequency(SPI_CLOCK); uint16_t count = 0; for (;;) { uint16_t v12 = count >> 4; uint16_t v16 = count; CheckPinD2 = 1; OutMCP4922(v12); CheckPinD2 = 0; CheckPinD3 = 1; OutInternalDac(v16); CheckPinD3 = 0; count += 0x100; Thread::wait(1); } }
Nucleoをmbedで使って、SPIの周波数設定をするとちょうどの周波数にはならない。おそらくマスタークロックの分周比なのだと思う。
こういうハードウェア寄りの使い勝手はmbedの弱点ではあります。
SPI::frequency()でSPIクロックの周波数を変えて測定してみた。
ブレッドボード配線図
MCP4922にはLDAC pinがあって、これをH→LするとA ChannelとB Channelが同期して
同時に電圧が出力されるが、LDACをL(GND)に落としておくと、CSのアクティブ/インアクティブで制御できるようだ。配線や処理時間のコストがシビアな場合は役に立つと思う。(A Channelだけしか試してないです)
1MHz
ch1:MCP4922 ch2:内蔵DAC
MCP4922から出力すると、27.3usかかる。一方内蔵DACは700ns(0.7us)で済む。
ch1:MCP4922 ch2:SPI_SCK
1MHzを設定した場合はMCP4922との通信に使っているSPIのクロック周波数は643kHz
24MHz
ch1:MCP4922 ch2:内蔵DAC
SPIのクロック周波数を上げるとMCP4922でも6.8us(≒147kHz)で済む。
ch1:MCP4922 ch2:SPI_SCK
SPIのクロック周波数は22.44MHz。クロックが高周波数になるとダンピング抵抗を入れていても波形が怪しくなる。
MCP4922の最大周波数は20MHzなので仕様外だが、VOUTAから波形は出力される。
Zoom Out
ch1:MCP4922 ch2:SPI_SCK
高クロックになると、8bitずつのSPI通信の間隔が開くようだ。
<追記:2017.06.25>
間隔が開くと言うより、SPI::write()のオーバーヘッドが2~3us程度ある?
</追記>
設定値と出力周波数
設定値 | SPIクロック | 処理時間 |
---|---|---|
1MHz | 643.8kHz | 27.3us |
2MHz | 1.154MHz | 16.76us |
4MHz | 2.810MHz | 11.32us |
6MHz | 5.762MHz | 8.76us |
12MHz | 11.29MHz | 7.36us |
24MHz | 22.44MHz | 6.74us |
0 件のコメント:
コメントを投稿