• No results found

MSP430 Examples

N/A
N/A
Protected

Academic year: 2021

Share "MSP430 Examples"

Copied!
36
0
0

Loading.... (view fulltext now)

Full text

(1)

B

BYYUU CCSS//EECCEEnn 112244 MSMSPP443300 EExxaammpplleess 11

Topics to Co

Topics to Co

v

v

er«

er«

F2013 Blinky Example

F2013 Blinky Example

Lab 4: Blinky Lab

Lab 4: Blinky Lab

Example 2:

Example 2: Interrupts w/Timer_

Interrupts w/Timer_A

A

Example 3: S/W PWM w/Timer_A

Example 3: S/W

PWM w/Timer_A

Example 4: W

Example 4: Watchdog Clock

atchdog Clock

Example 5: Watchdog PWM

Example 5: Watchdog PWM

Example 6: SW Switch Debounce

Example 6: SW Switch Debounce

Example 7: Timer_B S/W PWM

Example 7: Timer_B S/W PWM

(2)
(3)

B

BYYUU CCSS//EECCEEnn 112244 MSMSPP443300 EExxaammpplleess 22

F2013

F2013

Blinky Example

Blinky Example

;******************************************************************************* ;******************************************************************************* ;

; CS/ECEn CS/ECEn 124 124 Lab Lab 1 1 -- blinky.ablinky.asm: sm: Software Software Toggle Toggle P1.0P1.0

;******************************************************************************* ;*******************************************************************************

.cdecls

.cdecls C,LIST, C,LIST, "msp430x20x3.h" "msp430x20x3.h" ; ; MSP430F2013MSP430F2013

;---.text

.text ; beginning ; beginning of of executable executable codecode ;---RESET:

RESET: mov.w mov.w #0x0280,SP #0x0280,SP ; ; init init stack stack pointerpointer   mov.w

  mov.w #WDTPW+WDTHOLD,&#WDTPW+WDTHOLD,&WDTCTL WDTCTL ; ; stop stop WDTWDT   bis.b

  bis.b #0x01,&P1DIR #0x01,&P1DIR ; ; set set P1.0 P1.0 as as outputoutput   mainloop:

  mainloop: xor.b xor.b #0x01,&P1OUT #0x01,&P1OUT ; ; toggle toggle P1.0P1.0   mov.w

  mov.w #0,r15 #0,r15 ; ; use use R15 R15 as as delay delay countercounter delayloop:

delayloop: dec.w dec.w r15 r15 ; ; delay delay over?over? jnz

jnz delayloop delayloop ; ; nn jmp

jmp mainloop mainloop ; ; y, y, toggle toggle led led 

;---;

; Interrupt Interrupt VectorsVectors

;---.sect

.sect ".reset" ".reset" ; ; MSP430 MSP430 RESET RESET VectorVector .short

.short RESET RESET ; ; start start addressaddress .end 

.end 

S

(4)

Add

Add

2

2

n

n

d

d

Delay Loop

Delay Loop

;******************************************************************************* ;******************************************************************************* ; CS/ECE

; CS/ECEn 124 Ln 124 Lab 1 -ab 1 - blinky.ablinky.asm: Sofsm: Software Ttware Toggle P1.0oggle P1.0

;******************************************************************************* ;*******************************************************************************

.cdecls

.cdecls C,LIST, C,LIST, "msp430x20x3.h" "msp430x20x3.h" ; ; MSP430F2013MSP430F2013 delay

delay .set .set 00

;---.text

.text ; beginning ; beginning of of executable executable codecode ;---RESET:

RESET: mov.w mov.w #0x0280,SP #0x0280,SP ; ; init init stack stack pointerpointer   mov.w

  mov.w #WDTPW+WDTHOLD,&#WDTPW+WDTHOLD,&WDTCTL WDTCTL ; ; stop stop WDTWDT   bis.b

  bis.b #0x01,&P1DIR #0x01,&P1DIR ; ; set set P1.0 P1.0 as as outputoutput   mainloop:

  mainloop: xor.b xor.b #0x01,&P1OUT #0x01,&P1OUT ; ; toggle toggle P1.0P1.0   mov.w #delay,r15

  mov.w #delay,r15 ; ; use use R15 R15 as as delay delay countercounter delayloop:

