mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 4kHz Takt 5 Takte ausgeben aber wie???


Autor: Chris (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
dieses Programm erzeugt einen 4kHz Takt an Pin5.1.
ich moechte im "main" Programm eine IF Abfrage einbauen (z.B. if
Pin5.4 = high dann gebe 5 Takte a 4kHz an Pin 5.1 aus und wenn Pin5.4 =
low dann gebe 10 Takte a 40kHz aus (einmal CCR0+=98 und CCR0+=10)).
die Letzte Anweisung #progma..... gibt mir einen kontinuierlichen Takt,
der nicht mehr aufhoert.
Wie kann ich das realisieren?????

#include  <msp430x16x.h>

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  TACTL = TASSEL1 + TACLR;              // SMCLK, clear TAR
  CCTL0 = CCIE;                         // CCR0 interrupt enabled
  CCR0 = 20;
  P5DIR |= BIT1;                        // P5.1 output
  TACTL |= MC1;                         // Start Timer_A continuous
mode
  _EINT();                              // Enable interrupts
}


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  P5OUT ^= BIT1;                 // Toggle P5.1
  CCR0 += 98;                    // Add Offset to CCR0 to create 4kHz
}

Autor: Florian -der Flo- Scharf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi ..

wie wärs mit einer globalen Variable i als Zähler? Solange i-- > 0,
soll er CCR0 += 10 setzen, ansonsten CCR0 += 98.
Als Trigger setzt Du bei steigender Flanke von P5IN & BIT4 den Befehl i
= 20 (P5.1 wird getoggelt, daher ist eine doppelt so grosse Zahl von
Impulsen notwendig). Dafür brauchst Du noch eine Variable, in der der
Zustand von P5.4 einen Durchlauf vorher gespeichert ist. So kannst Du
mit einem einfachen Vergleich die steigende Signalflanke ermitteln.
Beachte beim Anschliessen von Tastern das mechanische Prellen.

Schöne Grüße,

der Flo

Autor: Florian -der Flo- Scharf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, ich stell grad fest, dass ich die Frage nicht ganz richtig
durchgelesen hab. Bei steigender Flanke setzt Du dann den Zähler auf
10, bei fallender Flanke auf 20, und dann brauchst Du noch ein globales
Flag, das Du auf die Geschwindigkeit einstellst. Also z.B. c = 98 bei
steigend und c = 10 bei fallend. Und in der Timer Routine setzt Du dann
nach der Abfrage von i: CCR0 += c.

der Flo

Autor: Chris (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, habe mal die if Anweisung eingebaut und ne Variable Nahmens clock
eingebunden.
die 4kHz Ausgangstakt liefert der chip, wenn P.5.3 = high
die 40kHz liefert er aber nicht, wenn P5.4 = high, stattdessen kommen
um die 16HZ raus, viel zu langsam.....?????
habe auch versucht CCR0 auf 10 zu setzen, anstatt 20, hilft nix....
bis clock=20 klappt alles => 20kHz aber wenn CCR0 += kleiner als 20
wird gibts die 16 Hz am Ausgang P.5.1.

Keine Ahnung warum.


#include  <msp430x16x.h>

unsigned int clock = 0;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  TACTL = TASSEL1 + TACLR;              // SMCLK, clear TAR
  CCTL0 = CCIE;                         // CCR0 interrupt enabled
  CCR0 = 20;
  P5DIR |= BIT1;                        // P5.1 output
  TACTL |= MC1;                         // Start Timer_A in continuous
mode
  _EINT();                              // Enable interrupts

if ((P5IN & BIT3) !=0)    // Abfrage Pin 5.3
    clock = 98;     // 780kHz/2/98= 4kHz

if ((P5IN & BIT4) !=0)    // Abfrage Pin 5.4
    clock = 10;  // 780kHz/2/10= 40kHz
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  P5OUT ^= BIT1;                // Toggle P5.1
  CCR0 += clock;                // Add Offset to CCR0 to create clock
}

Autor: Florian -der Flo- Scharf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo der Effekt ist einfach zu erklären:

Der TIMERA0_VECTOR wird dann aufgerufen, wenn der Timer-Zähler auf dem
Wert von CCR0 ist (bspw TAC=10). Das geschieht allerdings nicht
sofort, sondern verzögert sich immer um ein paar Takte, weil der Proz
erstmal nachgucken muss, was er jetzt tun soll. PC und Register sichern,
etc, dann Interrupt Routine ausführen, dann BIT1 toggeln. Und DANN wird
CCR0 um 10 (20, 98, ...) hochgezählt (bspw CCR0 = 20). In der
Zwischenzeit ist der Timer aber schon längst am neuen Zielwert
vorbeigerauscht (bspw TAC=23). Was passiert dann? Er zählt bis 2^16,
springt zur Null, und zählt muter weiter bis zum neuen CCR0 (20), und
dann erst wird der neue Interrupt ausgelöst. Das dauert natürlich seine
Zeit, und so kommen die 16Hz zustande. Also Lösung wäre: entweder den
Teiler oder die Chip-Clock verändern. Teiler ist bei Dir derzeit 2? Seh
ich das richtig? Setz ihn mal auf 1. Oder häng einen 8MHz Quarz dran,
damit kriegst Du die 40kHz locker hin ;)

Schöne Grüße,

der Flo

Autor: KoF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in den samples von ti steht es so

#include  <msp430x14x.h>

