B.3  Aufgaben aus Kapitel 3

1.
Erkläre den Unterschied zwischen Taktgenerator und Taktquelle.
Ein Taktgenerator ist ein physikalischer Baustein, der ein Taktsignal erzeugt. Also zum Beispiel ein Quarz oder sogar ein externer Quarzoszillator, aber auch der eingebaute DCO. Eine Taktquelle ist ein prozessorinterner Systemtakt, der aus einem Taktgenerator abgeleitet wird. Beim MSP sind dies MCLK, SMCLK, ACLK.

 
 

2.
Was sind die Auswahlkriterien, den internen DCO, einen Quarz, einen Uhrenquarz oder einen externen Taktgenerator zu selektieren?
Wie zu erwarten, ist eine solche Frage kaum allgemeingültig zu erklären. Zu sehr hängt die Entscheidung doch von den Vorstellungen des Entwicklers ab. Wenn es nicht auf die Einhaltung einer bestimmten Frequenz ankommt und zudem der Platz auf der Platine beschränkt ist, so ist der DCO sicherlich erste Wahl. Den Uhrenquarz an LFXT1 verwendet man zum seltenen Aufwachen aus einem Low-Power-Mode und natürlich für eine einfache Echtzeituhr. Ein externer Taktgenerator ist immer dann von Vorteil, wenn mehrere Bauteile synchronisiert mit dem gleichen Takt betrieben werden sollen (z.B. um Buskollisionen zu vermeiden). Den Quarz nimmt man immer dann, wenn es auf die Genauigkeit der Frequenz, also beispielsweise für asynchrone Schnittstellen ankommt.

 
 

3.
Wozu besitzt der MSP430 drei interne Taktquellen?
Nur so ist man flexibel genug, die verschiedenen Taktquellen optimal zu nutzen und die einzelnen Funktionskomponenten energieoptimal einzusetzen. Die MCLK betreibt den Prozessor und kann immer abgeschaltet werden, wenn gerade nichts zu rechnen ist. Mit der SMCLK können autonome Peripheriekomponenten unabhängig von der CPU betrieben werden. Die ACLK ist an den Uhrenquarz angeschlossen und ”weckt” mit Hilfe des Timers den Prozessor in regelmäßigen Abständen aus den Energiesparmodi wieder auf.

 
 

4.
An LFXT1 ist ein 32.768kHz-Uhrenquarz angeschlossen. Schreibe ein Programm, das den MSP so initialisiert, dass die DCO-Frequenz etwa mit der hundertfachen (3.2768MHz) Geschwindigkeit einstellt. Wie könnte man die DCO-Korrektur mit dem Uhrenquarz abgleichen?
#include <msp430x14x.h> 
int index;                    // Hilfsvariable 
 
int main( void ) { 
  WDTCTL  = WDTPW | WDTHOLD;  // Watchdog-Timer ausschalten 
 
  P1DIR   = BIT0;             // P1.0  Ausgang 
  P1SEL   = 0x00;             // normale I/O-Funktion 
 
  BCSCTL1|= RSEL1+RSEL2;      // RSEL und DCO aus Grafik 
  DCOCTL |= DCO1 + DCO2;      // ungefähr ablesen 
 
  BCSCTL1 &=~  XTS;            // LFXT1 im LF-Modus auswählen 
  _BIC_SR(OSCOFF);            // aktiviere XT1 
 
  while( 1 )                  // Endlosschleife 
  { 
   BCSCTL2 &=~ (SELM1+SELM0); // Wähle DCO 
   for (index=0; index<10000; index++); 
   P1OUT = BIT0;              // Ausgang=1 
 
   BCSCTL2 |= (SELM1+SELM0);  // wähle LFXT1 
   for (index=0; index<100; index++); 
   P1OUT = 0;                 // Ausgang=0 
 
   // Zum Abgleich Zeiten am Oszilloskop messen. 
   // Puls und Pause müssen gleich lang sein. 
  } 
} 
5.
Wozu braucht man eigentlich so viele verschiedene Low-Power-Modes?
Die verschiedenen Low-Power-Modes unterscheiden sich darin, welche Restfunktionalität des Prozessors noch weiterläuft und welche Module angehalten werden. Natürlich sinkt der Stromverbrauch im umgekehrten Verhältnis zu der Anzahl der laufenden Module. Mit der differenzierten Moduswahl kann man so genau die Funktionalität bei minimal möglichem Energieverbrauch einstellen, die man benötigt.

 
 

6.
Konstruiere ein 3-Tasten-Codeschloss für ein Garagentor. Verwende den Low-Power-Mode 3 um Energie zu sparen.
#include <msp430x16x.h> 
 int sym1,sym2,sym3;     // Variablen für Eingabe 
 
 const int CODE1 = BIT3; // definiere Tastenfolge, die das 
 const int CODE2 = BIT1; // Schloss öffnet, für mehr 
 const int CODE3 = BIT2; // Sicherheit einfach die 
                         // Tastenfolge verlängern 
#pragma vector=PORT1_VECTOR 
__interrupt void Port_1(void) 
  { 
 P1IFG = 0x00;           // Interrupt-Flag löschen 
 sym1 = sym2;            // Umspeichern der Eingabefolge 
 sym2 = sym3; 
 sym3 = P1IN;            // Einlesen neuer Wert 
 
 if {{sym1 == CODE1}&&{sym2 == CODE2}&&{sym3 == CODE3}} 
   { // Tor öffnen !!! } 
} 
 
int main ( void ) { 
 WDTCTL = WDTPW | WDTHOLD ; // Watchdog-Timer ausschalten 
 P1DIR = 0x00;           // P1 konfigurieren 
 P1SEL = 0x00;           // normale I/O-Funktion 
 P1IES = 0x00;           // Interrupt bei steigender Flanke 
 P1IFG = 0x00;           // Interrupt-Flag löschen 
 P1IE  = 0xFF;           // alle Pins Interrupt-Eingänge 
 _enable_interrupts ();  // Interrupts global aktivieren 
 
 while ( 1 )// Endlosschleife 
  { 
   LPM3;// Setze LPM3 
  } 
}