delayloop: dec.w dec.w r15 r15 ; ; delay delay over?over? jnz

jnz delayloop delayloop ; ; nn delay2:

delay2: dec.w dec.w r15r15 jnz delay2 jnz delay2 jmp

jmp mainloop mainloop ; ; y, y, toggle toggle led led 

;---;

; Interrupt Interrupt VectorsVectors

;---.sect

.sect ".reset" ".reset" ; ; MSP430 MSP430 RESET RESET VectorVector .short

.short RESET RESET ; ; start start addressaddress .end 

.end 

S

(5)

BYU CS/ECEn 124 MSP430 Examples 4

LEDs

6 LED¶s on eZ430X Development Board

P1.0 Red LED eZ430-RF2500

P1.1 Green LED eZ430-RF2500

P2.6 LED #1 (Green)

P2.7 LED #2 (Orange)

P3.3 LED #3 (Yellow)

P4.6 LED #4 (Red)

Port bits must be enabled for output by writing a 1 to the

port direction register 

bis.b #0x03,&P1DIR

; eZ430-RF2500 LED's

bic.b #0xc0,&P2SEL

; select GPIO

bis.b #0x40,&P2DIR

; LED #1 (P2.6)

bis.b #0x80,&P2DIR

; LED #2 (P2.7)

bis.b #0x08,&P3DIR

; LED #3 (P3.3)

bis.b #0x40,&P4DIR

; LED #4 (P4.6)

(6)

LEDs

Turn LED off by writing a 0 to the port pin

bic.b #0x03,&P1OUT

; eZ430-RF2500 LED's

bic.b #0x40,&P2OUT

; LED #1 (P2.6)

bic.b #0x80,&P2OUT

; LED #2 (P2.7)

bic.b #0x08,&P3OUT

; LED #3 (P3.3)

bic.b #0x40,&P4OUT

; LED #4 (P4.6)

Turn LED on by writing a 1 to the port pin

bis.b #0x03,&P1OUT

; eZ430-RF2500 LED's

bis.b #0x40,&P2OUT

; LED #1 (P2.6)

bis.b #0x80,&P2OUT

; LED #2 (P2.7)

bis.b #0x08,&P3OUT

; LED #3 (P3.3)

bis.b #0x40,&P4OUT

; LED #4 (P4.6)

Toggle LED by XOR¶ing a 1 to the port pin

xor.b #0x03,&P1OUT

; eZ430-RF2500 LED's

xor.b #0x40,&P2OUT

; LED #1 (P2.6)

xor.b #0x80,&P2OUT

; LED #2 (P2.7)

xor.b #0x08,&P3OUT

; LED #3 (P3.3)

xor.b #0x40,&P4OUT

; LED #4 (P4.6)

(7)

BYU CS/ECEn 124 MSP430 Examples 6

Lab 4: Blinky Lab

Lab 4: Blinky

;******************************************************************************* ; 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: xor.b #0x01,&P1OUT 4 ;toggle P1.0

  mov.w #COUNT,r15 1 use R15 as delay counter; delayloop: dec.w r15 ; 1 delay over?

jnz delayloop ; 2 n

jmp mainloop ; 2 y, toggle led 

;---; Interrupt Vectors

;---.sect ".reset" ; MSP430 RESET Vector

.short RESET ; start address .end 

(8)

.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 DELAY .equ (50/8)

.text ; beginning of 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   mainloop: xor.b #0x01,&P1OUT ; toggle P1.0

  push.w #DELAY ; pass delay count on stack

call #delay ; call delay subroutine

jmp mainloop

; 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 ; inner delay over?

jne delay02 ; n

dec.w 4(SP) ; y, outer done?