void main(void)
{
  WDTCTL = WDT_MDLY_32;                     // Set Watchdog Timer
interval to ~30ms
  IE1 |= WDTIE;                             // Enable WDT interrupt
  P1DIR |= 0x01;                            // Set P1.0 to output
direction

  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
  P1OUT ^= 0x01;                            // Toggle P1.0 using
exclusive-OR
}

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Beispiel mit dem Watchdog hatte ich auch schon ausprobiert, aber
irgendwie konnte man da nur ein paar (ca. 5) verschiedene Frequenzen
generieren, außerdem wollte ich den Watchdog nicht misbrauchen, wenn
der Chip schon nen TimerA bzw.B hat.
@Flo: Danke für die Erklärungen, ein externes Quarz kommt leider nicht
in Frage, da das ganze ein Projekt von meinem Chef ist.... ich arbeite
als Werksstudent und mein Chef meinte wenn ich mal "Leerlauf" habe
könnte ich dieses kleine Projekt übernehmen und da mich
Chipprogrammierung sehr interessiert habe ich zugesagt und versucht
mich in die Materie einzuarbeiten, studiere Elektrotechnik und hatte
nur 1 Semester c-Programmierung und da auch nur scanf, printf usw.
keine Hardwareprogrammierung.
Nen Teiler hatte ich eigentlich ned eingebaut, zumindest ned
absichtlich, hab halt für CCR0 += verschiedene Werte eingegeben, bin
zum Oszi und hab gemessen was rauskommt.....bissal Mathematik und ich
hatte ne Formel....aber warum das ganze so geht keine Ahnung.
Leider komm ich erst wieder nächsten Freitag in die Firma und hab ein
Oszi und kann neue Programme ausprobieren, denn nen Simulator für den
MSP430 gibts ja ned, oder?
Das kostet nämlich n Haufen Zeit, EVM anstöpseln, neu programmieren,
zum Oszi gehen, ausmessen... wieder anstöpseln neu programmieren usw.
ich betreibe zur Zeit learning by doing, immer wieder bau ich was aus
diesem Forum ins Programm ein und schau dann am Oszi was
passiert......
ich muss im Endeffekt nen Baustein (Ti TPS61060) ansprechen, der Leds
dimmen kann... diesen spricht man über nen Takt an. 1us - 75us heller
180us - 300us dunkler. Daher die 4khZ und die 40kHz liegen etwas in der
Mitte des Bereiches.....
werde weiter dranbleiben und versuchen imer mehr zu verstehen, freue
mich für weitere Tipps. Danke allerseits

Autor: Florian -der Flo- Scharf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Chris,

sorry für die lange Pause, ich hoffe Du hast noch nicht aufgegeben ;)
Also so wie ich das sehe, musst Du den System Clock irgendwie
hochkriegen, mit den normalen 800kHz ist da nicht viel zu machen. Ich
hätte es über den 8Mhz Quarz gemacht, wenn das nicht geht, ist es auch
nicht so schlimm, der MSP430 hat ja einen internen Resonator (DCO). Der
ist zwar nicht sonderlich genau, hat schon nen paar %
temperaturabhängige Abweichung, aber das sollte ja nich sooo schlimm
sein. g

Ich hab den internen Resonator noch nicht benutzt, daher kann ich da
auch nur aufs Manual verweisen. Ich hab eins hier, den User Guide, da
steht auf Seite 4-3 ein schönes Blockdiagramm, wo steht, wie man den
DCO konfigurieren muss. Ich kann nur orakeln, aber ich denk mal, mit
dem Befehl

DCOCTL = DCO0 | DCO1 | DCO2;

setzt Du den Resonator auf höchste Frequenz (8MHz plusminus). Das mit
den Registern funktioniert beim MSP ja immer so, dass Du in einem
Register (DCOCTL beispielsweise) die einzelnen Bits setzt (DCO1 usw).
Auf Seite 4-15 steht dann, was das im Fall des DCO zu bedeuten hat.

Probier damit einfach mal herum, vielleicht klappts ja g


der Flo

Autor: Florian -der Flo- Scharf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S. "DCO" sind Buchstaben, das letzte ist keine Null, sondern der
Buchstabe zwischen N und P ;)

Autor: Chris (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi, danke fuer die stetige Hilfestellung.
Das angehaengte Programm ist das aktuelle, es funktioniert jedoch
nicht...????
ich versuche per if Abfrage an Pin5.2-5.4 verschiedene offsets zu
setzen im Interrupt.
am Oszi kommt aber nur eine konstante Ausgangsspannung an....??
Werde mit den DCO noch etwas herumspielen, aber ich hab leider keine
Ahnung.
Weitere Tipps waeren hilfreich.
Hiermit mal ein dickes Danke an Flo.




#include  <msp430x16x.h>
char clock;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  DCOCTL = DCO2;
  BCSCTL1 = RSEL2;
  TACTL = TASSEL1 + TACLR;              // SMCLK, clear TAR
  CCTL0 = CCIE + OUTMOD_4;                        // CCR0 interrupt
enabled
  CCR0 = 1000;
  P5DIR |= BIT1;                        // P5.1 output
  TACTL |= MC1;                         // Start Timer_A in continuous
mode
  _EINT();                              // Enable interrupts

if ((P5IN & BIT2) > 0.5)
        clock = 20;
if ((P5IN & BIT3) > 0.5)
        clock = 18;
if ((P5IN & BIT4) > 0.5)
        clock = 15;

}


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  P5OUT ^= BIT1;                        // Toggle P5.1
  CCR0 += clock;                       // Add Offset to CCR0
}

Autor: Yagan Z. Dongobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Chris,

die Bitabfrage wird nur einmal ausgeführt und dann das Programm
beendet.
Wenn das dauernd laufen soll, brauchst du eine Endlosschleife.
Etwa so:

do
    {
    if (P5IN & BIT2) clock = 20;
    if (P5IN & BIT3) clock = 18;
    if (P5IN & BIT4) clock = 15;
    }
while ( 1 );

Der Vergleich "> 0.5" ist bei Bits eher suboptimal ;-)

Ciao, Yagan

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.