MSP430 Examples
Short Description
Download MSP430 Examples...
Description
Topics to Cov Co ver«
F2013 Blinky Example Lab 4: Blinky Lab Example 2: Interrupts w/Timer_A w/Timer_A Example 3: S/W PWM w/Timer_A Example 4: Watchdog W atchdog Clock Example 5: Watchdog PWM Example 6: SW Switch Debounce Example 7: Timer_B S/W PWM Recursive Line Draw
BYU CS/ECEn 124
MSP430 Examples
1
Systematic Decomposition
Blinky Example
F2013
;******************************************************************************* ; CS/ECEn 124 Lab 1 - blinky.asm: blinky.asm: Software Toggle P1.0 ;******************************************************************************* .cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 ;-----------------------------------------------------------------------------.text ; beginning of executable code ;-----------------------------------------------------------------------------RESET: mov.w #0x0280,SP ; init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL #WDTPW+WDTHOLD,& WDTCTL ; stop WDT bis.b #0x01,&P1DIR ; set P1.0 as output
mainloop:
delayloop:
xor.b mov.w
dec.w jnz jmp
#0x01,&P1OUT #0,r15
r15 delayloop mainloop
; toggle P1.0 ; use R15 as delay counter ; delay over? ; n ; y, toggle led
;-----------------------------------------------------------------------------; Interrupt Vectors ;-----------------------------------------------------------------------------.sect ".reset" ; MSP430 RESET Vector .short RESET ; start address .end
BYU CS/ECEn 124
MSP430 Examples
2
Systematic Decomposition
Add 2nd Delay Loop ;******************************************************************************* ; CS/ECEn CS/ECEn 124 Lab Lab 1 - blinky.asm: blinky.asm: Software Software Toggle Toggle P1.0 ;******************************************************************************* .cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 delay .set 0 ;-----------------------------------------------------------------------------.text ; beginning of executable code ;-----------------------------------------------------------------------------RESET: mov.w #0x0280,SP ; init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL #WDTPW+WDTHOLD,& WDTCTL ; stop WDT bis.b #0x01,&P1DIR ; set P1.0 as output
mainloop:
xor.b mov.w
#0x01,&P1OUT #delay,r15
; toggle P1.0 ; use R15 as delay counter
delayloop:
dec.w jnz
r15 delayloop
; delay over? ; n
delay2:
dec.w jnz jmp
r15 delay2 mainloop
; y, toggle led
;-----------------------------------------------------------------------------; Interrupt Vectors ;-----------------------------------------------------------------------------.sect ".reset" ; MSP430 RESET Vector .short RESET ; start address .end
BYU CS/ECEn 124
MSP430 Examples
3
Device: LED
LEDs
6 LED¶s on eZ430X Development Board
P1.0 P1.1 P2.6 P2.7 P3.3 P4.6
Red LED eZ430-RF2500 Green LED eZ430-RF2500 LED #1 (Green) LED #2 (Orange) LED #3 (Yellow) LED #4 (Red)
Port bits must be enabled for output by writing a 1 to the port direction register
bis.b bic.b bis.b bis.b bis.b bis.b
BYU CS/ECEn 124
#0x03,&P1DIR #0xc0,&P2SEL #0x40,&P2DIR #0x80,&P2DIR #0x08,&P3DIR #0x40,&P4DIR
; eZ430-RF2500 LED's ; select GPIO ; LED #1 (P2.6) ; LED #2 (P2.7) ; LED #3 (P3.3) ; LED #4 (P4.6) MSP430 Examples
4
Device: LED
LEDs
Turn LED off by writing a 0 to the port pin
#0x03,&P1OUT #0x40,&P2OUT #0x80,&P2OUT #0x08,&P3OUT #0x40,&P4OUT
; eZ430-RF2500 LED's ; LED #1 (P2.6) ; LED #2 (P2.7) ; LED #3 (P3.3) ; LED #4 (P4.6)
Turn LED on by writing a 1 to the port pin
bic.b bic.b bic.b bic.b bic.b bis.b bis.b bis.b bis.b bis.b
#0x03,&P1OUT #0x40,&P2OUT #0x80,&P2OUT #0x08,&P3OUT #0x40,&P4OUT
; eZ430-RF2500 LED's ; LED #1 (P2.6) ; LED #2 (P2.7) ; LED #3 (P3.3) ; LED #4 (P4.6)
Toggle LED by XOR¶ing a 1 to the port pin
xor.b xor.b xor.b xor.b xor.b
BYU CS/ECEn 124
#0x03,&P1OUT #0x40,&P2OUT #0x80,&P2OUT #0x08,&P3OUT #0x40,&P4OUT
; eZ430-RF2500 LED's ; LED #1 (P2.6) ; LED #2 (P2.7) ; LED #3 (P3.3) ; LED #4 (P4.6) MSP430 Examples
5
Lab 4: Blinky
Lab 4: Blinky Lab ;******************************************************************************* ; CS/ECEn 124 Lab 4 - blinky.asm ;******************************************************************************* ; cycles = --; MCLK = --- cycles / 10 seconds = --- Mhz ; CPI = MCLK / --; MIPS = MCLK / CPI / 1000000 = --- MIPS .cdecls C,LIST, "msp430x22x4.h" ; MSP430F2274 COUNT .equ 0 ; delay count ;-----------------------------------------------------------------------------.text ; beginning of executable code ;-----------------------------------------------------------------------------RESET: mov.w #0x0280,SP ; 2 init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL ;5 stop WDT bis.b #0x01,&P1DIR 4 set ; P1.0 as output
mainloop: delayloop:
xor.b #0x01,&P1OUT mov.w #COUNT,r15
dec.w jnz jmp
r15 delayloop mainloop
4 1 ; 1 ; 2 ; 2
;toggle P1.0 use; R15 as delay counter delay over? n y, toggle led
;-----------------------------------------------------------------------------; Interrupt Vectors ;-----------------------------------------------------------------------------.sect ".reset" ; MSP430 RESET Vector .short RESET ; start address .end
BYU CS/ECEn 124
MSP430 Examples
6
Activation Recor d
Example 1a: Activation Recor d DELAY
.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 4(SP) = delay count .equ (50/8) 2(SP) = return address 0(SP)
RESET:
= r 15
.text ; beginning of code mov.w #0x0280,SP ; init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop WDT bis.b #0x01,&P1DIR ; set P1.0 as output
mainloop: xor.b #0x01,&P1OUT push.w #DELAY call #delay jmp mainloop
; toggle P1.0 ; pass delay count on stack ; call delay subroutine
; delay subroutine: stack usage 4| DELAY | \ ; 2| ret | subroutine frame (6 bytes) ; (SP) => 0| r15 | / delay: push.w r15 ; callee-save mov.w #0,r15 ; use R15 as inner counter delay02:
dec.w r15 jne delay02 dec.w 4(SP) jne delay02 pop.w r15 mov.w @SP+,0(SP) ret .sect .word .end
BYU CS/ECEn 124
".reset" RESET
; ; ; ;
inner delay over? n y, outer done? n ; y, restore register(s) ; pop input delay count ; return from subroutine ; MSP430 RESET Vector ; start address
MSP430 Examples
7
Activation Recor d
Example 1b: Activation Recor d DELAY RESET:
.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 .equ (50/8) .text mov.w #0x0280,SP mov.w #WDTPW+WDTHOLD,&WDTCTL bis.b #0x01,&P1DIR
mainloop: xor.b #0x01,&P1OUT push.w #DELAY call #delay jmp mainloop
; delay subroutine: stack usage ; ; ; (SP) => delay: push.w r12 push.w r15 mov.w 6(SP),r12 mov.w #0,r15 delay02:
BYU CS/ECEn 124
dec.w r15 jne delay02 dec.w r12 jne delay02 pop.w r15 pop.w r12 mov.w @SP+,0(SP) ret .sect .word .end
".reset" RESET
6(SP) = delay count 4(SP) = return address 2(SP) = r 12 ; beginning of code 0(SP) = r 15 ; init stack pointer
; stop WDT ; set P1.0 as output
; toggle P1.0 ; pass delay count on stack ; call delay subroutine
6| DELAY | \ 4| ret | subroutine frame (8 bytes) 2| r12 | /(activation record) 0| r15 |/ ; callee-save ; get delay count ; use R15 as inner counter ; ; ; ;
delay over? n y, done? n ; y, restore registers
; pop input delay count ; return from subroutine
; MSP430 RESET Vector ; start address MSP430 Examples
8
Activation Recor d
Example 1c: Activation Recor d DELAY RESET:
.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 .equ (50/8)
4(SP) = delay count 2(SP) = return address 0(SP) = local variable
.text ; beginning of code mov.w #0x0280,SP ; init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop WDT bis.b #0x01,&P1DIR ; set P1.0 as output
mainloop: xor.b #0x01,&P1OUT push.w #DELAY call #delay jmp mainloop
; toggle P1.0 ; pass delay count on stack ; call delay subroutine
; delay subroutine: stack usage 4| DELAY | \ ; 2| ret | subroutine frame (6 bytes) ; (SP) => 0| counter | / delay: sub.w #2,SP ; activate local variable mov.w #0,0(SP) ; use as inner counter delay02:
dec.w jne dec.w jne add.w mov.w ret .sect .word .end
BYU CS/ECEn 124
0(SP) delay02 4(SP) delay02 #2,SP @SP+,0(SP)
; ; ; ; ;
delay over? n y, done? n y, deactivate local variable ; pop input delay count ; return from subroutine
".reset" RESET
; MSP430 RESET Vector ; start address MSP430 Examples
9
Blinky Example
Example 2: Interrupts w/Timer_A TASSEL_2 = SMCLK TA_CTL TA_FREQ
cdecls C,LIST, "msp430x20x3.h" .set TASSEL_2+ID_3+MC_1+TAIE .set 0xffff
MC_1 = UP Mode
; MSP430F2013 ; 000000 10 11 01 000 1 = SMCLK,/8,UP,IE ; clocks
ID_3 = /8 Enable Interrupt ;-----------------------------------------------------------------------------.text ; beginning of executable code RESET: mov.w #0x0280,SP ; init stack pointer mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop WDT bis.b #0x01,&P1DIR ; set P1.0 as output clr.w &TAR mov.w #TA_CTL,&TACTL mov.w #TA_FREQ,&TACCR0 bis.w #LPM0+GIE,SR jmp $ TA_isr:
bic.w #TAIFG,&TACTL xor.b #0x01,&P1OUT reti
; reset timerA ; set timerA control reg ; set interval (frequency) ; enter LPM0 w/interrupts
Put the processor to sleep!
; timer A ISR ; acknowledge interrupt ; toggle P1.0
Acknowledge Interrupt ;-----------------------------------------------------------------------------; Interrupt Vectors (Put its hand down) .sect ".int08" ; timer A section .word TA_isr ; timer A isr
.sect .word .end
BYU CS/ECEn 124
".reset" RESET
; MSP430 RESET Vector ; start address
MSP430 Examples
10
LED Intensity
Example 3: S /W PWM w/Timer_A .cdecls C,LIST,"msp430x20x3.h" .set 1200000 ; 1200000 clocks / second .set TASSEL_2+ID_0+MC_1+TAIE ; SMCLK, /1, UP, IE .set 120 ; FREQ / SMCLK = 0.0001 = 100 us
SMCLK TA_CTL TA_FREQ
RESET:
Acknowledge needed
TA_isr:
.bss cnt,2 .text mov.w #0x0280,SP mov.w #WDTPW+WDTHOLD,&WDTCTL bis.b #0x01,&P1DIR clr.w &TAR mov.w #TA_CTL,&TACTL mov.w #TA_FREQ,&TACCR0 bis.w #LPM0+GIE,SR jmp $ bic.w #TAIFG,&TACTL inc.w &cnt cmp.w #10,&cnt jlo TA_isr2 clr.w &cnt bis.b #0x01,&P1OUT jmp TA_isr4
TA_isr2: bic.b
#0x01,&P1OUT
TA_isr4: reti .sect .word .sect .short .end
BYU CS/ECEn 124
; counter variable ; init stack pointer ; stop watchdog ; set P1.0 as output ; reset timerA ; set timerA control reg ; set interval (frequency) ; enter LPM0 w/interrupts ; will never get here! ; acknowledge interrupt ; time to pulse? ; n ; y, reset counter ; turn on ; turn off ; return from interrupt
".int08" TA_isr ".reset" RESET
; ; ; ;
10% Duty
Cycle
timer A section timer A isr MSP430 RESET Vector start address
MSP430 Examples
11
Watchdog
Example 4: Watchdog Clock
SMCLK WDT_CTL WDT_CPS
.cdecls C,LIST,"msp430x20x3.h" .set 1200000 .set WDT_MDLY_8 .set SMCLK/8000
8 ms (@1 MHz SMCLK)
; 1.2 Mhz clock ; WDT SMCLK, 8 ms (@1 Mhz) ; WD clocks / second count
; Data Section -----------------------------------------------------------.bss WDTSecCnt,2 ; WDT second counter ; Code Section -----------------------------------------------------------.text RESET: mov.w #0x280,SP ; initialize stack pointer mov.w #WDT_CTL,&WDTCTL ; set WD timer interval mov.w #WDT_CPS,&WDTSecCnt ; initialize 1 sec WD counter bis.b #WDTIE,&IE1 ; enable WDT interrupt bis.b #0x01,&P1DIR ; P1.0 output bis.w #GIE,SR ; enable interrupts loop:
;> jmp loop
Enable WD Interrupts
; loop indefinitely
; Watchdog ISR -----------------------------------------------------------WDT_ISR: dec.w &WDTSecCnt ; decrement counter, 0? jne WDT_02 ; n mov.w #WDT_CPS,&WDTSecCnt ; y, re-initialize counter xor.b #0x01,&P1OUT ; toggle P1.0 WDT_02:
reti
; Interrupt Vectors .sect .word .sect No acknowledge .word d d nee e .end
BYU CS/ECEn 124
; return from interrupt
------------------------------------------------------".int10" ; Watchdog Vector WDT_ISR ; Watchdog ISR ".reset" ; PUC Vector RESET ; RESET ISR
MSP430 Examples
12
Speaker (Transducer )
Example 5: Watchdog PWM
WDT_CLK STACK
.cdecls C,LIST,"msp430x22x4.h" .set 500 .set 0x0600
; include c header ; 500 Mhz WD clock (@1 Mhz) ; stack
.bss .bss
; WDT second counter ; buzzer on flag
WDTSecCnt,2 buzzON,1
.text mov.w #STACK,SP mov.w #WDT_MDLY_0_5,&WDTCTL mov.w #WDT_CPS,&WDTSecCnt mov.b #WDTIE,&IE1 bis.b #0x01,&P1DIR PWM when buzzON is bis.b #0x20,&P4DIR clr.b &buzzON non-zero bis.w #LPM0+GIE,SR jmp $ RESET:
WDT_ISR:
WDT_02:
cmp.b #0,&buzzON jeq WDT_02 xor.b #0x20,&P4OUT
BYU CS/ECEn 124
; buzzer on? ; n ; y, use 50% PWM
dec.w &WDTSecCnt jne WDT_04 mov.w #WDT_CPS,&WDTSecCnt xor.b #0x01,&P1OUT xor.b #0xff,&buzzON
WDT_04: .sect .word .sect .word .end
; program section ; initialize stack pointer ; set WD timer interval to 0.5 ms ; initialize 1 sec WD counter ; enable WDT interrupt ; P1.0 output ; P4.5 output (transducer) ; turn off buzzer ; enable interrupts / sleep ; (should never get here!)
; decrement counter, 0? ; n ; y, re-initialize counter ; toggle P1.0 ; toggle buzzer on/off
reti ".int10" WDT_ISR ".reset" RESET
; return from interrupt ; ; ; ;
Watchdog Vector Watchdog ISR PUC Vector RESET ISR
MSP430 Examples
13
Switch Debounce
Example 6: SW Switch Debounce ;********************************************************************** ; Switch debounce routine ; DB_TIME .set 10 ; 10 ms debounce time DB_CYCS .set 13 ; instruction cycles for delay DB_DELAY .set DB_TIME*myCLOCK/DB_CYCS/1000 ; delay count debounce_switch: push
r15
; callee save
deb02:
mov.b xor.b and.b jne
&P2IN,r12 #0x0f,r12 #0x0f,r12 deb02
; ; ; ;
deb04:
mov.w
#DB_DELAY,r15
; minimum delay
&P2IN,r12 #0x0f,r12 #0x0f,r12 deb04 r15 deb06 r15
; ; ; ; ; ;
deb06: Reset timing counter if and of the switches read 0
mov.b xor.b and.b jeq dec.w jne pop ret
BYU CS/ECEn 124
Wait until all switches off
read switches SW1-4 any switch low? y, wait until all off
read switches SW1-4 all switches high? n, restart delay y, long enough delay? n, keep going ; y, switches debounced
MSP430 Examples
Return if R15 counts down to 0
14
Pulse Width Modulation (S /W)
Example 7: Timer_B S /W PWM
Timer B interrupts used to modulate transducer at 440 Hz .cdecls C,LIST,"msp430x22x4.h" SMCLK .set 1200000 TIME_A3 .set 1000000/440/2 TB_CTL .set TBSSEL_2+ID_0+MC_1+TBIE TB_FREQ .set SMCLK/TIME_A3
; ; ; ;
1200000 clocks / second A = 440 Hz SMCLK, /1, UP, IE clocks / 440 Hz
reset:
mov.w #0x0600,SP ; initialize SP mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop WDT bis.b #0x20,&P4DIR ; P4.5 transducer output clr.w &TBR ; reset timerB mov.w #TB_CTL,&TBCTL ; set timerB control reg ; set interval (frequency) Timer B Interrupt mov.w #TB_FREQ,&TBCCR0 bis.w #LPM0+GIE,SR ; enter LPM0 w/interrupts Service Routine jmp $ ; will never get here! TB_isr: bic.w xor.b reti .sect .word .sect .word .end BYU CS/ECEn 124
#TBIFG,&TBCTL #0x20,&P4OUT
; acknowledge interrupt ; toggle (50% duty cycle)
".int12" TB_isr ".reset" reset
; ; ; ;
timer timer reset reset
MSP430 Examples
B section B isr vector section vector ISR 15
Tone Scale Example
Step 1: Start Simple .cdecls C,LIST,"msp430x22x4.h" STACK .set 0x0600 ; top-of-stack .text ; code Section ;********************************************************************** ; Start of program... reset: mov.w #STACK,SP ; initialize SP call #init_MSP430 ; init MSP430 call #init_variables ; init variables ;********************************************************************** ; Main event loop... loop: call #update_LEDs ; update LED's call #goto_sleep ; go to sleep call #adjust_volume ; awake! adjust volume call #debounce_switch ; debounce switches jmp loop ; go back to sleep init_MSP430: init_variables: goto_sleep: adjust_volume: update_LEDs: debounce_switch: ret .sect .word .end BYU CS/ECEn 124
Working Program!
".reset" reset
; ; ; ; ; ;
init MSP430 init variables enter LPM0 adjust volume show volume in LEDx debounce switches
; reset vector section ; reset vector ISR MSP430 Examples
16
Tone Scale Example
Step 2: Initialize MSP430 WDT_CLK .set 8000 ; 8 khz clock (@1 Mhz) WDT_CTL .set WDT_MDLY_8 ; WDT SMCLK, 8 ms ;********************************************************************** ; Initialize MSP430 routine init_MSP430: mov.w #WDT_CTL,&WDTCTL ; configure WDT
bic.b bis.b bic.b bis.b
#0x03,&P1SEL #0x03,&P1DIR #0x01,&P1OUT #0x02,&P1OUT
; eZ430 LED's ; P1.0-1 as output ; turn off red ; turn on green
bic.b bis.b bis.b bis.b
#0xc0,&P2SEL #0xc0,&P2DIR #0x08,&P3DIR #0x40,&P4DIR
; eZ430X LED's ; LED #1 & #2 ; LED #3 ; LED #4
bic.b bic.b bis.b bis.b bis.b
#0x0f,&P2SEL #0x0f,&P2DIR #0x0f,&P2OUT #0x0f,&P2IES #0x0f,&P2REN
; eZ430X push buttons ; P2.0-3 as inputs ; P2.0-3 pull-ups ; h to l ; enable pull-ups
bis.b
#0x20,&P4DIR
; P4.5 transducer output
clr.w &TBR ; Timer B SMCLK, /1, up mode mov.w #TBSSEL_2+ID_0+MC_1,&TBCTL ret BYU CS/ECEn 124
MSP430 Examples
17
Tone Scale Example
Step 3a: Implement Watchdog
Add WDT 1 second data variable .bss
WDTSecCnt,2
; WDT second counter
Add WDT ISR and interrupt vector ;********************************************************************** ; Watchdog Timer ISR WDT_ISR: ; WD timer ISR dec.w &WDTSecCnt ; 1 second? jne WD10 ; n xor.b #0x03,&P1OUT ; y, toggle LEDs mov.w #WDT_CPS,&WDTSecCnt ; reset counter ;
WD10:
reti
; return from interrupt
;********************************************************************** ; Interrupt Vector Table Entries .sect ".int10" ; WDT vector .word WDT_ISR ; address of WDT ISR BYU CS/ECEn 124
MSP430 Examples
18
Tone Scale Example
Step 3b: Implement Watchdog
Initialize 1 second data variable myCLOCK .set WDT_CLK .set WDT_CTL .set WDT_CPS .set
1200000 8000 WDT_MDLY_8 myCLOCK/WDT_CLK
; 1.2 Mhz clock ; 8 khz clock (@1 Mhz) ; WDT SMCLK, 8 ms ; WD clocks / second count
;********************************************************************** ; Initalize variables routine init_variables: ; init variables mov.w #WDT_CPS,&WDTSecCnt ; WDT counts/second bis.b #WDTIE,&IE1 ; enable WDT interrupt ret
Enable interrupts ;********************************************************************** ; Goto sleep routine (Enable interrupts and LPM0) goto_sleep: ; enter LPM0 bis.b #LPM0+GIE,SR ; enter LPM0 w/interrupts ret
BYU CS/ECEn 124
MSP430 Examples
19
Tone Scale Example
Step 4a: Create Tones
Add some tone constants equates ; chromatic scale (12 just intonation intervals) DO .set myCLOCK*1000/261626 ; C (261.626 Hz) RE .set DO*8/9 ; D MI .set DO*4/5 ; E FA .set DO*3/4 ; F SOL .set DO*2/3 ; G LA .set DO*3/5 ; A TI .set DO*8/15 ; B DO1 .set DO*1/2 ; C
Create melodic array of tone values scale
.text .word
BYU CS/ECEn 124
; code Section DO, RE, MI, FA, SOL, LA, TI, DO1
MSP430 Examples
20
Tone Scale Example
Step 4b: Create Tones
Create tone index variable .bss
; tone number (0-8)
Initialize tone variable in init variable subroutine
tone,2
MAX_TONE mov.w
.set 8 #0,&tone
; 0-8 tones ; 1st tone
Use WDT ISR to sequence thru the scale push r4 mov.w &tone,r4 add.w #1,r4 cmp.w #MAX_TONE,r4 jlo WD02 clr.w r4 ;
; ; ; ;
; save r4 ; get tone next tone restart scale? n y
WD02: mov.w r4,&tone ; save tone > pop r4
BYU CS/ECEn 124
MSP430 Examples
21
Tone Scale Example
Step 5: Output Tone
Add TimerB ISR and interrupt vector ;********************************************************************** ; Timer B ISR TB_ISR: ; timer B ISR bic.w #TBIFG,&TBCTL ; acknowledge interrupt xor.b #0x20,&P4OUT ; pulse buzzer TB04:
reti .sect .word
; return from interrupt ".int12" TB_ISR
; timer B section ; timer B ISR
And start TimerB with 1st tone in init variables subroutine
BYU CS/ECEn 124
mov.w bis.w
#DO/2,&TBCCR0 #TBIE,&TBCTL
st note ; start timer clock w/1 ; enable timer B interrupts
MSP430 Examples
22
Tone Scale Example
Step 6: Enter LPM0
Add Port 2 ISR to clear LPM0 and enter AM ;********************************************************************** ; Port 2 (switches) ISR P2_ISR: ; Port 2 (switches) ISR bic.b #0x0f,&P2IE ; disable P2 interrupts bic.w #LPM0,0(SP) ; clear LPM0 from TOS reti ; return from interrupt .sect .word
".int03" P2_ISR
; P2 interrupt vector ; address of Port 2 ISR
And change to LPM0 when enabling interrupts ;********************************************************************** ; Goto sleep routine (Enable interrupts and LPM0) goto_sleep: ; enter LPM0 bic.b #GIE,SR ; disable all interrupts clr.b &P2IFG ; acknowledge all bis.b #0x0f,&P2IE ; enable switch interrupts bis.b #LPM0+GIE,SR ; enter LPM0 w/interrupts ret
BYU CS/ECEn 124
MSP430 Examples
23
Tone Scale Example
Step 7a: Play Scale
Add toggle, high, and low duty cycle variables .bss .bss .bss
duty_cycle_high,2 duty_cycle_low,2 duty_cycle_toggle,1
; high part of cycle ; low part of cycle ; duty cycle flag
Use Watchdog interrupt to change tone ;
;
;
> push r5 add.w r4,r4 mov.w scale(r4),r4 > rra.w r4 mov.w r4,r5 update tone duty cycle mov.w r4,&TBCCR0 mov.w r4,&duty_cycle_high mov.w r5,&duty_cycle_low pop r5
BYU CS/ECEn 124
; save r5 ; (word index) ; r4 = tone (frequency)
; 50% duty cycle
; start clock (if necessary) ; set high duty cycle ; set low duty cycle
MSP430 Examples
24
Tone Scale Example
Step 7b: Play Scale
Initialize high and low duty cycle variables clr.b &duty_cycle_toggle mov.w #DO/2,&duty_cycle_high mov.w #DO/2,&duty_cycle_low
; init toggle variable ; w/1st tone
And add high and low duty cycles to Timer_B ISR ;********************************************************************** ; Timer B ISR TB_ISR: ; timer B ISR bic.w #TBIFG,&TBCTL ; acknowledge interrupt xor.b #0x20,&P4OUT ; pulse buzzer xor.b #0xff,&duty_cycle_toggle ; high? jeq TB02 ; n mov.w &duty_cycle_high,&TBCCR0 ; y, set high duty cycle jmp TB04 TB02:
mov.w
TB04:
reti
BYU CS/ECEn 124
&duty_cycle_low,&TBCCR0
; set low duty cycle ; return from interrupt
MSP430 Examples
25
Tone Scale Example
Step 8a: Add Volume
Create volume index variable to data section .bss
; volume (0-8)
Initialize volume in init_variables
MAX_VOLUME
volume,2
mov.w
.set
4
; 0-4 volume
#MAX_VOLUME,&volume
; init volume
Create a PWM array of duty-cycles in text section ; duty cycle table (shift right until duty=0) duty .word 0x7fff, 0x0020, 0x0010, 0x0004, 0x0001 ; off 3.125% 6.25% 12.5% 50%
BYU CS/ECEn 124
MSP430 Examples
26
Tone Scale Example
Step 8b: Add Volume
Change Watchdog ISR to use duty array ; ; ;
> rra.w r4 mov.w r4,r5 push r6 mov.w r4,r5 mov.w volume,r6 add.w r6,r6 mov.w duty(r6),r6
;
rra.w r4 jne WD06 clr.w r5
; 50% duty cycle
; save in r5 ; get volume ; (word index) ; r6 = duty cycle
WD04:
WD06: rra.w r6 jne WD04 sub.w r4,r5 pop r6
; 1/2 duty cycle, off? ; n ; y ; done? ; n ; y, r4+r5=frequency
update tone duty cycle
BYU CS/ECEn 124
MSP430 Examples
27
Tone Scale Example
Step 9: Switches Change Volume
Use P2IFG determine which switch was pressed and adjust volume accordingly ;********************************************************************** ; Adjust volume routine adjust_volume: ; adjust volume bit.b #0x01,&P2IFG ; switch #1? jeq adj02 ; n sub.w #1,&volume ; y, down volume, too low? jge adj04 ; n clr.w &volume ; y, clear jmp adj04 adj02:
adj04:
bit.b jeq add.w cmp.w jlo mov.w
#0x02,&P2IFG adj04 #1,&volume #MAX_VOLUME,&volume adj04 #MAX_VOLUME,&volume
; ; ; ; ;
switch #2? n y, turn up volume too high? n ; y, set to max
ret
BYU CS/ECEn 124
MSP430 Examples
28
Tone Scale Example
Step 10: Volume in LEDs
Display the current volume setting using 4 LEDs ;********************************************************************** ; Update LEDs routine update_LEDs: ; show volume in LEDs bic.b #0xc0,&P2OUT ; LED #1 & #2 bic.b #0x08,&P3OUT ; LED #3 bic.b #0x40,&P4OUT ; LED #4 cmp.w #0,&volume jeq upd02 bis.b #0x40,&P2OUT ; turn on LED #1 cmp.w #1,&volume jeq upd02 bis.b #0x80,&P2OUT ; turn on LED #2 cmp.w #2,&volume jeq upd02 bis.b #0x08,&P3OUT ; turn on LED #3 cmp.w #3,&volume jeq upd02 bis.b #0x40,&P4OUT ; turn on LED #4 upd02:
ret
BYU CS/ECEn 124
MSP430 Examples
29
Tone Scale Example
Step 11: Debounce Switches
Finally, debounce switches (1¶s (up) for 10 ms) ;********************************************************************** ; Switch debounce routine ; DB_TIME .set 10 ; 10 ms debounce time DB_CYCS .set 12 ; instruction cycles for delay DB_DELAY .set DB_TIME*myCLOCK/DB_CYCS/1000 ; delay count debounce_switch: push
r15
; callee save
deb02:
mov.b xor.b and.b jne
&P2IN,r12 #0x0f,r12 #0x0f,r12 deb02
; ; ; ;
deb04:
mov.w
#DB_DELAY,r15
; minimum delay
&P2IN,r12 #0x0f,r12 #0x0f,r12 deb04 r15 deb06 r15
; ; ; ; ; ;
deb06:
mov.b xor.b and.b jeq dec.w jne pop ret
BYU CS/ECEn 124
read switches SW1-4 any switch low? y, wait until all off
read switches SW1-4 all switches high? n, restart delay y, long enough delay? n, keep going ; y, switches debounced
MSP430 Examples
30
Pulse Width Modulation (H /W)
Step 12a: Use Timer Output PWM
First, eliminate a lot of code!! .bss .bss .bss
duty_cycle_high,2 duty_cycle_l ow,2 duty_cycle_t oggle,1
; high part of cycle ; low part of cycle ; duty cycle flag
mov.w #DO/2,&TBCCR 0 ; start clock bis.w #TBIE,&TBCTL ; enable timer B interrupts mov.w #DO/2,&duty_ cycle_high ; set duty cycles mov.w #DO/2,&duty_cycle_low ; > ; rra.w r4 ; mov.w r4,r5 mov.b volume,r5 mov.w duty(r5),r5 sub.w r5,r4 cmp.w #0,r5 jne WD04 mov.w #0,r4
WD04: mov.w r4,&TBCCR0 mov.w r4,&duty_cyc le_high mov.w r5,&duty_cyc le_low
TB_isr:
; 50% duty cycle ; get volume ; r5 = duty cycle ; subtract from frequency ; turn off? ; n ; y, high=low=0 ; start clock (if necessary) ; set high duty cycle ; set low duty cycle
; timer B ISR bic.w #TBIFG,&TBCT L ; acknowledge interrupt xor.b #0x20,&P4OUT ; pulse buzzer xor.b #1,&duty_cyc le_toggle ; high? jeq TB02 ; n mov.w &duty_cycle_ high,&TBCCR0 ; y, set high duty cycle jmp TB04
TB02:
mov.w
TB04:
reti .sect .word
&duty_cycle_ low,&TBCCR0 ; set low duty cycle ; return from interrupt ".int12" TB_isr
BYU CS/ECEn 124
; timer B section ; timer B isr
MSP430 Examples
31
Pulse Width Modulation (H /W)
Step 12b: Use Timer Output PWM
Put transducer (P4.5) as secondary function bis.b #0x20,&P4SEL mov.w #OUTMOD_3,&TBCCTL2 mov.w #DO/2,&TBCCR2
; P4.5 transducer output ; output mode = set/reset ; use TBCCR2 as volume
Change WD ISR to just put the duty cycle in TBCCR2 ;
> push r5 ; save r5 add.w r4,r4 ; (word index) mov.w scale(r4),r4 ; r4 = tone (frequency) mov.w r4,&TBCCR0 ; start clock (if necessary) mov.b volume,r5 ; get volume add.w r5,r5 ; (word index) mov.w duty(r5),r5 ; r5 = duty cycle mov.w r5,&TBCCR2 ; start clock (if necessary) pop r5
BYU CS/ECEn 124
MSP430 Examples
32
Pulse Width Modulation (H /W)
Example 8: H /W PWM w/Timer_B
Timer B output used to modulate transducer at 440 Hz .cdecls C,LIST,"msp430x22x4.h" SMCLK .set 1200000 ; TIME_A3 .set 1000000/440/2/2 ; TB_CTL .set TBSSEL_2+ID_0+MC_1 ; TB_FREQ .set SMCLK/TIME_A3 ; reset:
Set P4.5 as output from TB2
UP mode, TB2 set/reset 50% Duty
Cycle
mov.w #0x0600,SP mov.w #WDTPW+WDTHOLD,&WDTCTL bis.b #0x20,&P4DIR bis.b #0x20,&P4SEL clr.w &TBR mov.w #TB_CTL,&TBCTL mov.w #OUTMOD_3,&TBCCTL2 mov.w #TB_FREQ,&TBCCR0 mov.w #TB_FREQ/2,&TBCCR2 bis.w #LPM0+GIE,SR jmp $ .sect .word .end
BYU CS/ECEn 124
".reset" reset
1200000 clocks / second A = 440 Hz (2x) SMCLK,/1,UP (No interrupts) clocks / 440 Hz
; initialize SP ; stop WDT ; P4.5 transducer output ; P4.5 timerB output ; reset timerB ; set timerB control reg ; TB2 output mode = set/reset ; set interval (frequency) ; load volume (duty cycle) ; enter LPM0 w/interrupts ; will never get here! ; reset vector section ; reset vector ISR
MSP430 Examples
33
Pulse Width Modulation (H /W)
Example 9: H /W PWM w/Timer_A #include #include #include #include #include
Set P2.4 as output from TA2
SMCLK, 1 /4, UP mode, TA2 set/reset
"msp430x22x4.h" "eZ430X.h" "lcd.h" "adc.h"
void main(void) { eZ430X_init(CALDCO_8MHZ); ADC_init(); lcd_init();
// init board // init ADC // init LCD
P2DIR |= 0x10; // P2SEL |= 0x10; // TAR = 0; // TACTL = TASSEL_2 + ID_2 + MC_1; // TACCTL2 = OUTMOD_3; //
P2.4 speaker output P2.4 TA2 output reset timer A SMCLK, /4, UP (no interrupts) TA2 = set/reset
while (1) { uint16 freq = (1023 - ADC_read(LEFT_POT)) > 10; TACCR0 = freq; // frequency TACCR2 = duty; // duty cycle lcd_cursor(10, 4); lcd_printf("Freq:%u ", freq); Freq = Left Pot lcd_cursor(10, 2); Duty Cycle = Right Pot lcd_printf("Duty:%u ", duty); } } // end main BYU CS/ECEn 124 MSP430 Examples 34
Pulse Width Modulation (H /W)
Example 9: H /W PWM w/Timer_A #include #include #include #include #include
Set P2.4 as output from TA2
SMCLK, 1 /4, UP mode, TA2 set/reset
"msp430x22x4.h" "eZ430X.h" "lcd.h" "adc.h"
void main(void) { eZ430X_init(CALDCO_8MHZ); ADC_init(); lcd_init();
// init board // init ADC // init LCD
P2DIR |= 0x10; // P2SEL |= 0x10; // TAR = 0; // TACTL = TASSEL_2 + ID_2 + MC_1; // TACCTL2 = OUTMOD_3; //
P2.4 speaker output P2.4 TA2 output reset timer A SMCLK, /4, UP (no interrupts) TA2 = set/reset
while (1) { uint16 freq = (1023 - ADC_read(LEFT_POT)) > 10; TACCR0 = freq; // frequency TACCR2 = duty; // duty cycle Freq = Left Pot lcd_cursor(10, 4); Duty Cycle = Right Pot lcd_printf("Duty/Freq:%u/%u ", duty, freq); } } // end main BYU CS/ECEn 124
MSP430 Examples
35
View more...
Comments