jne delay02 ; n

  pop.w r15 ; y, restore register(s)

  mov.w @SP+,0(SP) ; pop input delay count

ret ; return from subroutine

.sect ".reset" ; MSP430 RESET Vector

.word RESET ; start address

.end 

Example

1

a: Activation Recor d

4(SP)=delay count 2(SP)= return address 0(SP)= r 15

(9)

BYU CS/ECEn 124 MSP430 Examples 8

.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 DELAY .equ (50/8)

.text ; beginning of 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   mainloop: xor.b #0x01,&P1OUT ; toggle P1.0

  push.w #DELAY ; pass delay count on stack call #delay ; call delay subroutine jmp mainloop

; delay subroutine: stack usage 6| DELAY | \

; 4| ret | subroutine frame (8 bytes) ; 2| r12 | /(activation record)

; (SP) => 0| r15 |/

delay: push.w r12 ; callee-save   push.w r15

  mov.w 6(SP),r12 ; get delay count

  mov.w #0,r15 ; use R15 as inner counter delay02: dec.w r15 ; delay over?

jne delay02 ; n

dec.w r12 ; y, done? jne delay02 ; n

  pop.w r15 ; y, restore registers   pop.w r12

  mov.w @SP+,0(SP) ; pop input delay count ret ; return from subroutine .sect ".reset" ; MSP430 RESET Vector .word RESET ; start address

.end 

Example

1

b: Activation Recor d

6(SP)=delay count 4(SP)= return address 2(SP)= r 12

0(SP)= r 15

(10)

.cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013 DELAY .equ (50/8)

.text ; beginning of 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   mainloop: xor.b #0x01,&P1OUT ; toggle P1.0

  push.w #DELAY ; pass delay count on stack

call #delay ; call delay subroutine

jmp mainloop

; 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 0(SP) ; delay over?

jne delay02 ; n

dec.w 4(SP) ; y, done?

jne delay02 ; n

add.w #2,SP ; y, deactivate local variable   mov.w @SP+,0(SP) ; pop input delay count

ret ; return from subroutine

.sect ".reset" ; MSP430 RESET Vector

.word RESET ; start address

.end 

Example

1

c: Activation Recor d

4(SP)=delay count 2(SP)= return address 0(SP)= local variable

(11)

BYU CS/ECEn 124 MSP430 Examples 10

Example

2

: Interrupts w/Timer_A

cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013

TA_CTL .set TASSEL_2+ID_3+MC_1+TAIE ; 000000 10 11 01 000 1 = SMCLK,/8,UP,IE TA_FREQ .set 0xffff ; clocks

;---.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 ; reset timerA 

  mov.w #TA_CTL,&TACTL ; set timerA control reg   mov.w #TA_FREQ,&TACCR0 ; set interval (frequency)   bis.w #LPM0+GIE,SR ; enter LPM0 w/interrupts

jmp $

TA_isr: ; timer A ISR 

  bic.w #TAIFG,&TACTL ; acknowledge interrupt xor.b #0x01,&P1OUT ; toggle P1.0

reti

;---; Interrupt Vectors

.sect ".int08" ; timer A section .word TA_isr ; timer A isr

.sect ".reset" ; MSP430 RESET Vector .word RESET ; start address

.end 

Blinky Example

TASSEL_2=SMCLK ID_3= /8  MC_1= UP Mode Enable Interrupt Acknowledge Interrupt (Put its hand down)

Put the processor to sleep!

(12)

Example

3

: S /W PWM w/Timer_A

.cdecls C,LIST,"msp430x20x3.h"

SMCLK .set 1200000 ; 1200000 clocks / second  TA_CTL .set TASSEL_2+ID_0+MC_1+TAIE ; SMCLK, /1, UP, IE

TA_FREQ .set 120 ; FREQ / SMCLK = 0.0001 = 100 us .bss cnt,2 ; counter variable

.text

