MSP430 assembly language programs

I got a simple and user friendly msp430 assembler for linux. It is the "naken430asm", developed by Michael Khon. It is free to download from his website http://www.mikekohn.net

 Here are few example programs which I had done as a part of learning msp430 assembly language programming..
(microcontroller used -> MSP430G2231)
(assembler  used         ->naken430asm)


To familiarize the assembly language programming, I did some basic codes and tested it in the launchpad. Those codes are below...


Example .1
To turn on the RED led (P1.0) on the msp430 launchpad:

.include "msp430g2x31.inc"
org 0xf800
start:
     mov.w #(WDTPW|WDTHOLD), &WDTCTL ; disable watchdog timer
     mov.b #1,&P1DIR                 ; set  P1.0 as output
     mov.b #1,&P1OUT                 ; set P1.0 bit as high
loop1:
     jmp loop1   ; infinite loop
org 0xfffe       ; reset vector 
     dw 0xf800   ; pointing the reset vector to starting address

Steps to program the chip on the launchpad:

(assuming naken430asm and mspdebug are already installed)
  • save the file as *.asm, say led.asm.
  • in terminal, type naken430asm led.asm to generate the hex file.
  • now using mspdebug, the hex file could be burned into the launhpad.
  • command: sudo mspdebug rf2500
  • type prog out.hex to program the chip.
  • type run to run the code in chip
  • to stop, press ctrl + c 
 0xfffe is the reset vector address. When it resets, the program counter (PC/r0) is loaded with the 16 bit value in the reset vector address, ie here it will be loaded with the starting address of the program...Program memory of the msp430g2231 starts at 0xf800 and ends at 0xffff.


Example .2
To blink RED led (P1.0)
.include "msp430g2x31.inc"
org 0xf800
start:
     mov.w #(WDTPW|WDTHOLD), &WDTCTL   
     mov.b #1, &P1DIR                   
loop1:
     xor.b #1, &P1OUT
     mov #50000, r15  ;delay depends on the value moved to r15
delay:
     dec r15
     jnz delay
     jmp loop1
org 0xfffe
     dw start 



 Example .3
