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
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 isrHere, 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 isrIn 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 startThis 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
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.
ReplyDeletei have also published some examples based on msp430.
ReplyDeletehttp://emergingtechnologies1.blogspot.in/2014/05/msp-exp430g2-assembly-languge.html
How to set dco clock in assembly language.
ReplyDeletelove your post.
ReplyDeleteHappy Independence Day Quotes About India in Tamil 2018
There is now a clock course in assembly on Udmey.com entitled MSP430FR4311 Clock Operation Notes that pretty much does it all.
ReplyDelete