RESET: mov.w #0x0280,SP ; init stack pointer   mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog

  bis.b #0x01,&P1DIR ; set P1.0 as output clr.w &TAR ; reset timerA 

  mov.w #TA_CTL,&TACTL ; set timerA control reg   mov.w #TA_FREQ,&TACCR0 ; set interval (frequency)   bis.w #LPM0+GIE,SR ; enter LPM0 w/interrupts

jmp $ ; will never get here! TA_isr: bic.w #TAIFG,&TACTL ; acknowledge interrupt

inc.w &cnt

cmp.w #10,&cnt ; time to pulse? jlo TA_isr2 ; n

clr.w &cnt ; y, reset counter   bis.b #0x01,&P1OUT ; turn on

jmp TA_isr4

TA_isr2: bic.b #0x01,&P1OUT ; turn off

TA_isr4: reti ; return from interrupt .sect ".int08" ; timer A section

.word TA_isr ; timer A isr

.sect ".reset" ; MSP430 RESET Vector .short RESET ; start address

.end 

LED Intensity

Acknowledge needed 10%Duty Cycle

(13)

BYU CS/ECEn 124 MSP430 Examples 12

Example 4: Watchdog Clock

.cdecls C,LIST,"msp430x20x3.h"

SMCLK .set 1200000 ; 1.2 Mhz clock

  WDT_CTL .set WDT_MDLY_8 ; WDT SMCLK, 8 ms (@1 Mhz)   WDT_CPS .set SMCLK/8000 ; 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: ;<< program >> 

jmp loop ; 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 ; return from interrupt ; Interrupt Vectors

---.sect ".int10" ; Watchdog Vector .word WDT_ISR ; Watchdog ISR  .sect ".reset" ; PUC Vector .word RESET ; RESET ISR  .end 

Watchdog

8 ms (@1MHz SMCLK) Enable WD Interrupts No acknowledge needed

(14)

Example

5

: Watchdog PWM

.cdecls C,LIST,"msp430x22x4.h" ; include c header

  WDT_CLK .set 500 ; 500 Mhz WD clock (@1 Mhz) STACK .set 0x0600 ; stack

.bss WDTSecCnt,2 ; WDT second counter .bss buzzON,1 ; buzzer on flag .text ; program section

RESET: mov.w #STACK,SP ; initialize stack pointer

  mov.w #WDT_MDLY_0_5,&WDTCTL ; set WD timer interval to 0.5 ms   mov.w #WDT_CPS,&WDTSecCnt ; initialize 1 sec WD counter   mov.b #WDTIE,&IE1 ; enable WDT interrupt   bis.b #0x01,&P1DIR ; P1.0 output

  bis.b #0x20,&P4DIR ; P4.5 output (transducer) clr.b &buzzON ; turn off buzzer

  bis.w #LPM0+GIE,SR ; enable interrupts / sleep jmp $ ; (should never get here!)   WDT_ISR: cmp.b #0,&buzzON ; buzzer on?

jeq WDT_02 ; n

xor.b #0x20,&P4OUT ; y, use 50% PWM 

  WDT_02: dec.w &WDTSecCnt ; decrement counter, 0? jne WDT_04 ; n

  mov.w #WDT_CPS,&WDTSecCnt ; y, re-initialize counter xor.b #0x01,&P1OUT ; toggle P1.0

xor.b #0xff,&buzzON ; toggle buzzer on/off

  WDT_04: reti ; return from interrupt .sect ".int10" ; Watchdog Vector

.word WDT_ISR ; Watchdog ISR  .sect ".reset" ; PUC Vector .word RESET ; RESET ISR 

Speaker (Transducer )

PWM when buzzON is non-zero

(15)

BYU CS/ECEn 124 MSP430 Examples 14

;********************************************************************** ; 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 &P2IN,r12 ; read switches

xor.b #0x0f,r12 ; SW1-4

and.b #0x0f,r12 ; any switch low?

jne deb02 ; y, wait until all off deb04: mov.w #DB_DELAY,r15 ; minimum delay

