MSP430 - Timer A
Übersicht
- Taktquellen: meist ACLK oder SMCLK
- Zusätzliche Taktteiler: /1, /2, /4, /8
- 16-bit Zähler: von 0 bis 0xFFFF / 65535
- 3 sogenannte capture and compare register CCR0, CCR1 und CCR2
- Capture mode:
- Kopieren des Zählerwertes in das CCR im Falle eine Ereignisses (z. B. Flankenwechsel am Eingangsignal)
- z. B. Messen der Periodendauer und Frequenz von Eingangssignalen
- Compare mode:
- Erzeugen eines Interruptes, wenn CCR-Wert gleich dem Zählerwert
- Automatisches Setzen, Zurücksetzen oder Umschalten eines Pins des MSP430
- Register des Timer A
Der MSP430G2553 hat zwei Timer A, die mit Timer A0 und Timer A1 bezeichnet werden.
Registernamen von Timer A0 und Timer A1__
Description | Timer A0 | Timer A1 |
---|---|---|
Timer A Control Register | TA0CTL | TA1CTL |
Timer A Capture&Compare Register 0 | TA0CCR0 | TA1CCR0 |
Timer A Capture&Compare Register 1 | TA0CCR1 | TA1CCR1 |
Timer A Capture&Compare Register 2 | TA0CCR2 | TA1CCR2 |
Timer A Capture&Compare Control Register 0 | TA0CCTL0 | TA1CCTL0 |
Timer A Capture&Compare Control Register 1 | TA0CCTL1 | TA1CCTL1 |
Timer A Capture&Compare Control Register 2 | TA0CCTL2 | TA1CCTL2 |
Timer A Interrupt Vector 0 | TIMER0_A0_VECTOR | TIMER1_A0_VECTOR |
Timer A Interrupt Vector 1 | TIMER0_A1_VECTOR | TIMER1_A1_VECTOR |
Erzeugen regelmäßiger Interruptsignale
Verwendung des CCR0
Erzeugen eines Interruptsignals mit CCR0
#include <msp430.h>
#include <stdint.h>
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1DIR |= BIT0;
TA0CCR0 = 0;
TA0CCTL0 = CCIE;
TA0CTL = TASSEL_1 + MC_2 + TACLR;
__enable_interrupt();
while (1) {
__low_power_mode_3();
}
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR() {
P1OUT ^= BIT0;
}
Namenskonventionen von Bitfelder in der msp430.h
- Konstanten, die einzelne Bits enthalten werden entsprechend des Datenblatts benannt.
z. B.TACLR
ist gleichBIT2
oder0x04
- Bei Konstanten die mehrere Bits enthalten muss zwischen mit Unterstrich und ohne Unterstrich unterschieden werden.
- Dies zeigt die folgende Tabelle am Beispiel der Mode-Control-Bits
Wert | Beschreinung | Mit Unterstrich | Ohne Unterstrich |
---|---|---|---|
00 | Stop Mode | MC_0 |
0 |
01 | Up Mode | MC_1 |
MC0 |
10 | Continuous Mode | MC_2 |
MC1 |
11 | Up/Down Mode | MC_3 |
MC1 + MC0 |
Berechnungen von Zeitverzögerungen des Timers"
Formel:
mit \(\Delta t\) der Zeitdauer zwischen zwei Ereignissen, \(\Delta n\) der Differenz der Zählerwerte, oder dem CCR-Wert und \(f\) der Frequenz des Taktgebers des Timers.
Mit \(f = 32.768\si{kHz}\) ergeben sich die folgenden Werte
Δn (hex) | Δn (dec) | Δt [ms] |
---|---|---|
0x4000 | 16384 | 500 |
0x8000 | 32768 | 1000 |
0xC000 | 49152 | 1500 |
0xFFFF | 65535 | 1999.97 |
0x10000 | 65536 | 2000 |
Blinken mit 1 Hz
- Um eine LED mit einer Frequenz von 1 Hz blinken zu lassen, muss alle 500 ms der Pin umgeschaltet werden.
- Alle 0x4000 Zählschritte muss eine Interrupt erfolgen.
Lösung 1: Up Mode
Blinken mit 1 Hz - Up Mode
Lösung 2: Continuous Mode
Blinken mit 1 Hz - Continuous Mode
TA0CCR0 = 0x4000;
TA0CCTL0 = CCIE;
TA0CTL = TASSEL_1 + MC_2 + TACLR;
...
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR() {
P1OUT ^= BIT0;
TA0CCR0 += 0x4000;
}
Verwenden aller CCR und des Timer Overflow Interrupts
Verwenden aller CCR und des Timer Overflow Interrupts
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1OUT &= ~BIT0;
P2OUT &= ~(BIT1 + BIT3 + BIT5);
P1DIR |= BIT0;
P2DIR |= BIT1 + BIT3 + BIT5;
TA0CCR0 = 0x2000;
TA0CCTL0 = CCIE;
TA0CCR1 = 0x4000;
TA0CCTL1 = CCIE;
TA0CCR2 = 0x8000;
TA0CCTL2 = CCIE;
TA0CTL = TASSEL_1 + MC_2 + TACLR + TAIE;
__enable_interrupt();
while (1) {
__low_power_mode_3();
}
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR() {
P2OUT ^= BIT1;
TA0CCR0 += 0x2000;
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TimerA1_ISR() {
switch (TAIV) {
case 2:
// CCR1 Interrupt
P2OUT ^= BIT3;
TA0CCR1 += 0x4000;
break;
case 4:
// CCR2 Interrupt
P2OUT ^= BIT5;
TA0CCR2 += 0x8000;
break;
case 10:
// Timer Overflow
P1OUT ^= BIT0;
break;
}
}
Aufgabe
Veränderen Sie Ihre RGB-LED-Programm so, dass die Farben rot, gelb, grün, türkis, blau und violett automatisch durchrotieren. Durch einen Tastendruck soll zwischen mehreren Geschwindigkeiten gewechselt werden können.
Verwenden Sie Interrupt und den Low-Power-Mode. ISR sollen so kurz wie möglich gehalten werden.
Aufgabe
Verändern Sie das vorangengene Programm so, dass anstelle des Timers A0 der Timer A1 verwendet wird.
Erzeugen symmetrischer Rechtecksignale
- Beispiel: Erzeugen eines 440 Hz Rechtecksignals auf Grundlage des 32,768 kHz Taktgebers
- Schalten eines 440 kHz Signals benötigte eine hohe Anzahl von Taktzyklen.
- Die CCR können automatisch spezielle Pins des MSP430 manipulieren. Nach der Initialisierung werden keine CPU-Takte benötigt.
- Diese Pins müssen mit dem Timer A verbunden sein, siehe Pinbelegung des MSP430G2553:
Timer-Pins des MSP430G2553"
Pin | Timer | CCR |
---|---|---|
P1.1 | Timer A0 | CCR0 |
P1.2 | Timer A0 | CCR1 |
P1.5 | Timer A0 | CCR0 |
P1.6 | Timer A0 | CCR1 |
P2.0 | Timer A1 | CCR0 |
P2.1 | Timer A1 | CCR1 |
P2.2 | Timer A1 | CCR1 |
P2.3 | Timer A1 | CCR0 |
P2.4 | Timer A1 | CCR2 |
P2.5 | Timer A1 | CCR2 |
Verwenden des CCR zum Manipulieren der Pins
- Um die Verbindung des Pins mit dem Timer herzustellen müssen die Bits der Register
PxSEL
undPxSEL2
entsprechend gesetzt werden (siehe Pinbelegung). - Um P2.0 mit den Timer zu verbinden müssen
P2SEL = 1
undP2SEL2 = 0
gesetzt werden. - Die Datenrichten des Pins muss außerdem auf Ausgang gesetzt werden.
-
In welcher Art und Weise die Pins bei einen CCR-Ereignis verändert werden, wird durch die
OUTMOD
-Bits desTAxCCTLx
-Registers bestimmt.
- Zum Erzeugen eines symmetrischen Rechtecksignals sollte
OUTMOD = 4
verwendet werden.
Erzeugen eines 440 Hz-Signals an P2.0
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P2SEL |= BIT0;
P2SEL2 &= ~BIT0;
P2DIR |= BIT0;
TA1CCR0 = 37;
TA1CCTL0 = OUTMOD_4;
TA1CTL = TASSEL_1 + MC_1 + TACLR;
__enable_interrupt();
while (1) {
__low_power_mode_3();
}
}
Aufgabe
Messen Sie das Signal an P2.0 mit einem Oszilloskop. Wie hoch ist die Signalfrequenz?
Verändern Sie den Wert des CCR0-Registers auf 36. Warum ist die Signalfrequenz nun exakter?
Lösung
→ The generated frequency is to slow.
→ The timer counts from 0 to 36. This results into 37 counter steps. The frequency is generated with an CCR value of 36.
Aufgabe
Verwenden Sie die SMCLK des um ein 1 kHz Rechtecksignal an P2.0 zu erzeugen. Messen Sie die Signalfrequenz.
Der DCO des MSP430 erzeugt den Takt für die MCLK und SMCLK. Dieser muss kalibriert werden, um exaktere Ausgangssignale zu liefern. Texas Instruments speichert Kalibrierwerte für 1, 8, 12 und 16 MHz im Flash-Speicher des MSP430.
Um diese Werte zu laden, müssen die folgeden beiden Befehle zu Beginn des Programms eingefügt werden.
Der DCO des MSP430 ist nicht so exakt, wie der Quarzoszillator der ACLK. Die Frequenz des DCO ist außerdem stark abhängig von Umgebungstemperatur und Betriebsspannung.
Lösung
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P2SEL |= BIT0;
P2SEL2 &= ~BIT0;
P2DIR |= BIT0;
TA1CCR0 = 499;
TA1CCTL0 = OUTMOD_4;
TA1CTL = TASSEL_2 + MC_1 + TACLR;
__enable_interrupt();
while (1) {
__low_power_mode_0();
}
Erzeugen pulsdauer-modulierter Signale
- Verwenden von PWM-Signalen:
- Einfachste Form eines Digital-Analog-Wandlers
- Ausgabe von analogen Audiosignalen
- Dimmen von LEDs
- Geschwindigkeitssteuerung von Gleichstrommotoren
- Steuern von Modellbau-Servomotoren
Dimmen von LEDs
Dimmen von LEDs an P2.1 und P2.5
volatile uint8_t pwm = 16;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1DIR &= ~BIT3;
P1OUT |= BIT3;
P1REN |= BIT3;
P1IES |= BIT3;
P1IFG &= ~BIT3;
P1IE |= BIT3;
P2SEL |= BIT1 + BIT5;
P2SEL2 &= ~(BIT1 + BIT5);
P2DIR |= BIT1 + BIT5;
TA1CCR0 = 255;
TA1CCR1 = pwm;
TA1CCTL1 = OUTMOD_7;
TA1CCR2 = 255 - pwm;
TA1CCTL2 = OUTMOD_7;
TA1CTL = TASSEL_1 + MC_1 + TACLR;
__enable_interrupt();
while (1) {
__low_power_mode_3();
pwm += 32;
TA1CCR1 = pwm;
TA1CCR2 = 255 - pwm;
}
}
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR() {
if (P1IFG & BIT3) {
P1IFG &= ~BIT3;
__low_power_mode_off_on_exit();
}
}
Steuern von Modellbau-Servomotoren
Aufgabe
Verbinden Sie einen Modellbau-Servomotor mit dem Launchpad. Verwenden Sie die folgenden Pin-Belegung. Stellen Sie sicher, dass Sie die 5 V-Betriebsspannung verwenden.
Im folgenden Bild ist der Signalverlauf zu sehen, der verwendet werden muss, um einen Servomotor zu steuern. Programmieren Sie den MSP430, sodass die Position des Servomotors mit Hilfe eines Tasters verändert werden kann.