03 - MSP430 Programming PDF
03 - MSP430 Programming PDF
Introduction
If you’ve programmed most any mainstream microcontroller, this module shouldn’t be too much
of a surprise. What may surprise you is just how little power the MSP430 can draw when the
programmer makes some informed decisions. Most microcontrollers operate in a real-time
environment and respond to either interrupts or timers. The MSP430 is ideally suited to just this
programming model. It can wake quickly, compute quickly and sleep deeply to save power and
has a wide selection of highly capable and low power peripherals.
Learning Objectives
• MSP430 Products
• Operating Modes
• Clock Management
• Peripherals
• Timer
• Coding Tips
Module Topics
MSP430 Programming.............................................................................................................................. 3-1
F23x0
• 16 MIPS
F22xx
• 1-120KB
F21x1 • 500nA Stand By
F21x2 F15x-F16x
F20xx
F13x-F14x F471x7 CG461x
F12xx
1xx-Catalog F/C11xx F43x FG461xx
• 8 MIPS F44x
• 1-60KB F47x4
Fx42x
Fx42x0
F/C41x F = Flash
C = Custom ROM
Integration
Architecture …
2
Ultra-Low-Power Architecture
Modern CPU
Minimum cycles per task
Intelligent peripherals
Instant-on stable high-speed clock
Applications …
3
On demand
MCL K
DCO
CPU and p eriph erals 1uA
Operating modes …
4
Operating Modes
CPU
CPUOff
Off Active
Active Off
DCO Off
DCO
DCOon
on DCOonon All
All
ACLK
ACLKonon ACLK
ACLKonon Clocks
45-65uA 300-500uA <6us ClocksOff
Off
45-65uA 300-500uA 0.1uA
0.1uA
Clock Management …
5
Clock Management
Clock Management: 1xx, 2xx, 4xx
LFXT1CLK ACLK
OSCOFF
12pF LF XT CPUOFF
12pF
VCC
SCG0
SCG1
DCO
Instant on clock …
6
Instant-On Clock
Interrupt
DCO
Operating modes …
7
Effects of temperature …
8
Unused I/Os …
9
External devices …
10
Reduce Cycles …
12
Reduce Cycles
CPU active time is a direct function of how many cycles
need to be executed
Reducing cycles is key to maximizing the use of low-
power modes
Many ways to do this, but an important one is interrupt-
driven coding
UART
RX
9600 baud TX
//
// Polling
Polling UART
UART Receive //
For(;;)
Receive // UART
UART Receive
Receive Interrupt
Interrupt
For(;;) #pragma
#pragma vector=UART_VECTOR
vector=UART_VECTOR
{{ __interrupt void rx (void)
while __interrupt void rx (void)
while (!(IFG2&URXIFG0));
(!(IFG2&URXIFG0)); {{
TXBUF0
TXBUF0 == RXBUF0; TXBUF0
}}
RXBUF0; TXBUF0 == RXBUF0;
RXBUF0;
}}
Timer_A …
13
Timers
Timer_A
Asynchronous TACLK
ACLK
16-bit Timer
TAR
Count
Mode
16-Bit timer/counter SMCLK
INCLK Set
Continuous, TAIFG
up-down,
up count modes CCR0
Multiple
CCR1
capture/compare
registers
CCR2
PWM outputs
CCI2A Capture
TACCR2
Interrupt vector CCI2B Mode
register for fast GND
VCC Compararator 2
decoding CCI
Can trigger DMA SCCI Y A Set
transfer EN
CCIFG2
Counting Modes …
14
Stop/Halt Continuous
Timer is halted Timer continuously counts up
0FFFFh
0h
Up Up/Down
Timer counts between 0 and CCR0 Timer counts between 0 and CCR0 and 0
0FFFFh 0FFFFh UP/DOWN Mode
CCR 0
CCR0
0h 0h
Timer_A Interrupts
The Timer_A Capture/Comparison Register 0 Interrupt Flag
(TACCR0) generates a single interrupt vector:
No handler required
TACCR1 CCIFG
TAIFG
#pragma
#pragma vector
vector == TIMERA1_VECTOR
TIMERA1_VECTOR
__interrupt
__interrupt voidvoid TIMERA1_ISR(void)
TIMERA1_ISR(void)
{{
switch( __even_in_range(TAIV,10))
switch(__even_in_range(TAIV,10))
{{
case
case 22 :: //
// TACCR1
TACCR1 CCIFG
CCIFG
P1OUT
P1OUT ^=^= 0x04;
0x04; break;
break;
case 4
case 4 : : // TACCR2 CCIFG
// TACCR2 CCIFG
P1OUT
P1OUT ^=^= 0x02;
0x02; break;
break;
case
case 10
10 :: //
// TAIFG
TAIFG
P1OUT
P1OUT ^=^= 0x01;
0x01; break;
break;
}}
}}
C Coding Tips …
17
Summary
C Coding Tips
Use local variable as much as possible. Local variables use
CPU registers where global variables use RAM.
Use bit mask instead of bit fields for unsigned int and unsigned
char.
Use unsigned data types where possible
Use pointers to access structures and unions
Use “static const” class to avoid run-time copying of
structures, unions, and arrays.
Avoid modulo
Count down “for” loops
Get to know your C code and its disassembly
Summary …
18
Summary
Proper system design is necessary for the
best low-power performance
Maximize power efficiency by minimizing
program duty cycle
Make good use of all power modes
Reduce program cycles
Lab Time …
19
Measure current
draw of application
Apply low power
design techniques
to reduce current
20
Hardware list:
Software list:
(You will find shortcuts for the above application on the desktop)
Procedure
Measure the Current
1. Baseline
Reconnect the Power jumper on the battery module (the one we used at the end of the
last lab). The LEDs on the attached target board should be flashing again.
Take your Volt-Ohm-Milliameter (VOM) and connect the black banana plug to the COM
input and the red banana plug to the VΩmA input. Remove the Power jumper from the
battery module and put it where you’ll be able to find it again.
On the VOM, select 20m under DCA. Connect the black mini-clip at the other end of the
test lead to the battery module pin nearest the batteries. Connect the red mini-clip to the
pin furthest away from the batteries. If you manage to get this backwards, the current will
merely be negative.
The eZ430-RF2500 target board doesn’t just have a MSP430 on it. When connected to the
battery, the CC2500 is also powered. When powered up, the CC2500 goes into an idle
state and draws about 1.5mA. It is possible to send the device into a sleep state in which it
would draw nanoamps, but that would require us to add most of the SimpliciTI software to
the project. In the interest of doing things simply, we’ll just subtract 1.5mA from our
measurements to get the CPU current.
The Voltage is 2.9V (measure it yourself across the two batteries), so I calculate 14.5mW.
You will be awarded demerits for writing down any values below tenths of a mW.
Table 1
Some of this current is for the LEDs. Let’s get rid of that in the next steps.
With the LEDs blinking, a substantial amount of the current draw could be from them
alone. Let’s turn them off and see what the MCU draws by itself.
Start IAR Embedded Workbench and open the existing workspace Lab3.eww in
C:\Texas Instruments\SimpliciTI-1.0.6\Projects\Examples\
Peer applications\eZ430RF\Lab3. This is simply the project from Lab2 copied over into
a new folder. Open main.c for editing.
Comment out the three LED control statements and replace each of them with
BSP_TURN_OFF_LED2(); as shown below. This will execute exactly the same number
of instructions, but will not light the LEDs.
Build and load the program by clicking the Debug button . When the download is
complete, click the Stop Debugging button . Remove the target board, attach it to the
battery module and measure the current. I got 4.3mA – 1.5mA = 2.8mA and calculated
8.1mW. Enter your values into the table in step 1.
4. Using a Timer
Using CPU cycles to provide a delay time is not only wasteful of CPU cycles and power,
it’s the wrong way to program an MSP430. As an example of how a programmer can use
the peripherals to save power, we’ll use a timer to provide us with a delay. Every MSP430
has a Timer_A peripheral, so let’s use that one.
I didn’t write the code that follows from scratch; I stole it from slac123, which is a
downloadable set of code example for the MSP430F2274 and others. www.ti.com/msp430
is where you can find a ton of example code. Save yourself some time and check it out
before you start coding your project at home.
I dropped the important code pieces into a file named Lab3 Code.txt so you wouldn’t
have to type them in. Click the Open button on the menu, navigate to:
C:\Texas Instruments\SimpliciTI-1.0.6\Projects\Examples\Peer applications\
eZ430RF\Lab3, select Lab3 Code.txt and click Open to open it for editing.
Add LPM0; statements before and after the LED control statements inside the while()
loop, like below:
Cut/paste the top portion of the code from Lab3 Code.txt into main.c just above the
while(1) statement. Cut/paste the middle portion from Lab3 Code.txt into main.c at
the end of the file, like below:
Want to find out more about programming MSP430 timers? Search the TI website for the
MSP430x2xx User’s Guide.
The code won’t be very interesting if we can’t see it work. Comment/un-comment the LED
control statements like below:
6. Build/Load/Run
Take a target board and carefully insert it into the emulator, then build the project. Make
sure that it builds without error, and then click the Go button. The LEDs should be
blinking quite a bit faster than before, but it will do for the purposes of this exercise.
The code that we added controls Timer_A and its interrupt response. In the code right
above while():
The code we added at the bottom of main.c is the Timer_A interrupt service routine.
By the way, LPM0; drops the MSP430 into this operating mode with the DCO on.
Click the Stop Debugging button and un-do the LED code changes we just made:
Build and load the project to the target, then click the Stop Debugging button.
8. Measure Current
Connect the target board to the battery module and measure the current. I got 2.1mA –
1.5mA = 0.6mA or 1.7mW. Write your values into the table.
9. LPM3
In the existing code, we’re running the MSP430 on the DCO at 8MHz. For this code, that’s
overkill. We can easily run it on the VLO (Very Low frequency oscillator) that is internal
to the MSP430. But if we simply change out LPM0; statements to LPM3; the code simply
won’t work; the VLO needs to be setup and the timer needs to be changed to clock on the
VLO.
Delete the four lines of code just above the while() statement and replace them with the
six lines of code at the bottom of Lab3 Code.txt .
Add #include “VLO_Library.h” as the third include file at the top of main.c.
Finally, add unsigned int dco_delta; right below the line defining i.
11. Build/Load/Run
Before testing the code, swap the LED comments back so you can see the code operating.
Build/load/run. The numbers I selected for the timer should look about like what we had
before. Click the Stop Debugging button, swap the LED comments back so the LEDs stay
off and Build/Load the project. Click the Stop Debugging button.
12. Measure
Connect this target board to the battery module and measure the current. I got 1.7mA –
1.5mA = 0.2mA or 0.6mW. Write your values into the table.
Shut the VOM off, wrap the test leads around it and give it to your instructor; we won’t
need it again in this workshop. Shut down IAR Embedded Workbench, disconnect the
eZ430-RF2500 hardware and extender cable and put them aside. Make sure to get that
jumper and place it on one of the battery pins for safekeeping.
You’re done