di2968.txt ;***************************************************************************** ; ; "Make a DAC with a microcontroller's PWM timer," EDN, September 5, 2002, pg 110 ; ; ; THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR ; REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, ; INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ; FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR ; COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. ; TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET ; POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY ; INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR ; YOUR USE OF THE PROGRAM. ; ; IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, ; CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY ; THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED ; OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT ; OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. ; EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF ; REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS ; OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF ; USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S ; AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF ; YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS ; (U.S.$500). ; ; Unless otherwise stated, the Program written and copyrighted ; by Texas Instruments is distributed as "freeware". You may, ; only under TI's copyright in the Program, use and modify the ; Program without any charge or restriction. You may ; distribute to third parties, provided that you transfer a ; copy of this license to the third party and the third party ; agrees to these terms by its first use of the Program. You ; must reproduce the copyright notice and any other legend of ; ownership on each copy or partial copy, of the Program. ; ; You acknowledge and agree that the Program contains ; copyrighted material, trade secrets and other TI proprietary ; information and is protected by copyright laws, ; international copyright treaties, and trade secret laws, as ; well as other intellectual property laws. To protect TI's ; rights in the Program, you agree not to decompile, reverse ; engineer, disassemble or otherwise translate any object code ; versions of the Program to a human-readable form. You agree ; that in no event will you alter, remove or destroy any ; copyright notice included in the Program. TI reserves all ; rights not specifically granted under this license. Except ; as specifically provided herein, nothing in this agreement ; shall be construed as conferring by implication, estoppel, ; or otherwise, upon you, any license or other right under any ; TI patents, copyrights or trade secrets. ; ; You may not use the Program in non-TI devices. NAME PWMDAC ;**************************************************************************** ; PWM DAC Demonstratin Program ; Generate a 250Hz sine wave using PWM timer Timer_B. ; ; Description: This program demonstrates the usage of a PWM timer together ; with external filters to implement a DAC. The program shows how to ; create a 250Hz sine wave, a 125Hz ramp, and a DC level with Timer_B. ; Timer_A could also be used in the same manner. A sine table holds the ; sample values for the sinusoid. To create the ramp, the PWM value is ; simply incremented. The DC level is created by storing charge on an ; RC network using a PWM output to provide the charge. The value of the DC ; voltage directly corresponds to the duty cycele of the PWM signal. After ; initialization, the CPU is put into LPM0. It remains there until the ; CCIFG0 interrupt from Timer_B wakes it up. In the Timer_B ISR, the next ; value for the sinusoid is loaded into CCR1 and the ramp value is incremented ; and loded into CCR2. Upon return form the ISR, the CPU goes back into LPM0. ; ; Mike Mitchell ; MSP430 Applications ; Texas Instruments, Inc ; ;**************************************************************************** #include "MSP430X14x.H" ; Include Standard Defs Delta EQU 250 ; Delta = Target DCO/8192 ; Target DCO frequency = 2.048MHz ; This value is used in the ; software FLL routine to ; calibrate the DCO frequency ; using the 32768Hz oscillator ; as a reference. For more ; information on stabilizing ; the DCO or the FLL routine ; see the application report ; titled "Controlling the DCO ; frequency of the MSP430x11x" ; Literature number SLAA074 ;----------------------------------------------------------------------------- RSEG CODE ;----------------------------------------------------------------------------- Sine_Tab DW 255 ; Sine Table. These are the count DW 254 ; values in decimal that will DW 246 ; go into TBCCR1 to change the DW 234 ; PWM duty cycle. DW 219 ; Must use words instead of bytes DW 199 ; because must move words into DW 177 ; TB registers. DW 153 ; Don't use a '0' as a sample value DW 128 ; The timer will glitch. DW 103 DW 79 DW 57 DW 37 DW 22 DW 10 DW 2 DW 1 DW 2 DW 10 DW 22 DW 37 DW 57 DW 79 DW 103 DW 128 DW 153 DW 177 DW 199 DW 219 DW 234 DW 246 DW 255 ;----------------- Code Starts Here -------------------------------------- RESET mov #09FEh,SP ; Initialize stackpointer StopWDT mov #WDTPW+WDTHOLD,&WDTCTL ; Stop WDT SetupP4 bis.b #00Eh,&P4SEL ; Select TB1, TB2, TB3 instead of bis.b #00Eh,&P4DIR ; P4.x, and set as outputs SetupBC mov.b #0A6h,&BCSCTL1 ; ACLK is divided by 4. RSEL=6, ; no division for MCLK or SMCLK, ; DCO sources MCLK and SMCLK. ; XT2 is off. ; NOTE: To determine the value of ; Rsel for a desired DCO frequency, ; refer to the DCO table in the ; datasheet. call #Delay ; Delay for crystal stabilization. ; Need to put a delay here because ; the 32768Hz crystal is used as ; a reference to stabilize the DCO ; frequency. Therefore, the 32768 ; crystal needs to be stable. call #SW_FLL ; Call the routine to Stabilize ; the DCO clock. call #TB_SETUP ; Setup Timer_B for PWM generation clr R15 ; R15 and R14 used as pointers clr R14 ; to the sine table and to hold the ; ramp value after the DCO is ; stabilized eint ; Enable interrupts bis #LPM0,SR ; Put CPU to sleep. ; This is the end of the program ; except for handling the CCIFG0 ; interrupt, which is where the ; PWM values are updated. ;----------------------------------------------------------------------------- Delay; Software delay for crystal stabilization ;----------------------------------------------------------------------------- mov #0004h,R15 L1 mov #0FFFFh,R14 ; This should ideally be about a sec. L2 dec R14 ; jnz L2 ; ; dec R15 ; jnz L1 ; ret ; ; ;----------------------------------------------------------------------------- SW_FLL; Subroutine: Stabilizes DCO frequency. ; This routine uses the 32768Hz crystal oscillator as a reference ; frequency to stabilize and trim the DCO oscillator to the desired ; frequency of 2.048MHz. ;----------------------------------------------------------------------------- clr R15 ; Setup_TA mov #TASSEL1+TACLR,&TACTL ; SMCLK clocks TA Setup_CC2 mov #CCIS0+CM0+CAP,&CCTL2 ; Define CCR2,CAP,ACLK bis #MC1,&TACTL ; Start timer_A: Continous Mode Test_DCO bit #CCIFG,&CCTL2 ; Test capture flag jz Test_DCO ; bic #CCIFG,&CCTL2 ; Clear capture flag ; AdjDCO mov &CCR2,R14 ; R14 = captured SMCLK sub R15,R14 ; R14 = capture difference mov &CCR2,R15 ; R15 = captured SMCLK cmp #Delta,R14 ; Delta = SMCLK/(32768/4) jlo IncDCO ; jeq DoneFLL ; DecDCO dec.b &DCOCTL ; jmp Test_DCO ; IncDCO inc.b &DCOCTL ; jmp Test_DCO ; DoneFLL clr &CCTL2 ; Stop CCR2 clr &TACTL ; Stop timer_A ret ; Return from subroutine ;----------------------------------------------------------------------------- TB_SETUP; Subroutine: Setup Timer_B for PWM generation ;----------------------------------------------------------------------------- mov #TBSSEL1+TBCLR,&TBCTL ; SMCLK clocks TB. mov #CCIE,&TBCCTL0 ; Set CCR0 in compare mode, enable ; it's interrupt mov #0FFh,&TBCCR0 ; Put 255d in CCR0. This will set ; the period of the PWM output to ; 256 counts(8-bits). This gives ; an 8-bit DAC. mov #02E0h,&TBCCTL1 ; Set CCRx in compare mode, disable mov #02E0h,&TBCCTL2 ; interrupt, set outmode to '7' which mov #02E0h,&TBCCTL3 ; is reset/set. EQU0 sets the output ; EQU1 will reset it. Set the load ; condition for the compare latch ; to be when the counter counts to ; 0. mov #Sine_Tab,&TBCCR1 ; Load first sample value into CCR1 mov #01h,R14 ; Load inital ramp value into R14. mov #0AAh,&TBCCR3 ; This is for the DC value. It will ; result in a voltage of approximately ; 2/3 Vcc because #0AAh is 2/3 of ; #0FFh. bis #MC0,&TBCTL ; Start timer_B in up mode ret ;----------------------------------------------------------------------------- TB_ISR; Timer_B ISR: changes the value in the CCR1 and CCR2 registers to ; vary the PWM for the sinusoid and the ramp. The CCR3 value is left ; unchanged for the DC signal. ;----------------------------------------------------------------------------- incd R15 ; Increment the pointer R15 to ; to point to next word of sine ; table. Must increment by 2 ; because the sine table is words ; not bytes. and #03Fh,R15 ; ANDing with 03Fh gives an ; effective modulo 32 counter for ; pointing to each value in the ; sine table mov Sine_Tab(R15),&TBCCR1 ; Move new sine value to CCR1 add #04h,R14 ; Increment ramp value. ; Changing the step size in R14 ; will change the frequency of ; the ramp. and #0FFh,R14 ; And off unwanted bits mov R14,&TBCCR2 ; Move new ramp value to CCR2 reti ; return with interrupts enabled ;--------------------------------------------------------------------------- COMMON INTVEC ; MSP430x14x interrupt vectors ;--------------------------------------------------------------------------- ORG TIMERB0_VECTOR DW TB_ISR ; CCIFG0 interrupt ORG RESET_VECTOR DW RESET ; POR, ext. Reset, Watchdog END