4_0_EMBEDDED_GR_ppapag_Presentation_TIMERS_LAB

advertisement
MSP430F2013: 2KB + 256B Flash Memory
128B RAM
1
MSP430F2013
2
MSP430F2013 και πηγές ρολογιών
3
Clock System
4
Clock System
•
•
•
•
Low- or high-frequency crystal oscillator, LFXT1: Available in all devices. It is
usually used with a low-frequency watch crystal (32 KHz) but can also run with a
high-frequency crystal (typically a few MHz) in most devices. An external clock signal
can be used instead of a crystal if it is important to synchronize the MSP430 with
other devices in the system.
High-frequency crystal oscillator, XT2: Similar to LFXT1 except that it is restricted
to high frequencies. It is available in only a few devices and LFXT1 (or VLO) is used
instead if XT2 is missing.
Internal very low-power, low-frequency oscillator, VLO: Available in only the
more recent MSP430F2xx devices. It provides an alternative to LFXT1 when the
accuracy of a crystal is not needed.
Digitally controlled oscillator, DCO: Available in all devices and one of the
highlights of the MSP430. It is basically a highly controllable RC oscillator that starts
in less than 1 s in newer devices.
5
Clock System
• ACLK comes from a low-frequency crystal
oscillator at 32 KHz. There is no choice in almost
all devices, the exceptions being those with a
VLO.
• Both MCLK and SMCLK are supplied by the
DCO with a frequency of around 1 MHz. This is
stabilized by the FLL where present. You may
wish to raise this frequency provided that VCC is
high enough to support it.
6
EZ-430
• ACLK δεν είναι συνδεδεμένο σε
κρύσταλλο 32 kHz στο ΕΖ430
7
Μετρητές (Timers) του
MSP430F2013
• 1. Watchdog timer. Η κύρια λειτουργία του watchdog καταχωρητή
είναι στο να προφυλάσσει το σύστημα από ανεπιθύμητη λειτουργία
με το να το επαναφέρει μετά από καθορισμένο χρόνο. Μπορεί να
χρησιμοποιηθεί και ως μετρητής χρονικών διαστημάτων, αν η
προηγούμενη λειτουργία του δεν είναι επιθυμητή.
• 2. Timer_A. Τυπικά ο καταχωρητής αυτός έχει τρία κανάλια, μπορεί
να χειριστεί εξωτερικές εισόδους να μετρήσει συχνότητα και να
οδηγήσει εξόδους σε καθορισμένους χρόνους είτε μία φορά είτε
περιοδικά. Επειδή έχει εσωτερικές συνδέσεις με άλλα τμήματα του
ολοκληρωμένου μπορούμε να τον χρησιμοποιήσουμε για να
μετρήσουμε τη διάρκεια ενός σήματος από το ένα τμήμα στο άλλο
για παράδειγμα. Μπορεί επίσης να παράγει διακοπές (interrupts).
8
Timer A
9
Timer A
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Timer_A clock source select, TASSELx: There are four options for the clock: the
internal SMCLK or ACLK or two external sources.We use SMCLK because it is
always available, which needs TASSELx = 10.
Input divider, IDx: The frequency of the clock can be divided before it is applied to the
timer, which extends the period of the counter.We use the maximum factor of eight,
which needs IDx = 11.
Mode control, MCx: The timer has four modes. By default it is off to save power.We
.rst use the simplest Continuous mode, in which TAR simply counts up through its full
range of 0x0000–0xFFFF and repeats. This needs MCx = 10.
Timer_A clear, TACLR: Setting this bit clears the counter, the divider, and the
direction of the count (it can go both up and down in up/down mode). The bit is
automatically cleared by the timer after use. It is usually a good idea to clear the counter
whenever the timer is reconfigured to ensure that the .rst period has the expected
duration.
Timer_A interrupt enable, TAIE: Setting this bit enables interrupts when TAIFG
becomes set.We do not use this.
Timer_A interrupt .ag, TAIFG: This bit can be modi.ed by the timer itself or by a
program. It is raised (set) by the timer when the counter becomes 0. In continuous mode
this happens when the value in TAR rolls over from 0xFFFF to 0x0000. An interrupt is
also requested if TAIE has been set. The program must clear TAIFG so that the next
overflow can be distinguished.
10
Timer A
•
•
Timer block: The core, based on the 16-bit register TAR. There is a choice
of sources for the clock, whose frequency can be divided down (prescaled).
The timer block has no output but a flag TAIFG is raised when the counter
returns to 0.
Capture/compare channels: In which most events occur, each of which is
based on a register TACCRn. They all work in the same way with the
important exception of TACCR0. Each channel can
– Capture an input, which means recording the “time” (the value in TAR) at which
the input changes in TACCRn; the input can be either external or internal from
another peripheral or software.
– Compare the current value of TAR with the value stored in TACCRn and update
an output when they match; the output can again be either external or internal.
– Request an interrupt by setting its flag TACCRn CCIFG on either of these
events; this can be done even if no output signal is produced.
– Sample an input at a compare event; this special feature is particularly useful if
Timer_A is used for serial communication in a device that lacks a dedicated
interface.
11
Timer A
• The number of channels is sometimes
appended to the name as in Timer_A3.
• Capture/compare channel 0 is special in two
ways. Its register TACCR0 is taken over for the
modulus value in Up and Up/Down modes, so
that it is no longer available for its usual
functions. It also has its own interrupt vector with
a higher priority than the other interrupts from
Timer_A, which all share a common vector.
Therefore channel 0 should be chosen for the
most urgent tasks if it is free.
12
Timer A
13
Timer A
14
Timer_A Counting Modes
The timer has four modes of operation, selected with the MCx bits:
• Stop (MC = 0): The timer is halted. All registers, including TAR, retain their
values so that the timer can be restarted later where it left off.
• Continuous (2): The counter runs freely through its full range from 0x0000
to 0xFFFF, at which point it over.ows and rolls over back to 0. The period is
216 = 65,536 counts. This mode is most convenient for capturing inputs and
is also used when channels provide outputs with different frequencies or
that are not periodic at all.
• Up (1): The counter counts from 0 up to the value in TACCR0, the
capture/compare register for channel 0. It returns to 0 on the next clock
transition. The period is (TACCR0+1) counts. For example, if TACCR0 = 4,
the sequence of counts is 0, 1, 2,3, 4, 0, 1, . . . with period 5. Up mode is
usually used when all channels provide outputs at the same frequency,
often for pulse-width modulation.
• Up/Down (3): The counter counts from 0 up to TACCR0, then down again
to 0 and repeats. The period is 2ΧTACCR0 counts. For example, if
TACCR0=3, the sequence of counts is 0, 1, 2, 3, 2, 1, 0, 1, . . . with period
6. This is a specialized mode, typically used for centered pulse-width
modulation.
15
Timer_A Counting Modes
UP/DOWN Mode
Stop/Halt Mode
Timer is halted with the next +CLK
Timer counts between 0 and CCR0 and 0
0FFFFh
UP/DOWN Mode
CCR0
0h
UP Mode
Continuous Mode
Timer counts between 0 and CCR0
Timer continuously counts up
0FFFFh
Continuous Mode
0FFFFh
CCR0
0h
0h
16
Timer_A 16-bit Counter
15
0
TACTL
Input
Select
unused
160h
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
SSEL1 SSEL0
0
0
0
1
1
0
1
1
Input
Divider
rw(0)
Mode
Control
rw(0)
ID1
ID0
0
0
1
1
0
1
0
1
unTAIE TAIFG
used CLR
rw(0)
rw(0)
MC1
MC0
0
0
1
1
0
1
0
1
rw(0)
(w)(0)
rw(0)
rw(0)
Stop Mode
Up Mode
Continuous Mode
Up/Down Mode
1/1, Pass
1/2
1/4
1/8
TACLK
ACLK
MCLK
INCLK
17
Timer_A 16-bit Control Register
18
Timer_A 16-bit Control Register
• Three items are given for each bit:
• Its position in the word, which should not be needed
• Its name, which is defined in the header file and should
be known to the debugger;
• some bits are not used, which I show by a gray fill.
• The accessibility and initial condition of the bit; here they
can all be read and written with the exception of TACLR,
where the missing r indicates that there is no meaningful
value to read. The (0) shows that each bit is cleared after
a power-on reset (POR).
19
Timer A
• The flag TAIFG in TACTL is set when the
timer counts to 0 and a maskable interrupt
is requested if the TAIE bit is set. The
family user’s guide always shows count in
italics to emphasize that actions such as
setting TAIFG occur only as a result of
normal counting. They do not occur if the
appropriate value is written directly to a
register. For example, setting TACLR
clears TAR but does not set TAIFG.
20
Timer_A Capture Compare Blocks
Overflow x
COVx
Logic
Capture Path
Timer Bus
Data Bus
CMPx
CCISx1 CCISx0
0
CCIxA
1
CCIxB
2
GND
3
VCC
CCMx1
0
0
1
1
15
1
Capture
Mode
Timer
Clock
CCMx0
0 Disabled
1 Pos. Edge
0 Neg. Edge
1 Both Edges
Capture/Compare Register
CCRx
Capture
0
Synchronize
Capture
0
SCSx
15
0
Comparator
to Port0x
EQUx 0
CAPx
1
Compare Path
EN
A
CCIx
CCRx
0172h
to
017Eh
162h
to
16Eh
2
rw(0)
CAPTURE
MODE
rw(0)
SCCIx
0
15
rw(0)
15
CCTLx
Y
15
2
Set_CCIFGx
rw(0)
rw(0)
rw(0)
INPUT
SELECT
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
SCS SCCI
unCAP
used
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
OUTMODx
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
rw(0)
0
rw(0)
0
CCIE CCI
OUT COV CCIFG
rw(0)
rw(0)
r
rw(0)
rw(0)
21
Capture/Compare Channels
• The central feature of each channel is its capture
/compare register TACCRn
• In Capture mode this stores the “time”—the value in
TAR—at which an event occurs on the input;
• In Compare mode it specifies the time at which the
output should next be changed and an interrupt
requested. The mode is selected with the CAP bit. This
is cleared by default so that the channel is in Compare
mode. Any mixture of capture and compare channels
can be used and the mode can be switched freely from
one to the other.
22
23
24
Interrupts from Timer_A
25
Timer_A Output Units
Timer Clock
TAx
EQUx
OUTx (CCTLx.2)
Logic
Output
EQU0
D
Set
Output Signal Outx
Q
To Output Logic TAx
Timer Clock
Reset
POR
Output Mode 0
OUTx
OMx2 OMx1 OMx0
OMx2 OMx1 OMx0 Function
Operational Conditions
0
0
0
Output Mode
Outx signal is set according to Outx bit
0
0
1
Set
EQUx sets Outx signal clock synchronous with timer clock
0
1
0
PWM Toggle/Reset
EQUx toggles Outx signal, reset with EQU0, clock sync. with timer clock
0
1
1
PWM Set/Reset
EQUx sets Outx signal, reset with EQU0, clock synchronous with timer clock
1
0
0
Toggle
EQUx toggles Outx signal, clock synchronous with timer clock
1
0
1
Reset
EQUx resets Outx signal clock synchronous with timer clock
1
1
0
PWM Toggle/Set
EQUx toggles Outx signal, set with EQU0, clock synchronous with timer clock
1
1
1
PWM Reset/Set
EQUx resets Outx signal, set with EQU0, clock synchronous with timer clock
26
•
Output operating modes (OUTMODx bits):
OUTMODx
Mode
Description
000
Output
The output signal OUTx is defined by the bit OUTx
001
Set
OUTx = 1  timer = TxCCRx
OUTx = 0  timer = 0 or until another output mode is selected and
affects the output
010
Toggle/Reset
OUTx = toggle  timer = TxCCRx
OUTx = 0  timer = TxCCR0
011
Set/Reset
OUTx = 1  timer = TxCCRx
OUTx = 0  timer = TxCCR0
100
Toggle
OUTx = toggle  timer = TxCCRx
The output period is double the timer period
101
Reset
OUTx = 0  timer = TxCCRx
OUTx = 1  another output mode is selected and affects the output
110
Toggle/Set
OUTx = toggle  timer = TxCCRx
OUTx = 1  timer = TxCCR0
111
Reset/Set
OUTx = 0  timer = TxCCRx
OUTx = 1  timer = TxCCR0
27
28
Timer_A Continuous-Mode Example
0FFFh
0h
Px.x
TA0 Input
CCR0:
Capture Mode: Positive Edge
Px.y
TA1 Input
CCR1:
Capture Mode: Both Edges
Px.z
TA2 Input
CCR2:
Capture Mode: Negative Edge
CCR0
CCR0
CCR1 CCR1
CCR1
CCR1
CCR1 CCR1
Interrupts can be generated
CCR2
Example shows three independent HW event captures.
CCRx “stamps” time of event - Continuous-Mode is ideal.
29
Timer_A PWM Up-Mode Example
0FFFFh
CCR0
CCR1
CCR2
0h
TA1 Output
CCR1: PWM Set/Reset
Px.x
CCR2: PWM Reset/Set
TA2 Output
Px.y
CCR0: PWM Toggle
Auto
Re-load
TA0 Output
Px.z
EQU2
EQU0
EQU2
EQU1
EQU0
EQU1
EQU2
EQU0
Interrupts can be generated
Output Mode 4: PWM Toggle
Example shows three different asymmetric
PWM-Timings generated with the Up-Mode
30
Timer_A PWM Up/Down Mode Example
0FFFFh
thlfper
CCR0
CCR2
CCR1
CCR3
0h
TA1 Output
0 Degrees
(0.5xVmotor)
Px.x
tpw1
TA2 Output
+120 Degrees
tpw2
(0.93xVmotor)
Px.y
tpw3
-120 Degrees
TA0 Output
Px.z
(0.07xVmotor)
TIMOV
EQU0
TIMOV
EQU0
TIMOV
Interrupts can be generated
Example shows Symmetric PWM Generation Digital Motor Control
31
C Examples, CCR0 Continuous mode
ISR, TA_0 ISR
//***************************************************************
// MSP-FET430P140 Demo - Timer_A Toggle P1.0,
// CCR0 Contmode ISR, DCO SMCLK
// Description; Toggle P1.0 using software and TA_0 ISR. Toggle rate is
// set at 50000 DCO/SMCLK cycles. Default DCO frequency used for TACLK.
// Durring the TA_0 ISR P0.1 is toggled and 50000 clock cycles are added to
// CCR0. TA_0 ISR is triggered exactly 50000 cycles. CPU is normally off
and
// used only durring TA_ISR.
// ACLK = n/a, MCLK = SMCLK = TACLK = DCO~ 800k
//
//
//
MSP430F149
//
--------------//
/|\|
XIN|//
| |
|
//
--|RST
XOUT|//
|
|
//
|
P1.0|-->LED
//
// M. Buccini
// Texas Instruments, Inc
// September 2003
// Built with IAR Embedded Workbench Version: 1.26B
// December 2003
// Updated for IAR Embedded Workbench Version: 2.21B
//**********************************************************************
#include <msp430x14x.h>
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
// Stop WDT
P1DIR |= 0x01;
// P1.0 output
CCTL0 = CCIE;
// CCR0 interrupt enabled
CCR0 = 50000;
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Timer A0 interrupt service routine
interrupt[TIMERA0_VECTOR] void TimerA(void)
{
P1OUT ^= 0x01; // Toggle P1.0
CCR0 += 50000; // Add Offset to CCR0
}
32
//***************************************************************
// MSP-ez430 Demo - Timer_A Toggle P1.0,
// CCR0 Contmode ISR, DCO SMCLK
// Description; Toggle P1.0 using software and TA_0 ISR. Toggle rate is
// set at 50000 DCO/SMCLK cycles. Default DCO frequency used for TACLK.
// Durring the TA_0 ISR P0.1 is toggled and 50000 clock cycles are added to
// CCR0. TA_0 ISR is triggered exactly 50000 cycles. CPU is normally off and
// used only durring TA_ISR.
// ACLK = n/a, MCLK = SMCLK = TACLK = DCO~ 800k
//
//
//
MSP430F149
//
--------------// /|\|
XIN|//
||
|
//
--|RST
XOUT|//
|
|
//
|
P1.0|-->LED
//
// M. Buccini ;P. Papageorgas
// Texas Instruments, Inc
// September 2003
// Built with IAR Embedded Workbench Version: 1.26B
// December 2003
// Updated for IAR Embedded Workbench Version: 2.21B
//**********************************************************************
#include <msp430x20x3.h>
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
// Stop WDT
P1DIR |= 0x01;
// P1.0 output
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 50000;
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
P1OUT ^= 0x01; // Toggle P1.0
CCR0 += 50000; // Add Offset to CCR0
}
33
C Examples, CCR1 Contmode ISR, TA_1
//*****************************************************************
// MSP-FET430P140 Demo –
// Timer_A Toggle P1.0, CCR1 Contmode ISR, CO SMCLK
// Description; Toggle P1.0 using using software and TA_1 ISR.
// Toggle rate is set at 50000 DCO/SMCLK cycles.
// Default DCO frequency used for TACLK.
// Durring the TA_1 ISR P0.1 is toggled and
// 50000 clock cycles are added to CCR1.
// TA_1 ISR is triggered exactly 50000 cycles.
// CPU is normally off and used only durring TA_ISR.
// ACLK = n/a, MCLK = SMCLK = TACLK = DCO ~ 800k
// Proper use of TAIV interrupt vector generator demonstrated.
//
//
MSP430F149
//
--------------//
/|\|
XIN|//
| |
|
//
--|RST
XOUT|//
|
|
//
|
P1.0|-->LED
//
// M. Buccini
// Texas Instruments, Inc
// September 2003
// Built with IAR Embedded Workbench Version: 1.26B
// December 2003
// Updated for IAR Embedded Workbench Version: 2.21B
//**************************************************************
#include <msp430x14x.h>
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
CCTL1 = CCIE; // CCR1 interrupt enabled
CCR1 = 50000;
TACTL = TASSEL_2 + MC_2; // SMCLK, Contmode
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/
interrupt
}
// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A(void)
{
switch( TAIV )
{
case 2:
// CCR1
{
P1OUT ^= 0x01;
// Toggle P1.0
CCR1 += 50000;
// Add Offset to CCR1
}
break;
case 4: break;
// CCR2 not used
case 10: break;
// overflow not used
}
}
34
C Examples, PWM, TA1-2 upmode
//***************************************************************************
// MSP-FET430P140 Demo - Timer_a PWM TA1-2 upmode, DCO SMCLK
//
// Description; This program will generate a two PWM outputs on P1.2/1.3 using
// Timer_A in an upmode. The value in CCR0, defines the period and the
// values in CCR1 and CCR2 the duty PWM cycles. Using ~ 800kHz SMCLK as TACLK,
// the timer period is ~ 640us with a 75% duty cycle on P1.2 and 25% on P1.3.
// ACLK = na, SMCLK = MCLK = TACLK = default DCO ~ 800kHz.
//
//
MSP430F149
//
----------------//
/|\|
XIN|void main(void)
//
| |
|
//
--|RST
XOUT|{
//
|
|
WDTCTL = WDTPW + WDTHOLD;
// Stop WDT
//
|
P1.2|--> CCR1 - 75% PWM
P1DIR |= 0x0C;
// P1.2 and P1.3 output
//
|
P1.3|--> CCR2 - 25% PWM
//
P1SEL |= 0x0C; // P1.2 and P1.3 TA1/2 options
// M.Buccini
CCR0 = 512-1;
// PWM Period
// Texas Instruments, Inc
CCTL1 = OUTMOD_7;
// CCR1 reset/set
// September 2003
// Built with IAR Embedded Workbench Version: 1.26B
CCR1 = 384;
// CCR1 PWM duty cycle
// January 2004
CCTL2 = OUTMOD_7;
// CCR2 reset/set
// Updated for IAR Embedded Workbench Version: 2.21B
CCR2 = 128;
// CCR2 PWM duty cycle
//*****************************************************
TACTL = TASSEL_2 + MC_1;
_BIS_SR(LPM0_bits);
// SMCLK, up mode
// Enter LPM0
}
35
C Examples, CCR0 Upmode ISR, TA_0
//************************************************************************
#include <MSP430G2231.h>
// MSP-FET430P140 Demo - Timer_A Toggle P1.0, CCR0 upmode ISR, 32kHz ACLK
//
void main(void)
// Description; Toggle P1.0 using software and the TA_0 ISR. Timer_A is
{
// configured in an upmode, thus the the timer will overflow when TAR
counts
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// to CCR0. In this example, CCR0 is loaded with 1000-1.
P1DIR |= 0x01; // P1.0 output
// Toggle rate = 32768/(2*1000) = 16.384
CCTL0 = CCIE;
// CCR0 interrupt enabled
// ACLK = TACLK = 32768, MCLK = SMCLK = DCO~ 800k
CCR0 = 1000-1;
// //*An external watch crystal on XIN XOUT is required for ACLK*//
TACTL = TASSEL_1 + MC_1; // ACLK, upmode
//
//
MSP430F149
//
--------------//
/|\|
XIN|//
| |
| 32kHz
//
--|RST
XOUT|//
|
|
//
|
P1.0|-->LED
//
// M. Buccini
// Texas Instruments, Inc
// October 2003
// Built with IAR Embedded Workbench Version: 1.26B
// December 2003
// Updated for IAR Embedded Workbench Version: 2.21B
//************************************************************************
_BIS_SR(LPM3_bits + GIE);
// Enter LPM3 w/ interrupt
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
P1OUT ^= 0x01; // Toggle P1.0
}
36
Simple PWM program (davies)
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
// simppwm1.c - Simple, slow PWM using Timer_A in Up mode from ACLK
// Period = 1s, LED1 at duty cycle D = 1/2, LED2 at D = 1/4
// Olimex 1121STK, LED1 on P2.3 = TA1, LED2 on P2.4 = TA2, active low
// J H Davies, 2007-07-17; IAR Kickstart version 3.42A
//---------------------------------------------------------------------#include <io430x11x1.h>
// Specific device
#include <intrinsics.h>
// Intrinsic functions
//---------------------------------------------------------------------void main (void)
{
WDTCTL = WDTPW | WDTHOLD;
// Stop watchdog timer
// Configure ports 1 and 2; redirect P2.3,4 to Timer_A
P1OUT = BIT0 | BIT1;
// Output high for Freq pin and TXD
P1DIR = BIT0 | BIT1;
P2SEL = BIT3 | BIT4;
// Re-route P2.3 to TA1, P2.4 to TA2
P2DIR = BIT0 | BIT3 | BIT4 | BIT5;
// Piezo and LED outputs
// Set up Timer_A for PWM on active low LEDs, channels 1 and 2
TACCR0 = 0x7FFF;
// 1s period from 32KHz timer clock
TACCR1 = 0x4000;
// Duty cycle D = 1/2
TACCR2 = 0x2000;
// Duty cycle D = 1/4
TACCTL1 = OUTMOD_3;
// Set/reset mode for negative PWM
TACCTL2 = OUTMOD_3;
// Set/reset mode for negative PWM
// Start timer from ACLK, no division, Up mode, clear, no interrupts
TACTL = TASSEL_1 | ID_0 | MC_1 | TACLR;
for (;;) {
// Loop forever
__low_power_mode_3();
// Remain in LPM3, CPU not needed!
}
interrupts)
}
// (nor are
37
Automatic Control: Flashing a Light by PollingTimer_A
• The simplest way of generating a fixed
delay with Timer_A is to wait for TAR to
overflow. This is normally done by
requesting an interrupt but we instead use
polling.
38
8.5.3 Generation of a Precise Frequency
(davies p.328)
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
#define FREQUENCY 880 // Desired frequency of events
// Generally: f_timer = QUOTIENT * FREQUENCY +
REMAINDER
// or QUOTIENT = f_timer / FREQUENCY; REMAINDER =
f_timer % FREQUENCY
#define QUOTIENT 37 // values for 32KHz timer clock
#define REMAINDER 208
// ---------------------------------------------------------------------#pragma vector = TIMERA1_VECTOR
__interrupt void TIMERA1_ISR (void) // Flag NOT cleared
automatically
{
static uint16_t shortfall = 0; // Accumulated (summed) shortfall
TACCTL1_bit.CCIFG = 0; // Acknowledge interrupt
P2OUT ˆ= (BIT0|BIT5); // Toggle piezo sounder
shortfall += REMAINDER; // Update accumulated shortfall
if (shortfall >= FREQUENCY) { // Over threshold for extra
count?
TACCR1 += (QUOTIENT + 1); // Yes: extra count in output
period
shortfall -= FREQUENCY; // Subtrct correction from shortfall
} else {
TACCR1 += QUOTIENT; // No: usual count
}
}
39
LED Flashing by Polling Timer_A
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Listing 4.16: Program timrled1.c to Flash LEDs with a frequency of roughly 1Hz
by polling free-running Timer_A.
// timrled1.c - toggles LEDs with period of about 1.3s
// Poll free -running timer A with period of about 0.65s
// Timer clock is SMCLK divided by 8, continuous mode
// Olimex 1121STK , LED1 ,2 active low on P2.3,4
// J H Davies , 2006 -06 -12; IAR Kickstart version 3.41A
// ---------------------------------------------------------------------#include <io430x11x1.h> // Specific device
// Pins for LEDs
#define LED1 BIT3
#define LED2 BIT4
void main (void)
{
WDTCTL = WDTPW|WDTHOLD; // Stop watchdog timer
P2OUT = L̃ED1; // Preload LED1 on , LED2 off
P2DIR = LED1|LED2; // Set pins for LED1 ,2 to output
TACTL = MC_2|ID_3|TASSEL_2|TACLR; // Set up and start Timer A
// Continuous up mode , divide clock by 8, clock from SMCLK , clear timer
for (;;) { // Loop forever
while (TACTL_bit.TAIFG == 0) { // Wait for overflow
} // doing nothing
TACTL_bit.TAIFG = 0; // Clear overflow flag
P2OUT ˆ= LED1|LED2; // Toggle LEDs
} // Back around infinite loop
}
40
Output in the Up Mode: Edge-Aligned
Pulse-Width Modulation
41
PWM LED FLASH TA0
• TACCR0 = 0x3FFF; // (1/2)s period with 32KHz
clock
• TACCTL0 = OUTMOD_4; // Toggle mode , no
interrupts
• // Start timer from ACLK , no division , Up mode ,
clear , no interrupts
• TACTL = TASSEL_1 | ID_0 | MC_1 | TACLR;
• for (;;) { // Loop forever
• __low_power_mode_3 (); // Remain in LPM3 ,
CPU not needed
• } // (nor are interrupts)
42
Edge-Aligned PWM
43
Edge-Aligned PWM
• Listing 8.14: Very slow pulse-width modulation at 1 Hz on an
Olimex 1121STK in simppwm1.c. LED1 has duty cycle D1 = 1/2
and LED2 has D2 = 1/4 .
• // Set up Timer_A for PWM on active low LEDs , channels 1 and 2
• TACCR0 = 0x7FFF; // 1s period from 32KHz timer clock
• TACCR1 = 0x4000; // Duty cycle D = 1/2
• TACCR2 = 0x2000; // Duty cycle D = 1/4
• TACCTL1 = OUTMOD_3; // Set -reset mode for negative PWM
• TACCTL2 = OUTMOD_3; // Set -reset mode for negative PWM
• // Start timer from ACLK , no division , Up mode , clear , no
interrupts
• TACTL = TASSEL_1 | ID_0 | MC_1 | TACLR;
• for (;;) { // Loop forever
• __low_power_mode_3 (); // Remain in LPM3 , CPU not needed
• } // (nor are interrupts)
44
Led brightness
45
Led brightness
46
Flash led sw delay
•
•
•
•
•
•
// flashled.c - toggles LEDs with period of about 1s
// Software delay for() loop
// Olimex 1121STK, LED1,2 active low on P2.3,4
// J H Davies, 2006-06-03; IAR Kickstart version 3.41A
//---------------------------------------------------------------------#include <msp430x11x1.h>
•
•
•
•
•
// Pins for LEDs
#define LED1
BIT3
#define LED2
BIT4
// Iterations of delay loop; reduce for simulation
#define DELAYLOOPS
50000
•
•
•
void main (void)
{
volatile unsigned int LoopCtr;
•
•
•
•
•
•
•
•
•
// Specific device
// Loop counter: volatile!
WDTCTL = WDTPW | WDTHOLD;
// Stop watchdog timer
P2OUT = ~LED1;
// Preload LED1 on, LED2 off
P2DIR = LED1|LED2;
// Set pins with LED1,2 to output
for (;;) {
// Loop forever
for (LoopCtr = 0; LoopCtr < DELAYLOOPS; ++LoopCtr) {
}
// Empty delay loop
P2OUT ^= LED1|LED2;
// Toggle LEDs
}
}
47
Flash led με timer Α
(Χωρίς Interrupts)
•
•
•
•
•
•
•
// timrled2.c - toggles LEDs with period of about 1.0s
// Poll timer A in Up mode with period of about 0.5s
// Timer clock is SMCLK divided by 8, up mode, period 50000
// Olimex 1121STK, LED1,2 active low on P2.3,4
// J H Davies, 2006-06-16; IAR Kickstart version 3.41A
//---------------------------------------------------------------------#include <io430x11x1.h>
•
•
•
// Pins for LEDs
#define
LED1
#define
LED2
•
•
•
•
•
•
void main (void)
{
WDTCTL = WDTPW|WDTHOLD;
P2OUT = ~LED1;
P2DIR = LED1|LED2;
TACCR0 = 49999;
of count for TAR
TACTL = MC_1|ID_3|TASSEL_2|TACLR;
// Set up and start Timer A
// "Up to CCR0" mode, divide clock by 8, clock from SMCLK, clear timer
for (;;) {
forever
while (TACTL_bit.TAIFG == 0) {
// Wait for overflow
}
// doing nothing
TACTL_bit.TAIFG = 0;
P2OUT ^= LED1|LED2;
}
// Back around infinite loop
}
•
•
•
•
•
•
•
•
•
// Specific device
BIT3
BIT4
// Stop watchdog timer
// Preload LED1 on, LED2 off
// Set pins for LED1,2 to output
// Upper limit
// Loop
// Clear overflow flag
// Toggle LEDs
48
Flash led με timer Α
(Vissim Αυτόματη Παραγωγή κώδικα με Interrupts)
•
•
/*** VisSim Automatic C Code Generator Version 7.0A14 ***/
/* Output for blink-f2013 at Mon Oct 27 22:28:04 2008 */
•
•
•
#include "math.h"
#include "cgen.h"
#include <msp430x20x3.h>
•
extern CGDOUBLE Zed;
•
•
•
•
static __interrupt void cgMain();
static SIM_STATE tSim={0,0,0
,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0};
SIM_STATE *sim=&tSim;
•
#pragma vector=TIMERA0_VECTOR
•
•
•
•
•
•
•
static __interrupt void cgMain()
{
static int _squareCnt1=0;
if ((++_squareCnt1 > 500?(_squareCnt1>=1000?_squareCnt1=0,1:1):0))
P1OUT |= 0x1;
else
P1OUT &= 0xFFFE;
•
}
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
main()
{
WDTCTL = WDTPW + WDTHOLD;
// Disable Watchdog
TACCR0 = 0x2710;
// Timer Period
TACTL = 0x214;
// Timer Control
#define dspWaitStandAlone() __enable_interrupt(); while (1) { LPM1;}
BCSCTL1 = CALBC1_1MHZ; // Use calibrated DCO settings
DCOCTL = CALDCO_1MHZ;
BCSCTL2 = 0x0; // MCLK and SMCLK sel
BCSCTL3 = 0x20; // VLO, range, & CAP sel
TACCTL0 |= CCIE;
// Enable Timer A interrupt
TACTL |= 0x10;
// Start Timer A
P1DIR = 0x1;
simInit( 0 );
startSimDsp();
dspWaitStandAlone();
return 0;
}
49
Self-dimming Led PWM (eZ430) με Interrupts
51
Self-dimming Led PWM (eZ430) με Interrupts (1)
•
•
•
•
•
•
•
// eZ430led2.c - self-dimming LED on P1.0 in eZ430 using SD16A
// PWM controlled by software, about 100Hz from ACLK = VLO,
// SD16A measures light during off phase of PWM
// Calibrated 8MHz DCO, no crystal, ACLK from VLO, power from JTAG (SBW)
// J H Davies, 2007-09-30; IAR Kickstart version 3.42A
//---------------------------------------------------------------------#include <io430x20x3.h>
•
•
•
•
•
•
•
•
#include <intrinsics.h>
//#include <stdint.h>
#define
LED_OUT
#define
LED_ANALOG
#define
RANGE
#define PWM_MAX
#define
DIVISOR
#define
SENSE_TIME
•
•
//uint16_t dutyCycle = PWM_MAX;
•
•
•
•
•
•
•
•
•
•
•
•
•
•
void main (void)
{
WDTCTL = WDTPW | WDTHOLD;
// Stop watchdog
BCSCTL1 = CALBC1_8MHZ;
DCOCTL = CALDCO_8MHZ;
BCSCTL2 = DIVS_3;
BCSCTL3 = LFXT1S_2;
P2SEL = 0;
P2REN = BIT6|BIT7;
P1REN = ~BIT0;
P1DIR = BIT0;
LED_OUT = 0;
// Configure SD16A: clock from SMCLK, no division, internal reference on
SD16CTL = SD16XDIV_0 | SD16DIV_0 | SD16SSEL_1 | SD16REFON;
// Header file for this device
// Intrinsic functions
// Standard integer types
P1OUT_bit.P1OUT_0
// Output to LED on P1.0
SD16AE_bit.SD16AE0
// Enable analog input from LED
4096
// Dynamic range of values from SD16
128
// Maximum value of duty cycle
(RANGE/PWM_MAX)
// For converting SD16 -> PWM
2
// Cycles of TACLK needed for SD16
// Duty cycle computed from SD16
unsigned int dutyCycle = PWM_MAX;
// Start at maximum (but LED off)
// Calibrated range for DCO
// Calibrated tap and modulation
// SMCLK = DCO / 8 = 1MHz
// Select ACLK from VLO (no crystal)
// Digital i/o rather than crystal
// Pull Rs on unused pins (6 and 7)
// Pull Rs on all pins except 0
// To drive LED on P1.0
// LED initially off (active high)
52
Self-dimming Led PWM (eZ430) με Interrupts (2)
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
// Unipolar, single convs, OSR = 32, interrupts on finish
SD16CCTL0 = SD16UNI | SD16SNGL | SD16OSR_32 | SD16IE;
// PGA gain = 16, input channel A0+/-, result after 4th conversion
SD16INCTL0 = SD16GAIN_16 | SD16INCH_0 | SD16INTDLY_0;
// Timer_A for software-assisted PWM using channel 1, up to TACCR0 mode
TACCR0 = PWM_MAX + SENSE_TIME;
// Overall period
TACCR1 = dutyCycle;
// Initial duty cycle
TACCTL1 = CCIE;
// Interrupts on compare
// Start Timer_A from ACLK, undivided, up mode, clear, interrupts
TACTL = TASSEL_1 | ID_0 | MC_1 | TACLR | TAIE;
for (;;) {
// Loop forever
__low_power_mode_3();
// All action in interrupts
}
}
//---------------------------------------------------------------------// Interrupt service routine for CCIFG1 and TAIFG; share vector
//---------------------------------------------------------------------#pragma vector = TIMERA1_VECTOR
__interrupt void TIMERA1_ISR (void)
// Shared ISR for CCIFG1 and TAIFG
{
switch (__even_in_range(TAIV, TAIV_TAIFG)) {
// Acknowledges int
case 0:
// No interrupt pending
break;
// No action
case TAIV_TAIFG:
// TAIFG vector
// Start PWM duty cycle by turning LED on and updating duty cycle
LED_OUT = 1;
// Turn LED on; duty cycle always > 0
TACCR1 = dutyCycle;
// Update duty cycle from SD16 reading
break;
case TAIV_CCIFG1:
// CCIFG1 vector
// Finish PWM duty cycle by turning off LED, then measuring light level
LED_OUT = 0;
// End of duty cycle: Turn off LED
LED_ANALOG = 1;
// Switch LED to SD16A input A0+
SD16CCTL0_bit.SD16SC = 1;
// Start SD16A conversion
// Change mode from LPM3 to LPM0 on exit to provide SMCLK for SD16
__bic_SR_register_on_exit(LPM3_bits);
__bis_SR_register_on_exit(LPM0_bits);
break;
default:
// Should not be possible: ignore
break;
}
}
53
Self-dimming Led PWM (eZ430) με Interrupts (3)
•
•
•
•
•
•
•
//---------------------------------------------------------------------// ISR for SD16A: compute new duty cycle in range [1, PWM_MAX]
//---------------------------------------------------------------------#pragma vector = SD16_VECTOR
__interrupt void SD16_ISR (void) // Acknowledged when SD16MEM0 read
{
static unsigned int floor = 0xFFFF - RANGE;
// Dark reading from SD16
•
•
•
•
•
•
•
•
•
•
•
•
•
LED_ANALOG = 0;
// Switch LED back to digital output
if (SD16MEM0 < floor) {
// Update floor if new reading is lower
floor = SD16MEM0;
dutyCycle = 1;
// Minimum value; never go down to 0
} else if (SD16MEM0 >= (floor + RANGE - DIVISOR)) {
dutyCycle = PWM_MAX; // Maximum value (saturates)
} else {
dutyCycle = (SD16MEM0 - floor) / DIVISOR + 1;
}
// Change mode from LPM0 to LPM3 on exit: SMCLK no longer needed
__bic_SR_register_on_exit(LPM0_bits); // (not really necessary)
__bis_SR_register_on_exit(LPM3_bits);
}
54
Self-dimming Led PWM (eZ430) με Interrupts (4)
• How should the program be designed? The brightness of
the LED is controlled by pulse-width modulation in the
usual way. One possibility is to let the PWM run at a
fixed duty cycle for several periods, then interrupt it to
measure the intensity of the ambient light.
• The duty cycle is updated for the next burst of PWM. I
take a different approach, which is to measure the
intensity during the dark part of each cycle of PWM. This
means that the duty cycle cannot be raised all the way to
100%, but the logarithmic response of the eye means
that this is never noticed.
55
Self-dimming Led PWM (eZ430) με Interrupts (5)
• I ran Timer_A from ACLK, which is in keeping with the low-power
spirit of the MSP430 although it seems pointless when driving an
LED. There is no crystal in the eZ430–F2013 so ACLK is supplied
by the VLO at about 12KHz. I like to run LEDs at a frequency of
atleast 100Hz to avoid flickering, which gives about 120 clock cycles
of Timer_A per period. This is rather limited resolution but could be
improved only by using a faster clock. We do not need high
resolution from the ADC so I configured the SD16_A for its lowest
oversampling ratio of 32. The measurement should be completed as
quickly as possible and the clock is therefore taken from SMCLK at
a calibrated 1MHz. A single measurement actually requires four
conversions because of the SDA3 bug in this device and therefore
takes 4×32 = 128 s. This is about 1.5 cycles of ACLK, which rounds
up to 2.
56
SLAZ026I - 04/28/2008 Copyright © 2008, Texas Instruments Incorporated
MSP430F20xx Device Erratasheet
SDA3 SDA3 - Bug description
• Module: SD16_A, the interrupt delay function can result
in incorrect conversion data. The interrupt delay
operation can result in incorrect conversion data when
SD16INTDLYx = 01,10, or 11.
Workaround:
• Use SD16INTDLYx = 00 setting (Interrupt generated
after 4th conversion). This applies to the first conversion
in Continuous mode and to each conversion in Single
mode.
57
Download