deb06: mov.b &P2IN,r12 ; read switches xor.b #0x0f,r12 ; SW1-4

and.b #0x0f,r12 ; all switches high? jeq deb04 ; n, restart delay

dec.w r15 ; y, long enough delay? jne deb06 ; n, keep going

  pop r15 ; y, switches debounced  ret

Example 6: SW Switch Debounce

Reset timing counter if  andof the switches read0

Switch Debounce

Return if  R15 counts down to0 Wait until all switches off 

(16)

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 ; 1200000 clocks / second  TIME_A3 .set 1000000/440/2 ; A = 440 Hz

TB_CTL .set TBSSEL_2+ID_0+MC_1+TBIE ; SMCLK, /1, UP, IE TB_FREQ .set SMCLK/TIME_A3 ; 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   mov.w #TB_FREQ,&TBCCR0 ; set interval (frequency)   bis.w #LPM0+GIE,SR ; enter LPM0 w/interrupts

jmp $ ; will never get here!

TB_isr: bic.w #TBIFG,&TBCTL ; acknowledge interrupt xor.b #0x20,&P4OUT ; toggle (50% duty cycle) reti

.sect ".int12" ; timer B section

.word TB_isr ; timer B isr

.sect ".reset" ; reset vector section

.word reset ; reset vector ISR 

.end 

Timer B Interrupt

Service Routine

(17)

BYU CS/ECEn 124 MSP430 Examples 16

Step

1

: Start Simple

Tone Scale Example

.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 MSP430

init_variables: ; init variables

goto_sleep: ; enter LPM0

adjust_volume: ; adjust volume

update_LEDs: ; show volume in LEDx

debounce_switch: ; debounce switches

ret

.sect ".reset" ; reset vector section

.word reset ; reset vector ISR 

.end 

(18)

Step

2

: Initialize MSP4

30

Tone Scale Example

  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 #0x03,&P1SEL ; eZ430 LED's

  bis.b #0x03,&P1DIR ; P1.0-1 as output   bic.b #0x01,&P1OUT ; turn off red    bis.b #0x02,&P1OUT ; turn on green   bic.b #0xc0,&P2SEL ; eZ430X LED's   bis.b #0xc0,&P2DIR ; LED #1 & #2   bis.b #0x08,&P3DIR ; LED #3   bis.b #0x40,&P4DIR ; LED #4

  bic.b #0x0f,&P2SEL ; eZ430X push buttons   bic.b #0x0f,&P2DIR ; P2.0-3 as inputs   bis.b #0x0f,&P2OUT ; P2.0-3 pull-ups   bis.b #0x0f,&P2IES ; h to l

  bis.b #0x0f,&P2REN ; 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

(19)

BYU CS/ECEn 124 MSP430 Examples 18

 Add WDT 1 second data variable

 Add WDT ISR and interrupt vector 

Tone Scale Example

;********************************************************************** ; 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 ; <<add scale sequence code here>> 

  WD10: reti ; return from interrupt

;********************************************************************** ; Interrupt Vector Table Entries

.sect ".int10" ; WDT vector

.word WDT_ISR ; address of WDT ISR 

.bss WDTSecCnt,2 ; WDT second counter

(20)

Initialize 1 second data variable

Enable interrupts

Tone Scale Example

  myCLOCK .set 1200000 ; 1.2 Mhz clock

  WDT_CLK .set 8000 ; 8 khz clock (@1 Mhz)

  WDT_CTL .set WDT_MDLY_8 ; WDT SMCLK, 8 ms

  WDT_CPS .set myCLOCK/WDT_CLK ; 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

Step

3

b: Implement Watchdog

;********************************************************************** ; Goto sleep routine (Enable interrupts and LPM0)

goto_sleep: ; enter LPM0

  bis.b #LPM0+GIE,SR ; enter LPM0 w/interrupts ret

(21)

BYU CS/ECEn 124 MSP430 Examples 20

 Add some tone constants equates

Create melodic array of tone values

Tone Scale Example

; 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

Step 4a: Create Tones

.text ; code Section

(22)

Create tone index variable

Initialize tone variable in init variable subroutine

Use WDT ISR to sequence thru the scale

Tone Scale Example

Step 4b: Create Tones

  push r4 ; save r4

  mov.w &tone,r4 ; get tone

add.w #1,r4 ; next tone

cmp.w #MAX_TONE,r4 ; restart scale?

jlo WD02 ; n

clr.w r4 ; y

  WD02: mov.w r4,&tone ; save tone ; << later adjust tone & volume here >> 

  pop r4

.bss tone,2 ; tone number (0-8)

  MAX_TONE .set 8 ; 0-8 tones

(23)

BYU CS/ECEn 124 MSP430 Examples 22

 Add TimerB ISR and interrupt vector 

 And start TimerB with 1

st

tone in init variables subroutine

Tone Scale Example

;********************************************************************** ; Timer B ISR 

TB_ISR: ; timer B ISR 

  bic.w #TBIFG,&TBCTL ; acknowledge interrupt xor.b #0x20,&P4OUT ; pulse buzzer

TB04: reti ; return from interrupt

.sect ".int12" ; timer B section

.word TB_ISR ; timer B ISR 

Step

5

: Output Tone

  mov.w #DO/2,&TBCCR0 ; start timer clock w/1st note

(24)

 Add Port 2 ISR to clear LPM0 and enter AM

 And change to LPM0 when enabling interrupts

Tone Scale Example

Step 6: Enter LPM

0

;********************************************************************** ; 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 ".int03" ; P2 interrupt vector .word P2_ISR ; address of Port 2 ISR 

;********************************************************************** ; 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

(25)

BYU CS/ECEn 124 MSP430 Examples 24

 Add toggle, high, and low duty cycle variables

Use Watchdog interrupt to change tone

Tone Scale Example

Step 7a: Play Scale

.bss duty_cycle_high,2 ; high part of cycle .bss duty_cycle_low,2 ; low part of cycle .bss duty_cycle_toggle,1 ; duty cycle flag

; << adjust timer b tone here >> 

  push r5 ; save r5

add.w r4,r4 ; (word index)

  mov.w scale(r4),r4 ; r4 = tone (frequency) ; << adjust volume here >> 

rra.w r4 ; 50% duty cycle

  mov.w r4,r5

; update tone duty cycle

  mov.w r4,&TBCCR0 ; start clock (if necessary)   mov.w r4,&duty_cycle_high ; set high duty cycle

  mov.w r5,&duty_cycle_low ; set low duty cycle

(26)

Initialize high and low duty cycle variables

 And add high and low duty cycles to Timer_B ISR

Tone Scale Example

Step 7b: Play Scale

;********************************************************************** ; 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 &duty_cycle_low,&TBCCR0 ; set low duty cycle

TB04: reti ; return from interrupt

clr.b &duty_cycle_toggle ; init toggle variable   mov.w #DO/2,&duty_cycle_high ; w/1st tone

(27)

BYU CS/ECEn 124 MSP430 Examples 26

Create volume index variable to data section

Initialize volume in init_variables

Create a PWM array of duty-cycles in text section

Tone Scale Example

Step 8a: Add Volume

  MAX_VOLUME .set 4 ; 0-4 volume

  mov.w #MAX_VOLUME,&volume ; init volume

; duty cycle table (shift right until duty=0)

duty .word 0x7fff, 0x0020, 0x0010, 0x0004, 0x0001

; off 3.125% 6.25% 12.5% 50%

(28)

Change Watchdog ISR to use duty array

Tone Scale Example

Step 8b: Add Volume

; << adjust volume here >> 

; rra.w r4 ; 50% duty cycle

; mov.w r4,r5   push r6

  mov.w r4,r5 ; save in r5

  mov.w volume,r6 ; get volume

add.w r6,r6 ; (word index)

  mov.w duty(r6),r6 ; r6 = duty cycle

  WD04: rra.w r4 ; 1/2 duty cycle, off?

jne WD06 ; n clr.w r5 ; y   WD06: rra.w r6 ; done? jne WD04 ; n sub.w r4,r5 ; y, r4+r5=frequency   pop r6

(29)

BYU CS/ECEn 124 MSP430 Examples 28

Use P2IFG determine which switch was pressed and

adjust volume accordingly

Tone Scale Example

Step 9: Switches Change Volume

;********************************************************************** ; 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: bit.b #0x02,&P2IFG ; switch #2?

jeq adj04 ; n

add.w #1,&volume ; y, turn up volume cmp.w #MAX_VOLUME,&volume ; too high?

jlo adj04 ; n

  mov.w #MAX_VOLUME,&volume ; y, set to max adj04: ret

(30)

Display the current volume setting using 4 LEDs

Tone Scale Example

Step

10

: Volume in 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

(31)

BYU CS/ECEn 124 MSP430 Examples 30

Finally, debounce switches (1¶s (up) for 10 ms)

Tone Scale Example

Step

11

: Debounce Switches

;********************************************************************** ; 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 &P2IN,r12 ; read switches

xor.b #0x0f,r12 ; SW1-4

and.b #0x0f,r12 ; any switch low?

jne deb02 ; y, wait until all off deb04: mov.w #DB_DELAY,r15 ; minimum delay

deb06: mov.b &P2IN,r12 ; read switches xor.b #0x0f,r12 ; SW1-4

and.b #0x0f,r12 ; all switches high? jeq deb04 ; n, restart delay

dec.w r15 ; y, long enough delay? jne deb06 ; n, keep going

  pop r15 ; y, switches debounced  ret

(32)

First, eliminate a lot of code!!

Step

12

a: Use Timer Output PWM

.bss duty_cycle_high,2 ; high part of cycle .bss duty_cycle_l ow,2 ; low part of cycle .bss duty_cycle_t oggle,1 ; 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 ; << adjust volume here >> 

; rra.w r4 ; 50% duty cycle ; mov.w r4,r5

  mov.b volume,r5 ; get volume   mov.w duty(r5),r5 ; r5 = duty cycle

sub.w r5,r4 ; subtract from frequency cmp.w #0,r5 ; turn off?

jne WD04 ; n

  mov.w #0,r4 ; y, high=low=0

  WD04: mov.w r4,&TBCCR0 ; start clock (if necessary)   mov.w r4,&duty_cyc le_high ; set high duty cycle

  mov.w r5,&duty_cyc le_low ; set low duty cycle TB_isr: ; 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 &duty_cycle_ low,&TBCCR0 ; set low duty cycle TB04: reti ; return from interrupt

.sect ".int12" ; timer B section .word TB_isr ; timer B isr

(33)

BYU CS/ECEn 124 MSP430 Examples 32

Put transducer (P4.5) as secondary function

Change WD ISR to just put the duty cycle in TBCCR2

Step

12

b: Use Timer Output PWM

  bis.b #0x20,&P4SEL ; P4.5 transducer output   mov.w #OUTMOD_3,&TBCCTL2 ; output mode = set/reset   mov.w #DO/2,&TBCCR2 ; use TBCCR2 as volume

; << adjust timer b tone here >> 

  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

(34)

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

; 1200000 clocks / second 

TIME_A3 .set 1000000/440/2/2

; A = 440 Hz (2x)

TB_CTL .set TBSSEL_2+ID_0+MC_1

; SMCLK,/1,UP (No interrupts)

TB_FREQ .set SMCLK/TIME_A3

; 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

 

bis.b #0x20,&P4SEL

; P4.5 timerB output

clr.w &TBR

; reset timerB

  mov.w #TB_CTL,&TBCTL

; set timerB control reg

  mov.w #OUTMOD_3,&TBCCTL2

; TB2 output mode = set/reset

  mov.w #TB_FREQ,&TBCCR0

; set interval (frequency)

  mov.w #TB_FREQ/2,&TBCCR2

; load volume (duty cycle)

 

bis.w #LPM0+GIE,SR

; enter LPM0 w/interrupts

jmp

$

; will never get here!

.sect ".reset"

; reset vector section

.word reset

; reset vector ISR 

.end 

Pulse Width Modulation (H /W)

SetP4.5as output from TB2 UPmode, TB2 set/reset 50%Duty Cycle

(35)

BYU CS/ECEn 124 MSP430 Examples 34

Example 9: H /W PWM w/Timer_A

#include "msp430x22x4.h" #include <stdio.h>  #include "eZ430X.h" #include "lcd.h" #include "adc.h" void main(void) {

eZ430X_init(CALDCO_8MHZ); // init board    ADC_init(); // init ADC

lcd_init(); // init LCD

P2DIR |= 0x10; // P2.4 speaker output P2SEL |= 0x10; // P2.4 TA2 output TAR = 0; // reset timer A 

TACTL = TASSEL_2 + ID_2 + MC_1; // SMCLK, /4, UP (no interrupts) TACCTL2 = OUTMOD_3; // TA2 = set/reset

 while (1) {

uint16 freq = (1023 - ADC_read(LEFT_POT)) << 6;

uint16 duty = ((long)freq * (1023 - ADC_read(RIGHT_POT)) >> 10; TACCR0 = freq; // frequency

TACCR2 = duty; // duty cycle lcd_cursor(10, 4); lcd_printf("Freq:%u ", freq); lcd_cursor(10, 2); lcd_printf("Duty:%u ", duty); } } // end main

Pulse Width Modulation (H /W)

SetP2.4 as output from TA2 Freq = LeftPot Duty Cycle = RightPot SMCLK, 1 /4, UPmode, TA2 set/reset

(36)

Example 9: H /W PWM w/Timer_A

#include "msp430x22x4.h" #include <stdio.h>  #include "eZ430X.h" #include "lcd.h" #include "adc.h" void main(void) {

eZ430X_init(CALDCO_8MHZ); // init board 

  ADC_init(); // init ADC

lcd_init(); // init LCD

P2DIR |= 0x10; // P2.4 speaker output

P2SEL |= 0x10; // P2.4 TA2 output

TAR = 0; // reset timer A 

TACTL = TASSEL_2 + ID_2 + MC_1; // SMCLK, /4, UP (no interrupts) TACCTL2 = OUTMOD_3; // TA2 = set/reset

 while (1) {

uint16 freq = (1023 - ADC_read(LEFT_POT)) << 6;

uint16 duty = ((long)freq * (1023 - ADC_read(RIGHT_POT)) >> 10; TACCR0 = freq; // frequency

TACCR2 = duty; // duty cycle lcd_cursor(10, 4);

lcd_printf("Duty/Freq:%u/%u ", duty, freq); }

} // end main

Pulse Width Modulation (H /W)

SetP2.4 as output from TA2 Freq = LeftPot Duty Cycle = RightPot SMCLK, 1 /4, UPmode, TA2 set/reset

References

Related documents

While there have been protests against other dam projects in Sikkim, most notably the Rathongchu project in North Sikkim in the 1990s, 42 this article will focus on the Dzongu dams

Linear prediction of ocean levels through the year 2050 provide another increase in water levels of about 1 foot whereas the parabolic approximation of the long-term

Instituto de Investigaciones Económicas UNAM Red de Acervos Digitales UNAM (RAD-UNAM).. Open

In this stage, features extracted from the region of interest are passed to a classifier which would determine the make and model. The support vector machine is a

For the investigation of mechanical triggering, the microcapsules with BH shell, the colloidal silica (CS) as core and the outer diameter of 88 mm and shell thickness of 7 mm

1 Treatment of MDR-TB is costly, requires 18 – 24 months before patients can be deemed cured of the disease, results in lower cure rates than the treatment of drug- susceptible TB,

For this purpose, the author places her main focus on the interplay of media practices, citizens’ agency, and urban daily life, deploying a methodological approach based on