To toggle LED1 and LED2 (P1.0 ans P1.6)
    .include "msp430g2x31.inc"
    org 0xf800
    start:
         mov.w #(WDTPW|WDTHOLD), &WDTCTL   
         mov.b #(1|64), &P1DIR  ; set P1.0 as output 
         mov.b #1, &P1OUT
    loop1:
         xor.b #(1|64), &P1OUT
         mov #0xffff, r15
    delay:
         dec r15
         jnz delay
         jmp loop1
    org 0xfffe
         dw start
    



    Example .4
    To toggle LED1 and LED2 (P1.0 ans P1.6)-  (delay as a function)

    .include "msp430g2x31.inc"
    org 0xf800
    ;;;;;;;;DELAY FUNCTION;;;;;;;;;
    delay:
            mov.w #60000, r5
    l1:
            dec r5
            jnz l1
            ret
    ;;;;;;;;START;;;;;;;;;;;;;;;;;;
    start:
            mov.w #(WDTPW|WDTHOLD), &WDTCTL
            mov.w #0x280, SP
    ;;;;;;;;MAIN;;;;;;;;;;;;;;;;;;;
    main:
            mov.b #01000001b, &P1DIR
            mov.b #1, &P1OUT
    mainloop:
            xor.b #01000001b, &P1OUT
            call #delay
            jmp mainloop
    ;;;;;;;;;VECTORS;;;;;;;;;;;;;;;
    org 0xfffe
            dw start
    

    'call #delay' will call the delay function. What exactly happening is,
    SP - 2 ->SP,  PC+2 ->@SP, #delay ->PC

    Now in 'ret' ,
    @SP ->PC, SP+2 ->SP


    Example .5
    Timer interrupt on TAR overflow
    .include "msp430g2x31.inc"
    org 0xf800
    start:
         mov.w #(WDTPW|WDTHOLD), &WDTCTL
         mov.w #0x280, SP      
         mov.b #255,&P1DIR
         mov.b #0,&P1OUT
         mov.w #(TASSEL_2|MC_2|ID_3|TAIE), &TACTL
         eint
    gg:
         jmp gg
    
    isr:
         xor.b #1,&P1OUT  ;toggle LED.1 on interrupt
         bic.w #1, &TACTL ;clearing the TAIFG (flag)
         reti
    
    org 0xfffe           ;reset vector
         dw start
    org 0xfff0
         dw isr
    
    Here, the LED.1 will toggle on every timer interrupt... On every timer overflow (TAR), the timer interrupt flag (TAIFG) will set.. Since GIE and TAIE is enabled, on every timer overflow, a timer interrupt will occur. At this time, the program  counter will be loaded with the address stored in the timer interrupt vector address 0xfff0.

    Example .6
    Timer interrupt when TAR = TACCR0      (CCIFG)
    .include "msp430g2x31.inc"
    org 0xf800
    start:
             mov.w #(WDTPW|WDTHOLD), &WDTCTL
             mov.w #0x280, SP       
             mov.b #255,&P1DIR
             mov.b #0,&P1OUT
             mov.w #(TASSEL_2|MC_1|ID_3), &TACTL
             mov.w #(CCIE), &TACCTL0
             mov.w #50000, &TACCR0
             eint
    gg:
            jmp gg
    
    isr:
            xor.b #1,&P1OUT ; toggle LED1 on interrupt
            reti
    org 0xfffe           ;reset vector
           dw start
    org 0xfff2
           dw isr
    
    In this case, the interrupt occur when the timer value (TAR) matches the TACCR0 value.. Here the interrupt vector(0xfff2) is different from the previous example. Also, instead of TAIE , CCIE is enabled... We could set the value of TACCR0 to adjust the time period of the periodic interrupt... Here, the CCIFG is cleared automatically in the hardware...

    Example .7
    Software implementation of a Linear Feedback shift register (LFSR)
    (Pseudo random number generation)
     (A 16-bit Fibonacci LFSR)
    .include "msp430g2x31.inc"
    org 0xf800
    start:
     mov.w #(WDTPW|WDTHOLD), &WDTCTL
     mov.w #0x280, SP 
            mov.b #255,&P1DIR
          mov #3323,R4  ;seed value in r4
    loop1:  
     mov.b r4, &P1OUT ;showing 8 bit of the shift register in port1
     mov r4,r5
     mov r4,r10
     rra r5
     rra r5
     xor r5,r10
     rra r5
     xor r5,r10
     rra r5
     rra r5
     xor r5,r10
     rra r4
     bit #1,r10
     jnz aa
     bic #(1<<15),r4
     jmp bb
    aa:
     bis #(1<<15),r4
    bb:
     mov #30000,r6
    cc:
     dec r6
     jnz cc
     jmp loop1
     
    org 0xfffe           ;reset vector
           dw start
    
    This is just a software implementation of a 16 bit fibonacci LFSR (in above figure)
    Here, register r4 emulates the linear feedback shift register. Instruction rra is used to shift one position to right. 8 bits of r4 is moved to PORT1 to show the 8 least bits of the LFSR on LEDs connected to PORT1. Also, if we connect a single LED at any of the P1 bits, we could observe the streaming of 'pseudo' random sequence. It is called 'pseudo' just because it is not really a random sequence even though it seems to be a ramdom sequence....
    LFSR have great practical importance, for example:
    Direct-sequence spread spectrum radio, Generating an approximation of white noice ,Cryptography etc.......

    Example .8
    1 second accurate timer using ACLK clock (32768Hz external crystal oscillator is to be soldered)
    ;---------------------------------------------------------
    ;author                  :vinod s (vinodstanur@gmail.com)
    ;date                    : sat June 9, 11:42:51PM
    ;PROCESSOR               : MSP430G2231
    ;assembler               : naken430asm
    ;development platform    : linux
    ;NOTE: 32768Hz crystal must be soldered to the launchpad
    ;      before doing this test program
    ;--------------------------------------------------------
    .include "msp430g2x31.inc"
    
    org 0xf800             ;flash begins 
    start:                 ;startup code which sets the stack pointer and disable WDT
        mov.w #(WDTPW|WDTHOLD), &WDTCTL ;disabling watch dog timer, otherwise it will reset on regular interval
        mov.w #0x27f, SP     ;SETTING TOP OF THE STACK ON STACK POINTER
        call #main           ; NOT NEEDED ANY WAY :-)
      
    main:
        mov.b #0, &P1OUT
        mov.b #1,&P1DIR       ;setting port1 bit 0 as output
        mov.b #(XCAP_3), BCSCTL3 ;selecting internal capacitor value for crystal
        mov.w #32767, &TACCR0 ;seting the timer compare value for interrupt
        mov.w #CCIE, &TACCTL0 ;compare interrupt enable
        mov.w #(TASSEL_1|MC_1|TACLR), &TACTL ;setting the timer with ACLK clock
        eint                                 ;general interrupt enable
        bis.b #(11011000b),SR                ;entering LOW POWER MODE 3
      
    ;WILL NEVER REACH HERE (CPU OFF , SMCLK OFF)
    
    isr: ;LED flashing routine which happens on every second
        mov.b #1, &P1OUT
        mov.w #10000, R10
        small_delay_loop: dec.w R10
        jnz small_delay_loop
        mov.b #0, &P1OUT
        reti  
    
    ;VECTORS
    org 0xfffe                  ;reset vector
        dw start             ;to write start address to 0xfffe on programming
    org 0xfff2                  ;timer interrupt vector (CC)
        dw isr               ;to write isr address to 0xfff2 on programming
    

    5 comments :

    1. Very good post. In the example number 2 you load the register "r15" with the number 50000. Can you tell me how long is the delay? Thank you very much.

      ReplyDelete
    2. i have also published some examples based on msp430.
      http://emergingtechnologies1.blogspot.in/2014/05/msp-exp430g2-assembly-languge.html

      ReplyDelete
    3. How to set dco clock in assembly language.

      ReplyDelete
    4. There is now a clock course in assembly on Udmey.com entitled MSP430FR4311 Clock Operation Notes that pretty much does it all.

      ReplyDelete