应用笔记 3497

MAX5581接口: MAX5581快速建立DAC与PIC微控制器的接口


摘要 : 本应用笔记介绍MAX5581 DAC与PIC®微控制器的配合使用,给出了详细的电路图和源代码。

MAX5581简介

MAX5581是一款12位、快速建立DAC,采用3线SPI™串行接口。MAX5581的接口支持高达20MHz的SPI,最快建立时间为3µs。本应用笔记给出了连接高速PIC微控制器(PIC18F核)和MAX5581 DAC的应用电路以及所需要的全部固件。汇编程序利用MPLAB IDE、6.10.0.0版本中免费提供的编译器编写,用于PIC18F442。

硬件说明

这里讨论的应用电路采用了MAX5581评估板,包括:MAX5581、超高精度电压基准(MAX6126)、两个按键开关、增益设置电阻和PCB。PIC18F442没有安装在MAX5581EVKIT板上,但已添加到系统中,图1所示是一个完整的应用电路。MAX5581EVKIT上的/CS、SCLK、DIN和DOUT焊盘便于SPI串行接口的连接。

图1. MAX5581应用电路第一部分
查看大图

图1. MAX5581应用电路第一部分

图1. MAX5581应用电路第二部分
图1. MAX5581应用电路第二部分

模拟与数字地平面

将模拟地与数字地分离开(如图2所示)可以得到较好的实际效果,利用铁氧体磁珠,如TDK MMZ1608B601C,连接两个地平面。这种布局可以避免微控制器系统时钟及其谐波成份馈入模拟地。已知PIC18F442的系统时钟为40MHz,考虑到MMZ1608B601C特殊的阻抗与频率特性,我们选择了这款铁氧体磁珠。图3给出了MMZ1608B601C阻抗随频率的变化曲线。

图2. 分离的模拟地和数字地
图2. 分离的模拟地和数字地

图3. TDK MMZ1608B601C铁氧体磁珠阻抗随频率的变化曲线
图3. TDK MMZ1608B601C铁氧体磁珠阻抗随频率的变化曲线

固件说明

列表1给出的汇编程序通过PIC18F442的内部MSSP SPI接口对MAX5581进行初始化,PIC18F442的40MHz系统时钟允许MSSP提供高达10MHz的SPI时钟(SCLK)。表1所示为上电后的配置字。一旦完成了对MAX5581的初始化,程序便将DAC输出寄存器装载为零,然后装载满量程输出,如表2所示。该固定循环程序可产生方波输出,如图4所示,可以用来演示MAX5581的快速建立时间。

图4. 一个输出为80kHz方波的实际示波器测试图
图4. 一个输出为80kHz方波的实际示波器测试图

列表1. 用于连接MAX5581和PIC18F442内部MSSP SPI接口的汇编程序

下载: P18F442.INC

列表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. 配置写命令,将所有四路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输出设置为零,第二个命令将所有DAC设置为满量程输出。
下一步
EE-Mail 订阅EE-Mail,接收关于您感兴趣的新文档的自动通知。
© , Maxim Integrated Products, Inc.
The content on this webpage is protected by copyright laws of the United States and of foreign countries. For requests to copy this content, contact us.
APP 3497:
应用笔记 3497,AN3497, AN 3497, APP3497, Appnote3497, Appnote 3497