要約
このアプリケーションノートでは、MAX5581 DACを用いてPIC®マイクロコントローラを使用する方法について説明します。詳細な回路図とソースコードを提示しています。
MAX5581の概要
MAX5581は、3線式SPI™シリアルインタフェースを搭載した12ビット高速セトリングDACです。MAX5581のインタフェースは、最大3マイクロ秒のセトリング時間で最大20MHzまでのSPIをサポートすることができます。このアプリケーションノートでは、最速ラインのPICマイクロコントローラ(PIC18Fコア)をMAX5581 DACに接続するために必要なアプリケーション回路とすべてのファームウェアを紹介しています。例として挙げたアセンブリプログラムは、MPLAB IDEバージョン6.10.0.0にて無償提供されているアセンブラを使用して、PIC18F442向けに記述したものです。
ハードウェアの概要
ここで取り上げるアプリケーション回路は、MAX5581評価(EV)キットを使用しています。このキットにはMAX5581、超高精度電圧リファレンス(MAX6126)、プッシュボタンスイッチ2個、ゲイン設定抵抗器、および検証されたPCBレイアウトが含まれています。PIC18F442は、MAX5581EVキットボード上にはありませんが、図1に示すアプリケーション回路図を完成するために、システムに追加しています。MAX5581EVキットの/CS\、SCLK、DIN、およびDOUTパッドを利用すれば、SPIシリアルインタフェースに簡単に接続することができます。
大きな画像を見る
図1. MAX5581アプリケーション回路図(1/2)
図1. MAX5581アプリケーション回路図(2/2)
アナログ/ディジタルグランドプレーン
図2に示すように、アナログとディジタルのグランドプレーンを分離するのが懸命な方法です。TDK MMZ1608B601Cなどのフェライトビーズを使用して、両グランドプレーンを接続します。これによって、マイクロコントローラのシステムクロックとその高調波がアナロググランドに流れ込むことを防止しています。PIC18F442のシステムクロックは40MHzですが、特定のインピーダンス対周波数特性のためにMMZ1608B601Cを選択しています。図3はMMZ1608B601Cのインピーダンス対周波数曲線を示しています。
図2. アナロググランドとディジタルグランドの分離
図3. TDK MMZ1608B601Cフェライトビーズのインピーダンス対周波数曲線
ファームウェアの概要
リスト1に示すアセンブリプログラムの例は、PIC18F442の内部MSSP SPI周辺回路を使用してMAX5581を初期化しています。PIC18F442の40MHzシステムクロックによって、MSSPは最大10MHzまでのSPIクロック(SCLK)を供給することができます。表1は、電力供給後に必要な唯一の設定ワードを示しています。一度MAX5581の初期化が行われた後は、表2に示すようにプログラムは絶えずゼロスケールに続いてフルスケールをDAC出力レジスタにロードします。これを絶えずループすることによって、図4に示すような方形波が形成されます。これはMAX5581の高速セトリング時間を実証するものです。
図4. 80kHz方形波の実際のスコープ画面
リスト1:PIC18F442の内部MSSP SPI周辺回路を使用してMAX5581にインタフェース接続する、アセンブリプログラムの例
ダウンロード:P18F442.INC
Listing 1.asm
;****************************************************************************** ; ; Filename: Listing 1 (Absolute Code Version) ; Date: 2/25/05 ; File Version: 1.0 ; ; Author: Ted Salazar ; Company: Maxim ; ;****************************************************************************** ; ; Program Description: ; ; This program interfaces the internal SPI MSSP ; (Peripheral) of the PIC18F442 to the MAX5581 SPI ; Quad DAC. The program initializes the MAX5581 ; and dynamically generates a 50% duty cycle square ; wave with a frequency of 80KHz. ; ; ;****************************************************************************** ; ; History: ; 2/25/05: Tested SPI DAC format ; 2/25/05: Initialized MAX5591 ; 12/14/04: Cleared tcount timer in HWSPI_W_spidata_W ;****************************************************************************** ;****************************************************************************** ; ;****************************************************************************** ; ; Files required: P18F442.INC ; ;****************************************************************************** radix hex ;Default to HEX LIST P=18F442, F=INHX32 ;Directive to define processor and file format #include;Microchip's Include File ;****************************************************************************** ;****************************************************************************** xmit equ 06 ; Asynchronous TX is at C6 ; ;****************************************************************************** ;Configuration bits ; The __CONFIG directive defines configuration data within the .ASM file. ; The labels following the directive are defined in the P18F442.INC file. ; The PIC18FXX2 Data Sheet explains the functions of the configuration bits. ; Change the following lines to suit your application. ;T __CONFIG _CONFIG1H, _OSCS_OFF_1H & _RCIO_OSC_1H ;T __CONFIG _CONFIG2L, _BOR_ON_2L & _BORV_20_2L & _PWRT_OFF_2L ;T __CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_128_2H ;T __CONFIG _CONFIG3H, _CCP2MX_ON_3H ;T __CONFIG _CONFIG4L, _STVR_ON_4L & _LVP_OFF_4L & _DEBUG_OFF_4L ;T __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L ;T __CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_OFF_5H ;T __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L ;T __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H ;T __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L ;T __CONFIG _CONFIG7H, _EBTRB_OFF_7H ;****************************************************************************** ;Variable definitions ; These variables are only needed if low priority interrupts are used. ; More variables may be needed to store other special function registers used ; in the interrupt routines. CBLOCK 0x080 WREG_TEMP ;variable used for context saving STATUS_TEMP ;variable used for context saving BSR_TEMP ;variable used for context saving ; ENDC CBLOCK 0x000 EXAMPLE ;example of a variable in access RAM ; temp ; temp2 ; xmtreg ; cntrb ; cntra ; bitctr ; tcount ; speedLbyte ;T Being used in HWSPI_speed ; ENDC ;****************************************************************************** ;Reset vector ; This code will start executing when a reset occurs. ORG 0x0000 goto Main ;go to start of main code ;****************************************************************************** ;High priority interrupt vector ; This code will start executing when a high priority interrupt occurs or ; when any interrupt occurs if interrupt priorities are not enabled. ORG 0x0008 bra HighInt ;go to high priority interrupt routine ;****************************************************************************** ;Low priority interrupt vector and routine ; This code will start executing when a low priority interrupt occurs. ; This code can be removed if low priority interrupts are not used. ORG 0x0018 movff STATUS,STATUS_TEMP ;save STATUS register movff WREG,WREG_TEMP ;save working register movff BSR,BSR_TEMP ;save BSR register ; *** low priority interrupt code goes here *** movff BSR_TEMP,BSR ;restore BSR register movff WREG_TEMP,WREG ;restore working register movff STATUS_TEMP,STATUS ;restore STATUS register retfie ;****************************************************************************** ;High priority interrupt routine ; The high priority interrupt code is placed here to avoid conflicting with ; the low priority interrupt vector. HighInt: ; *** high priority interrupt code goes here *** retfie FAST ;****************************************************************************** ;Start of main program ; The main program code is placed here. Main: ; *** main code goes here *** start ; *** Port Initialization *** movlw 0x0FF movwf PORTB clrf PORTA movlw 0x06 ;T Configure PortA as Digital movwf ADCON1 movlw 0x00FB ;T A2 OUTPUT, ALL OTHERS INPUT movwf TRISA movlw 0x0001 ;T B0 INPUT, ALL OTHERS OUTPUT movwf TRISB movlw 0x0093 ;T C7-C0 => bit7-0 ;T OUTPUTs: C6(TX), C5(MOSI), C3(SCLK), C2(CS) ;T INPUTs:C4 (MISO) and all others movwf TRISC ;T TRISC bit3 Master = 0 bsf PORTC,RC2 ;T RC2 = CS\ Make CS\ high ; *** SPI Initialization *** call HWSPI_init ;T Initialize the MSSP for SPI ; *** SPI Configuration *** movlw b'00000000' ;T load W with test byte for CPOLCPHA 0,0 ;T b'00000000' => CPOLCPHA 0,0 ;T b'00000001' => CPOLCPHA 0,1 ;T b'00000010' => CPOLCPHA 1,0 ;T b'00000011' => CPOLCPHA 1,1 call HWSPI_W_configure ; *** SPI Speed *** movlw b'00000000' ;T load W with test byte for SPI Freq ;T b'00000000' => Fosc/4 = 10MHz ;T b'00000001' => Fosc/16 = 2.5Mhz ;T b'00000010' => Fosc/64 = 625kHz ;T b'00000011' => Reserved. call HWSPI_W_speed ;****************************************************************************** ; *** MAX5581 Initialization *** bcf PORTC,RC2 ;T RC2 = CS\ Make CS\ Low movlw 0xEC ;T byte0 of settling time config call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation movlw 0x0F ;T byte1 of settling time config call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation bsf PORTC,RC2 ;T RC2 = CS\ Make CS\ high ; *** MAX5581 Load All DAC Outputs to Zero Scale *** Loopforever bcf PORTC,RC2 ;T RC2 = CS\ Make CS\ Low movlw 0xD0 ;T byte0 of load all input/output to zeros call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation movlw 0x00 ;T byte1 of load all input/output to zeros call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation bsf PORTC,RC2 ;T RC2 = CS\ Make CS\ high ; *** MAX5581 Load All DAC Outputs to Full Scale *** bcf PORTC,RC2 ;T RC2 = CS\ Make CS\ Low movlw 0xDF ;T byte0 of load all input/output to zeros call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation movlw 0xFF ;T byte1 of load all input/output to zeros call HWSPI_W_spidata_W ;T HW SPI WriteRead Operation bsf PORTC,RC2 ;T RC2 = CS\ Make CS\ high ; movwf xmtreg ;T move w to xmtreg ; call asyxmtc ;T call UART routine ; goto Loopforever ;T loop forever ;****************************************************************************** errsrv movlw 0x65 ; load w with 'e' = 0x65 movwf xmtreg ; move w to xmtreg call asyxmtc ; call UART routine dead goto dead ; goto endless loop ;****************************************************************************** set_cf_error movlw 0x00 ; 0x00 into W sublw 0x00 ; Subtract W-0x00: If W<=N C set; If W>N C clear. return ; error=> cf=set ;****************************************************************************** clear_cf_ok movlw 0x01 ; 0x00 into W sublw 0x00 ; Subtract W-0x00: If W<=N C set; If W>N C clear. return ; success=> cf=clear ;****************************************************************************** HWSPI_init ;T SPI MSSP Initialization for M2EAM schematic ;T CPOL,CPHA = 0,0 => CKP = 0 & CKE = 1 bcf SSPCON1,SSPEN ;T Disable the MSSP, SSPCON-5 ; bcf TRISC,SDO ;T TRISC bit5 RC5/SDO = 0 MOSI Output bcf TRISC,SCK ;T TRISC bit3 RC3/SCK = 0 SCLK Output bsf TRISC,SDI ;T TRISC bit4 RC4/SDI = 1 MISO Input movlw 0x0040 ;T SSPSTAT bit8 = 0 sampled in middle ;T SSPSTAT bit6 = CKE = 1 movwf SSPSTAT ;T Used to be sspstat on older PICs movlw 0x0020 ;T SSPCON1 bit5 SSPEN = 1 Enables sycn serial port ;T SSPCON1 bit4 = CKP = 0 ;T SSPCON1 bit3= 0 = Turn MSSP ON for SPI ;T SSPCON1 bit2-0 = 000b = SCLK = Fosc/4 ;T SSPCON1 bit2 = 0 = Master movwf SSPCON1 ;T Used to be sspcon on older PICs bsf INTCON,PEIE ;T INTCON bit6 = PEIE = 1 = Enable periph interrupt bsf PIE1,SSPIE ;T PIE1 bit3 = SSPIE = 1 = interrupt enable movlw 0x00 ;T load 0x00 into W movwf tcount ;T initialize tcount to zero (0x00) ;****************************************************************************** HWSPI_W_configure ;Configure SPI Mode ; ;On Entry: WREG = confDATA ;On Exit: ;On Success: return with C flag clear ;On Failure: return with C flag set ; bcf SSPCON1,SSPEN ;T Disable the MSSP, SSPCON1-5 movwf temp ;T move the confDATA byte to temp btfsc SSPCON1,SSPM3 ;T In SPI Mode?, skip if yes call HWSPI_init ;T MSSP is in wrong mode, Init for SPI ; btfsc temp,1 ;T Is bit1 of confDATA byte clear? if so skip next goto CPOL_1 ;T goto CPOL = 1 label => CPOL = 1 btfsc temp,0 ;T Is bit0 of confDATA byte clear? if so skip next ;T => CPOL = 0 , CPHA = ? goto CPOLCPHA_01 ;T goto => CPOL = 0 CPHA = 1 ;Configure for CPOL = 0, CPHA = 0 bcf SSPCON1,CKP ;T SSPCON1 bit4 = CKP = 0 bsf SSPSTAT,CKE ;T SSPSTAT bit6 = CKE = 1 btfsc SSPCON1,CKP ;T Is SSPCON1 bit4 = CKP = 0 ? goto badjump ;T CKP bit test error btfss SSPSTAT,CKE ;T Is SSPSTAT bit6 = CKE = 1 ? goto badjump ;T CKE bit test error goto okjump2 ;OK configured! ; CPOL_1 btfsc temp,0 ;T Is bit0 of confDATA byte clear? if so skip next ;T CPOL = 1 , CPHA = ? goto CPOLCPHA_11 ;T goto => CPOL = 1, CPHA = 1 ;Configure for CPOL = 1, CPHA = 0 bsf SSPCON1,CKP ;T SSPCON1 bit4 = CKP = 1 bsf SSPSTAT,CKE ;T SSPSTAT bit6 = CKE = 1 btfss SSPCON1,CKP ;T Is SSPCON1 bit4 = CKP = 1 ? goto badjump ;T CKP bit test error btfss SSPSTAT,CKE ;T Is SSPSTAT bit6 = CKE = 1 ? goto badjump ;T CKE bit test error goto okjump2 ;OK configured! ; CPOLCPHA_01 ;configure for CPOL = 0, CPHA = 1 bcf SSPCON1,CKP ;T SSPCON1 bit4 = CKP = 0 bcf SSPSTAT,CKE ;T SSPSTAT bit6 = CKE = 0 btfsc SSPCON1,CKP ;T Is SSPCON1 bit4 = CKP = 0 ? goto badjump ;T CKP bit test error btfsc SSPSTAT,CKE ;T Is SSPSTAT bit6 = CKE = 0 ? goto badjump ;T CKE bit test error goto okjump2 ;OK configured! ; CPOLCPHA_11 ;configure for CPOL = 1, CPHA = 1 bsf SSPCON1,CKP ;T SSPCON1 bit4 = CKP = 1 bcf SSPSTAT,CKE ;T SSPSTAT bit6 = CKE = 0 btfss SSPCON1,CKP ;T Is SSPCON1 bit4 = CKP = 1 ? goto badjump ;T CKP bit test error btfsc SSPSTAT,CKE ;T Is SSPSTAT bit6 = CKE = 0 ? goto badjump ;T CKE bit test error goto okjump2 ;OK configured! ; okjump2 bsf SSPCON1,SSPEN ;T Re-enable MSSP goto clear_cf_ok return badjump bsf SSPCON1,SSPEN ;T Re-enable MSSP goto set_cf_error ;T configuration error return ;****************************************************************************** HWSPI_W_speed ;On Entry: WREG = speedDATA & checks SSPCON1-3 for SPI mode ; speedDATA = 0x00 => Fosc/4 ; speedDATA = 0x01 => Fosc/16 ; speedDATA = 0x02 => Fosc/64 ; speedDATA = 0x03 => Timer Divisor (Not working yet) ; ;On Exit: ;On Success: return with C flag clear ;On Failure: return with C flag set ; bcf SSPCON1,SSPEN ;T Disable MSSP movwf speedLbyte ;T move speedDATA stored in W to speedLbyte btfsc SSPCON1,SSPM3 ;T In SPI Mode?, skip if yes call HWSPI_init ;T MSSP is in wrong mode, Init for SPI ; ;Test if speedLbyte = 0x00. If yes, SPI clock speed = Fosc/4 movlw 0x00 ;T load 0x00 into W subwf speedLbyte,W ;T subtract 0x00 from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto fdiv16 ;T goto Fosc/16 section bcf SSPCON1,SSPM1 ;T SSPCON1-1 = 0 bcf SSPCON1,SSPM0 ;T SSPCON1-0 = 0 goto okjump3 ;T Fosc/4 was selected ;Test if speedLbyte = 0x01. If yes, SPI clock speed = Fosc/16 fdiv16 movlw 0x01 ;T load 0x01 into W subwf speedLbyte,W ;T subtract 0x01 from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto fdiv64 ;T goto Fosc/64 section bcf SSPCON1,SSPM1 ;T SSPCON1-1 = 0 bsf SSPCON1,SSPM0 ;T SSPCON1-0 = 1 goto okjump3 ;T Fosc/16 was selected ;Test if speedLbyte = 0x02. If yes, SPI clock speed = Fosc/64 fdiv64 movlw 0x02 ;T load 0x02 into W subwf speedLbyte,W ;T subtract 0x02 from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto timer ;T goto Timer section bsf SSPCON1,SSPM1 ;T SSPCON1-1 = 1 bcf SSPCON1,SSPM0 ;T SSPCON1-0 = 0 goto okjump3 ;T Fosc/64 was selected ;Test if speedLbyte >= 0x03. If yes, SPI clock speed will be set by the timer ;SETTING THE SPI CLOCK WITH THE TIMER WILL RETURN A FAILURE AT THIS TIME. ;Future To do: Implement the TIMER section timer movlw 0x03 ;T load 0x02 into W subwf speedLbyte,W ;T subtract 0x02 from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto badjmp2 ;T goto error section to return failure goto badjmp2 ;T goto error section to return failure ; bsf SSPCON1,SSPM1 ;T SSPCON1-1 = 1 ; bsf SSPCON1,SSPM0 ;T SSPCON1-0 = 1 ; goto okjump3 ;T Fosc/64 was selected okjump3 bsf SSPCON1,SSPEN ;T Re-enable MSSP bcf STATUS,C ;T clear c flag on success return badjmp2 bsf SSPCON1,SSPEN ;T Re-enable MSSP bsf STATUS,C ;T set c flag on failure return ;****************************************************************************** HWSPI_W_spidata_W ;Simultaneously write SPI data on MOSI and read SPI data on MISO ; ;on Entry: WREG = mosiDATA & checks bit3 of SSPCON1 for SPI mode ;On Exit: WREG = misoDATA ;On Success: return with C flag clear ;On Failure: return with C flag set ; movwf temp2 ;T move mosiDATA stored in W to WREG_TEMP btfsc SSPCON1,SSPM3 ;T In SPI Mode?, skip if yes call HWSPI_init ;T MSSP is in wrong mode, Init for SPI movf temp2,W ;T load W with original mosiDATA ; movwf SSPBUF ;T move byte to transmit to SSPBUF (transmit buffer) movlw 0x00 ;T load 0x00 into W movwf tcount ;T initialize tcount to zero (0x00) again1 btfsc SSPSTAT,BF ;T receive completed? if no, skip next goto okjump1 ;T no. goto again incf tcount,F ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,W ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto again1 ;T loop until timeout goto set_cf_error ;T receive timeout error return okjump1 movf SSPBUF,W ;T put received data in W goto clear_cf_ok return ;****************************************************************************** ; UART routine asyxmtc bcf PORTC,xmit ;T used to be portc,xmit call full movlw 0x08 ;TEST_T "08" movwf bitctr asyxmt1 rrcf xmtreg,f btfsc STATUS,C goto asyxmt2 bcf PORTC,xmit ;T used to be portc,xmit goto asyxmt3 asyxmt2 bsf PORTC,xmit ;T used to be portc,xmit ; asyxmt3 call full decfsz bitctr,f goto asyxmt1 ; bsf PORTC,xmit ;T used to be portc,xmit call full retlw 0 ;****************************************************************************** ; UART baud rate of 115.2kbps using a 40MHz System Clock full movlw d'3' movwf cntrb vdly0 movlw d'6' ; d'43' with 4MHz => 2400 baud movwf cntra vdly1 decfsz cntra,f goto vdly1 decfsz cntrb,f goto vdly0 retlw 0 ;****************************************************************************** ;End of program END
表1. 4つのすべてのDACのセトリング時間を3µsに設定する設定書き込みコマンド
SPI Line | C7 | C6 | C5 | C4 | C3 | C2 | C1 | C0 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
DIN | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
表2. すべてのDAC出力をロードするコマンド
SPI Line | C3 | C2 | C1 | C0 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
DIN (1st) | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
DIN (2nd) | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
表2では、最初のコマンドですべてのDAC出力をゼロスケールに設定し、2つ目のコマンドですべてのDAC出力をフルスケールに設定します。
{{modalTitle}}
{{modalDescription}}
{{dropdownTitle}}
- {{defaultSelectedText}} {{#each projectNames}}
- {{name}} {{/each}} {{#if newProjectText}}
-
{{newProjectText}}
{{/if}}
{{newProjectTitle}}
{{projectNameErrorText}}