摘要:本应用笔记介绍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)、两个按键开关、增益设置电阻和pc板。pic18f442没有安装在max5581evkit板上,但已添加到系统中,图1所示是一个完整的应用电路。max5581evkit上的/cs、sclk、din和dout焊盘便于spi串行接口的连接。
查看大图
图1. max5581应用电路第一部分
图1. max5581应用电路第二部分
模拟与数字地平面将模拟地与数字地分离开(如图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的初始化,程序便将dac输出寄存器装载为零,然后装载满量程输出,如表2所示。该固定循环程序可产生方波输出,如图4所示,可以用来演示max5581的快速建立时间。
图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 wn c clear.
return ; error=> cf=set
;******************************************************************************
clear_cf_ok
movlw 0x01 ; 0x00 into w
sublw 0x00 ; subtract w-0x00: if wn 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 d 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设置为满量程输出。
一款“改装神器”将会如何开拓全球智能家居的市场
麦格纳四项黑科技入围车圈奥斯卡奖
箱式仓储机器人的新战事
惠普2020年成功逆袭联想成PC市场第一
你知道什么是Python吗
MAX5581快速建立DAC与PIC微控制器的接口
普渡科技和松下签署战略合作协议,共同擘画智能新时代
哈曼远程车辆更新服务OTA解决方案V11版本:有利于巩固远程车辆更新服务领导地位
城市无人驾驶小巴将引进中国
变压器的安装位置对电力传输有何影响?
数据治理体系完整实践指南
电力监控系统实现远程实时监控案例分析
深圳电梯五方对讲融合遇到危险可及时联系
噪声测量之Y参数法学习
3D手势识别掀动一场新的消费革命
变压器运行的检查_变压器的故障处理
聚灿光电宣布获1.13政府补助金
索尼发布两款新电视 分辨率最高达到8K
印度威胁苹果封网是怎么回事?苹果到底冤不冤?还要被欧盟砍一刀
PCB设计基础-基本概念