📄 dac_ctrl.rmh
字号:
// #418: ;when appropriate.// #419: ;// #420: ;Entry to this routine assumes that register s0 defines the state of the SPI// #421: ;control signals including SCK which should be Low. The easiest way to achieve this is// #422: ;to use the SPI_init routine before calling this one for the first time.// #423: ;// #424: ;As a 'master' the signal sequence is as follows..// #425: ; Transmit data bit on SDO line// #426: ; Drive SCK transition from low to high// #427: ; Receive data bit from SDI line (D/A transmits on previous falling edge)// #428: ; Drive SCK transition from high to low.// #429: ;// #430: ;Important note// #431: ; The received data bit must be captured some time before SCK goes low.// #432: ; However the combination of relatively slow clock to output time of the// #433: ; LTC2624 combined with the low drive strength of its SDO output means that// #434: ; the received bit needs maximum time to settle. Therefore this routine// #435: ; schedules the read as late as it can.// #436: ;// @07a #437: [SPI_dac_tx_rx]00108 // @07a #437: LOAD(s1,8) ;8-bits to transmit and receive// @07b #438: [next_SPI_dac_bit]2c204 // @07b #438: OUTPUT(s2,SPI_output_port) ;output data bit ready to be used on rising edge0e001 // @07c #439: XOR(s0,SPI_sck) ;clock High (bit0)2c008 // @07d #440: OUTPUT(s0,SPI_control_port) ;drive clock High0e001 // @07e #441: XOR(s0,SPI_sck) ;prepare clock Low (bit0)04301 // @07f #442: INPUT(s3,SPI_input_port) ;read input bit12380 // @080 #443: TEST(s3,SPI_sdi) ;detect state of received bit20200 // @081 #444: SLA(s2) ;shift new data into result and move to next transmit bit2c008 // @082 #445: OUTPUT(s0,SPI_control_port) ;drive clock Low1c101 // @083 #446: SUB(s1,1) ;count bits3547b // @084 #447: JUMP(NZ,next_SPI_dac_bit) ;repeat until finished2a000 // @085 #448: RETURN// #449: ;// #450: ;// #451: ;// #452: ;Set a voltage on one of the LTC2624 D/A converter outputs// #453: ;// #454: ;The D/A converter has 4 channels. Specify which channel is to be set using// #455: ;register sC as follows....// #456: ; sC Channel Nominal Voltage Range// #457: ; 00 A 0 to 3.30v (or VREFAB)// #458: ; 01 B 0 to 3.30v (or VREFAB)// #459: ; 02 C 0 to 2.50v (or VREFCD)// #460: ; 03 D 0 to 2.50v (or VREFCD)// #461: ; 0F All channels various as above.// #462: ;// #463: ;The analogue level is a 12-bit value to be supplied in lower 12-bits of register// #464: ;pair [sB,sA]. If this value is called 'k' and is in the range 0 to 4095 (000 to FFF)// #465: ;then// #466: ; Vout = (k/4096) * VREFx// #467: ;Hence it is not possible to reach the absolute level of the reference.// #468: ;// #469: ;Here are some useful values..// #470: ; Voltage A or B C or D// #471: ; 0.0 000 000// #472: ; 0.5 26D 333// #473: ; 0.65 327 A/D reference -1.00v// #474: ; 1.0 4D9 666// #475: ; 1.5 746 99A// #476: ; 1.65 800 A8F converter reference = 3.3/2 = 1.65v// #477: ; 2.0 9B2 CCD// #478: ; 2.5 C1F FFF// #479: ; 2.65 CD9 A/D reference +1.00v// #480: ; 3.0 E8C n/a// #481: ; 3.3 FFF n/a// #482: ;// #483: ;Note that the full scale deflection of FFF will result in different output// #484: ;voltages due to different reference voltages for each pair of channels.// #485: ;// #486: ;SPI communication with the DAC only requires a 24-bit word to be transmitted.// #487: ;However, the device internally contains a 32-bit shift register. When writing// #488: ;a command word, the previous contents are shifted out and can be observed by// #489: ;the master (Spartan-3E in this case). If you do not use a 32-bit format, then// #490: ;the read back is confusing. Hence this routine uses a 32-bit format by transmitting// #491: ;a dummy byte first.// #492: ;// #493: ; Byte 1 = 00 8 dummy bits// #494: ; Byte 2 = 3c Command nibble (3=write and update) and channel selection// #495: ; Byte 3 = dd Upper 8-bits of the 12-bit voltage value// #496: ; Byte 4 = d0 lower 4-bits of the 12-bit voltage value and 4 dummy bits.// #497: ;// #498: ;At the end of this communication, the register set [s9,s8,s7,s6] will contain the// #499: ;data received back from the D/A converter which should be the previous command.// #500: ;// @086 #501: [set_dac]30077 // @086 #501: CALL(SPI_init) ;ensure known state of bus and s0 register0e020 // @087 #502: XOR(s0,SPI_dac_cs) ;select low on D/A converter2c008 // @088 #503: OUTPUT(s0,SPI_control_port)00200 // @089 #504: LOAD(s2,0) ;Write dummy byte to DAC3007a // @08a #505: CALL(SPI_dac_tx_rx)01920 // @08b #506: LOAD(s9,s2) ;capture response012c0 // @08c #507: LOAD(s2,sC) ;Select channel for update0a20f // @08d #508: AND(s2,15) ;isolate channel bits to be certain of correct command0c230 // @08e #509: OR(s2,48) ;Use immediate Write and Update command is "0011"3007a // @08f #510: CALL(SPI_dac_tx_rx)01820 // @090 #511: LOAD(s8,s2) ;capture response20a06 // @091 #512: SL0(sA) ;data shift bits into correct position20b00 // @092 #513: SLA(sB) ;with 4 dummy bits ('0') in the least significant bits.20a06 // @093 #514: SL0(sA)20b00 // @094 #515: SLA(sB)20a06 // @095 #516: SL0(sA)20b00 // @096 #517: SLA(sB)20a06 // @097 #518: SL0(sA)20b00 // @098 #519: SLA(sB)012b0 // @099 #520: LOAD(s2,sB) ;Write 12 bit value followed by 4 dummy bits3007a // @09a #521: CALL(SPI_dac_tx_rx)01720 // @09b #522: LOAD(s7,s2) ;capture response012a0 // @09c #523: LOAD(s2,sA)3007a // @09d #524: CALL(SPI_dac_tx_rx)01620 // @09e #525: LOAD(s6,s2) ;capture response0e020 // @09f #526: XOR(s0,SPI_dac_cs) ;deselect the D/A converter to execute2c008 // @0a0 #527: OUTPUT(s0,SPI_control_port)2a000 // @0a1 #528: RETURN// #529: ;// #530: ;Perform a hard reset of the D/A converter// #531: ;// @0a2 #532: [dac_reset]30077 // @0a2 #532: CALL(SPI_init) ;ensure known state of bus and s0 register0e080 // @0a3 #533: XOR(s0,SPI_dac_clr) ;pulse the clear signal.2c008 // @0a4 #534: OUTPUT(s0,SPI_control_port)0e080 // @0a5 #535: XOR(s0,SPI_dac_clr)2c008 // @0a6 #536: OUTPUT(s0,SPI_control_port)2a000 // @0a7 #537: RETURN// #538: ;// #539: ;// #540: ;**************************************************************************************// #541: ;Software delay routines// #542: ;**************************************************************************************// #543: ;// #544: ;// #545: ;// #546: ;Delay of 1us.// #547: ;// #548: ;Constant value defines reflects the clock applied to KCPSM3. Every instruction// #549: ;executes in 2 clock cycles making the calculation highly predictable. The '6' in// #550: ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code.// #551: ;// #552: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz// #553: ;// #554: ;Registers used s0// #555: ;// @0a8 #556: [delay_1us]0000b // @0a8 #556: LOAD(s0,delay_1us_constant)// @0a9 #557: [wait_1us]1c001 // @0a9 #557: SUB(s0,1)354a9 // @0aa #558: JUMP(NZ,wait_1us)2a000 // @0ab #559: RETURN// #560: ;// #561: ;Delay of 40us.// #562: ;// #563: ;Registers used s0, s1// #564: ;// @0ac #565: [delay_40us]00128 // @0ac #565: LOAD(s1,40) ;40 x 1us = 40us// @0ad #566: [wait_40us]300a8 // @0ad #566: CALL(delay_1us)1c101 // @0ae #567: SUB(s1,1)354ad // @0af #568: JUMP(NZ,wait_40us)2a000 // @0b0 #569: RETURN// #570: ;// #571: ;// #572: ;Delay of 1ms.// #573: ;// #574: ;Registers used s0, s1, s2// #575: ;// @0b1 #576: [delay_1ms]00219 // @0b1 #576: LOAD(s2,25) ;25 x 40us = 1ms// @0b2 #577: [wait_1ms]300ac // @0b2 #577: CALL(delay_40us)1c201 // @0b3 #578: SUB(s2,1)354b2 // @0b4 #579: JUMP(NZ,wait_1ms)2a000 // @0b5 #580: RETURN// #581: ;// #582: ;Delay of 20ms.// #583: ;// #584: ;Delay of 20ms used during initialisation.// #585: ;// #586: ;Registers used s0, s1, s2, s3// #587: ;// @0b6 #588: [delay_20ms]00314 // @0b6 #588: LOAD(s3,20) ;20 x 1ms = 20ms// @0b7 #589: [wait_20ms]300b1 // @0b7 #589: CALL(delay_1ms)1c301 // @0b8 #590: SUB(s3,1)354b7 // @0b9 #591: JUMP(NZ,wait_20ms)2a000 // @0ba #592: RETURN// #593: ;// #594: ;Delay of approximately 1 second.// #595: ;// #596: ;Registers used s0, s1, s2, s3, s4// #597: ;// @0bb #598: [delay_1s]00414 // @0bb #598: LOAD(s4,20) ;50 x 20ms = 1000ms// @0bc #599: [wait_1s]300b6 // @0bc #599: CALL(delay_20ms)1c401 // @0bd #600: SUB(s4,1)354bc // @0be #601: JUMP(NZ,wait_1s)2a000 // @0bf #602: RETURN// #603: ;// #604: ;// #605: ;// #606: ;**************************************************************************************// #607: ;Interrupt Service Routine (ISR)// #608: ;**************************************************************************************// #609: ;// #610: ;Interrupts occur at a rate of 8KHz.// #611: ;// #612: ;Each interrupt is the fundamental timing trigger used to set the sample rate and// #613: ;it is therefore use to set the D/A outputs by copying the values stored in// #614: ;scratch pad memory and outputting them to the D/A converter using the SPI bus.// #615: ;// #616: ;Because the SPI communication is in itself a predictable process, the sample rate// #617: ;is preserved without sample jitter. All variable activities are left to the main// #618: ;program.// #619: ;// #620: ;Each time PicoBlaze transmits a 32-bit command word to the D/A converter, the// #621: ;D/A responds with the last command it was sent. So as the end of this service routine// #622: ;the register set [s9,s8,s7,s6] will contain the command which has just been sent// #623: ;for the setting of channel C.// #624: ;// #625: ;Set channel A// #626: ;// @0c0 #627: [ISR]00c00 // @0c0 #627: LOAD(sC,0) ;channel A06b01 // @0c1 #628: FETCH(sB,chan_A_msb) ;12-bit value06a00 // @0c2 #629: FETCH(sA,chan_A_lsb)30086 // @0c3 #630: CALL(set_dac)// #631: ;// #632: ;Set channel B// #633: ;00c01 // @0c4 #634: LOAD(sC,1) ;channel B06b03 // @0c5 #635: FETCH(sB,chan_B_msb) ;12-bit value06a02 // @0c6 #636: FETCH(sA,chan_B_lsb)30086 // @0c7 #637: CALL(set_dac)// #638: ;// #639: ;Set channel C// #640: ;00c02 // @0c8 #641: LOAD(sC,2) ;channel C06b05 // @0c9 #642: FETCH(sB,chan_C_msb) ;12-bit value06a04 // @0ca #643: FETCH(sA,chan_C_lsb)30086 // @0cb #644: CALL(set_dac)// #645: ;// #646: ;Set channel A// #647: ;00c03 // @0cc #648: LOAD(sC,3) ;channel D06b07 // @0cd #649: FETCH(sB,chan_D_msb) ;12-bit value06a06 // @0ce #650: FETCH(sA,chan_D_lsb)30086 // @0cf #651: CALL(set_dac)// #652: ;00f00 // @0d0 #653: LOAD(sF,0) ;clear flag38001 // @0d1 #654: RETURNI(ENABLE)// #655: ;// #656: ;// #657: ;**************************************************************************************// #658: ;Interrupt Vector// #659: ;**************************************************************************************// #660: ;@3ff // #661: ADDRESS(1023)340c0 // @3ff #662: JUMP(ISR)// #663: ;// #664: ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -