MSP430 Assembly Code Examples from Class: Difference between revisions
Jump to navigation
Jump to search
Line 169: | Line 169: | ||
;------------------------------------------------------------------------------- |
;------------------------------------------------------------------------------- |
||
.text ; Assemble into program memory |
.text ; Assemble into program memory |
||
.global RESET |
.global RESET ; Remember to set linker option to enter at RESET. |
||
.retain ; Override ELF conditional linking |
.retain ; Override ELF conditional linking |
||
; and retain current section |
; and retain current section |
||
Line 219: | Line 219: | ||
.end |
.end |
||
</nowiki> |
</nowiki> |
||
====Change the Blink Period of an LED running on Timer TA0, Using Interrupts on P1.1 (S2)==== |
====Change the Blink Period of an LED running on Timer TA0, Using Interrupts on P1.1 (S2)==== |
||
<nowiki> |
<nowiki> |
Revision as of 11:10, 9 November 2015
Fibonacci Sequence (Mystery Program from ece382.com)
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This is the Fibonacci Sequence Program. f0=0, f1=1, fn=(fn-1)+(fn-2). ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- mov.w #0x2400, r9 mov.w #10, r10 mov.w #0, r11 mov.w r11, 0(r9) mov.w #1, r12 incd r9 mov.w r12, 0(r9) loop tst r10 jz forever incd r9 dec r10 mov.w r12, r13 add.w r11, r12 mov.w r12, 0(r9) mov.w r13, r11 jmp loop forever jmp forever ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET
Use S2 (P1.1) to turn on and off LED1 (P1.0).
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; ; ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- bis.b #BIT0, &P1DIR ; Set the P1.0 as output for the LED. bic.b #BIT1, &P1DIR ; Set P1.1 for input. bis.b #BIT1, &P1REN ; Set pull up for switch on P1.1 bis.b #BIT1, &P1OUT ; Make the pull up pull up not down.forever loop bit.b #BIT1, &P1IN ; Check if the button is switched. jnz off on bis.b #BIT0, &P1OUT ; Toggle the LED jmp loop off bic.b #BIT0, &P1OUT ; Turn the LED off to start with. jmp loop ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET
Simple Blink the LED without Interrupts
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; Blink the LED using no interrupts. ; Rob Frohne, 2014 ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- ; This program is to blink the red LED on the MSP430F5529 LaunchPad. bis.b #1,&PADIR outer xor.b #1,&PAOUT mov.w #0x2710,r5 inner dec.w r5 tst.w r5 jne inner jmp outer ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET
Blink the LED Using Timer TA0 and Interrupts
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This program blinks the LED on P1.0 at one Hz period using TimerA0 ; and interrupts. ; Rob Frohne, 11/17/2014. ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET ; Remember to set linker option to enter at RESET. .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- bis.b #BIT0, &P1DIR ; Set the LED at P1.0 as output. bic.b #BIT0, &P1OUT ; Ensure the LED is off to start with. bic.w #MC0|MC1, &TA0CTL ; Turn off timer TA0. bis.w #TACLR, &TA0CTL ; Clear the timer TAR. bis.w #TASSEL__ACLK, &TA0CTL ; Use ACLK (32 KHz). This means 2 seconds a period. bic.w #ID0|ID1, &TA0CTL ; Divide by 4. bic.w #TAIFG, &TA0CTL ; Clear the interrupt flag. bis.w #MC0, &TA0CTL ; Set timer mode to count to TA0CCR0. bis.w #TAIE, &TA0CTL ; Enable timer TA0 interrupts. mov.w #0x3fff, &TA0CCR0 ; Make it count up to 1/4 maximum, meaning 1 second on off period. nop bis.w #LPM3|GIE, SR ; Put the processor in Low Power Mode 3 (ACLK still active) & Enable Interrupts. nop ; No loop necessary. All done by interrupts. TA0_ISR cmp.w #TA0IV_TAIFG, &TA0IV ; Check if the timer overflowed. (Other opitons exist.) jnz not_correct_flag ; If TA0IV not equal to 0x000e, it wasn't an overflow. xor.b #BIT0, &P1OUT ; Toggle the LED at P1.0. not_correct_flag bic.w #TAIFG, &TA0CTL ; This is the ISR. Clear interrupt flag reti ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET .sect ".int52" ; Timer0_A5 Interrupt Service Routine /* 0xFFE8 Timer0_A5 CC1-4, TA */ .short TA0_ISR ; page 49, http://www.ti.com/lit/ug/slau157af/slau157af.pdf .end
Change the Blink Period of an LED running on Timer TA0, Using Interrupts on P1.1 (S2)
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This program blinks the LED on P1.0 at one Hz period using TimerA0 ; and interrupts, until you press the button S2 connected to P1.1, ; then it changes the blink rate. ; Rob Frohne, 11/17/2014. ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET ; Remember to set linker option to enter at RESET. .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- bis.b #BIT0, &P1DIR ; Set the LED at P1.0 as output. bic.b #BIT0, &P1OUT ; Ensure the LED is off to start with. bic.w #MC0|MC1, &TA0CTL ; Turn off timer TA0. bis.w #TACLR, &TA0CTL ; Clear the timer TAR. bis.w #TASSEL__ACLK, &TA0CTL ; Use ACLK (32 KHz). This means 2 seconds a period. bic.w #ID0|ID1, &TA0CTL ; Divide by 1. bic.w #TAIFG, &TA0CTL ; Clear the interrupt flag. bis.w #MC0, &TA0CTL ; Set timer mode to count to TA0CCR0. bis.w #TAIE, &TA0CTL ; Enable timer TA0 interrupts. mov.w #0x3fff, &TA0CCR0 ; Make it count up to 1/4 maximum, meaning 1 second on off period. bis.b #BIT1, &P1REN ; Enable resistor on P1. bis.b #BIT1, &P1OUT ; Make it a pull up resistor. bis.b #BIT1, &P1IE ; Enable the interrupt on P1.1. bic.b #BIT1, &P1IFG ; Clear the P1.1 interrupt flag. bis.b #BIT1, &P1IES ; Look for high to low transitions only. mov.w #0, r4 ; This will toggle to make a delay for the switch on P1.1. nop bis.w #LPM3|GIE, SR ; Put the processor in Low Power Mode 3 (ACLK still active) & Enable Interrupts. nop ; No loop necessary. All done by interrupts. TA0_ISR cmp.w #TA0IV_TAIFG, &TA0IV ; Check if the timer overflowed. (Other opitons exist.) jnz not_correct_flag ; If TA0IV not equal to 0x000e, it wasn't an overflow. xor.b #BIT0, &P1OUT ; Toggle the LED at P1.0. cmp #1, r4 ; Check flag to see if we need to debounce the switch. jnz debounce bis.b #BIT1, &P1IE ; Enable the interrupt on P1.1 if it isn't the first time after the button was pressed. debounce mov.w #0, r4 ; Reset the flag on the button switch. not_correct_flag bic.w #TAIFG, &TA0CTL ; This is the ISR. Clear interrupt flag reti PORT1_ISR ; This is the ISR that gets called when you push the S2 (P1.1 button). bic.w #MC0|MC1, &TA0CTL ; Turn off timer TA0. bis.w #ID0|ID1, &TA0CTL ; Divide by 8. bis.w #MC0, &TA0CTL ; Set timer mode to count to TA0CCR0. bis.w #TAIE, &TA0CTL ; Enable timer TA0 interrupts. bic.b #BIT1, &P1IFG ; Clear the Port 1 interrupt flag. bic.b #BIT1, &P1IE ; Disable the interrupt on P1.1. mov.w #1, r4 ; This is the flag that the button was just pushed. reti ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET .sect ".int52" ; Timer0_A5 Interrupt Service Routine /* 0xFFE8 Timer0_A5 CC1-4, TA */ .short TA0_ISR ; page 49, http://www.ti.com/lit/ug/slau157af/slau157af.pdf .sect ".int47" ; Port1 Interrupt vector (FFDE). .short PORT1_ISR .end
Put PWM on Port P1.2
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This program blinks the LED if you hook it up to P1.2 at one Hz period using TimerA0 ; and no interrupts. The duty cycle is TA0CCR1/TA0CCR0. ; Rob Frohne, 11/17/2014. ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET ; Remember to set linker option to enter at RESET. .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- bis.b #BIT2, &P1DIR ; Set the LED at P1.2 as output. bis.b #BIT2, &P1SEL ; Select the TA0.2 instead of GPIO. bic.w #MC0|MC1, &TA0CTL ; Turn off timer TA0. bis.w #TACLR, &TA0CTL ; Clear the timer TAR. bis.w #TASSEL__ACLK, &TA0CTL ; Use ACLK (32768 Hz). bis.w #ID1, &TA0CTL ; Divide by 4. Gives 1/4096 uS per tic, because we are using up and down mode. bic.w #ID0, &TA0CTL ; The other bit to divide by 4. bis.w #MC0|MC1, &TA0CTL ; Set timer mode to count to TA0CCR0 and then back down. bic.w #CAP, &TA0CCTL1 ; Set compare mode. bis.w #OUTMOD_2, &TA0CCTL1 ; Toggle/Reset mode: this gives duty cycle of TA0CCR1/TA0CCR0. mov.w #4096, &TA0CCR0 ; This gives a 1 second period. mov.w #1024, &TA0CCR1 ; 25% duty cycle. bis.w #MC0|MC1, &TA0CTL ; Turn on timer TA0. nop bis.w #LPM3, SR ; Put the processor in Low Power Mode 3 (ACLK still active). nop ; No loop necessary. All done by interrupts. ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET .end
PWM to drive the Robot Wheels
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This program blinks the LED on P1.0 at one Hz period using TimerA0 ; and interrupts. ; Rob Frohne, 11/17/2014. ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET ; Remember to set linker option to enter at RESET. .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- ; Use Output Mode 2 (Toggle/Reset) with timer up then down counting. Then TAxCCRn will determine the duty cycle. ; Use P1.2 and P1.3 (TA0.1 and TA0.2) for the left and right wheels respectively. ; If we use the ACLK, the smallest step in pulse is 30.518 microseconds. The SMCLK gives .125 microseconds. ; The servo needs a resolution of at least 5 microseconds, so we better use the SMCLK. bis.b #BIT2|BIT3, &P1DIR ; Set P1.2 and P1.3 as output. bis.b #BIT2|BIT3, &P1SEL ; Select the peripheral (TA0.2 and TA0.3) bic.w #MC0|MC1, &TA0CTL ; Turn off timer TA0. bis.w #TACLR, &TA0CTL ; Clear the timer TAR. bis.w #TASSEL__SMCLK, &TA0CTL ; Use SMCLK (not 8 MHz, about 1 MHz). C example ta0_16 says 1.045 MHz. bis.w #ID1, &TA0CTL ; Divide by 4. Gives 1uS per tic, because we are using up and down mode. bic.w #ID0, &TA0CTL ; The other bit to divide by 4. bis.w #MC0|MC1, &TA0CTL ; Set timer mode to count to TA0CCR0 and then back down. bic.w #CM0|CM1, &TA0CCTL1 ; One wheel, turn off capture mode. bic.w #CM0|CM1, &TA0CCTL2 ; The other wheel.... bic.w #CAP, &TA0CCTL1 ; Set compare mode. bic.w #CAP, &TA0CCTL2 ; The other wheel.... bis.w #OUTMOD_2, &TA0CCTL1 ; Toggle/Reset mode bis.w #OUTMOD_2, &TA0CCTL2 ; The other wheel.... bic.w #CCIE, &TA0CCTL1 ; No interrupts needed for the PWM. bic.w #CCIE, &TA0CCTL2 ; The other wheel.... mov.w #0x0a6a, &TA0CCR0 ; This gives a 20 mS period. Was 4e20. Experimentally determined to be 0xa6a. mov.w #0x00d0, &TA0CCR1 ; Makes both wheels stopped. (1500 uS) Experimentally determined to be 0xc8. mov.w #0x00b8, &TA0CCR2 ; The other wheel.... bis.w #MC0|MC1, &TA0CTL ; Turn on the timer. nop bis.w #LPM0, SR ; Put the processor in Low Power Mode 0 (SMCLK still active). nop ; No loop necessary. All done by interrupts. ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET .end
Analog to Digital Conversion Example
;------------------------------------------------------------------------------- ; MSP430 Assembler Code Template for use with TI Code Composer Studio ; ; This program demonstrates reading the A0 with reference to AVcc. ; A single conversion is done, then it sleeps forever. ; Software sets ADC12SC to start the sample and conversion and automatically ; ADC12SC is cleared at end of conversion. ADC12 internal oscillator times ; sample (16x) and conversion. In main loop we wait in LPM0 to save power until ; conversion is complete, ADC12_ISR will force exit from LPM0 on reti. ; If A0 > (1/2) AVcc, P1.0 LED is lit, else not. ; Rob Frohne, 12/4/2014. ;------------------------------------------------------------------------------- .cdecls C,LIST,"msp430.h" ; Include device header file ;------------------------------------------------------------------------------- .text ; Assemble into program memory .global RESET ; Remember to set linker option to enter at RESET. .retain ; Override ELF conditional linking ; and retain current section .retainrefs ; Additionally retain any sections ; that have references to current ; section ;------------------------------------------------------------------------------- RESET mov.w #__STACK_END,SP ; Initialize stackpointer StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer ;------------------------------------------------------------------------------- ; Main loop here ;------------------------------------------------------------------------------- mov.w #ADC12SHT02|ADC12ON, & ADC12CTL0 ; Sampling time, ADC 12 on mov.w #ADC12SHP, &ADC12CTL1 ; Use sampling timer. mov.w #BIT0, &ADC12IE ; Enable interrupt. bis.w #ADC12ENC, &ADC12CTL0 ; bis.w #BIT0, &P6SEL ; Select ADC instead of GPIO. bis.w #BIT0, &P1DIR ; P1.0 as output. bis.w #ADC12SC, &ADC12CTL0 ; Start conversion nop bis.w #LPM0|GIE, SR ; bis.w #LPM0|GIE, SR doesn't quite work. Put the processor in Low Power Mode 0 and enable interrupts. nop ; no loop needed. We go to sleep forever. ADC12_ISR: cmp.w #ADC12IV_ADC12IFG0, &ADC12IV ; ADC12IFG0 jnz finish cmp.w #0x7ff, &ADC12MEM0 ; compare r8 to AVdd/2 jge on bic.b #BIT0, &P1OUT ; Turn off the LED on P1.0. jmp there on: bis.b #BIT0, &P1OUT ; Turn on LED there: bic.w #ADC12IV_ADC12IFG0, &ADC12IV ; Clear interrupt flag. finish: reti ;------------------------------------------------------------------------------- ; Stack Pointer definition ;------------------------------------------------------------------------------- .global __STACK_END .sect .stack ;------------------------------------------------------------------------------- ; Interrupt Vectors ;------------------------------------------------------------------------------- .sect ".reset" ; MSP430 RESET Vector .short RESET .sect ".int54" ; ADC12 interrupt .short ADC12_ISR .end
Calling Assembly from C/C++
extern "C" { extern int asmfunc(int a); /* declare external asm function */ int gvar = 0; /* define global variable */ } void main() { int var = 5; var = asmfunc(var); /* call function normally */ }
and the Assembly Function called....
.global asmfunc .global gvar asmfunc: mov.w &gvar,R11 add.w R11,R12 ret .end
You can in C also use the asm() function.
asm(";*** this is an assembly language comment");
Also, when moving from assembly to C it is handy to read about the extrinsic functions that you can call in C that do handy little things in assembly. They begin with __. See Section 6.5 of the C/C++ Manual. For example, the eint instruction is:
__enable_interrupt(void);