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)、两个按键开关、增益设置电阻和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设计基础-基本概念