Forum: Mikrocontroller und Digitale Elektronik MSP430 F149 PWM Signal als Interrupt


von Chris (Gast)


Lesenswert?

Hallo ich hab da mal eine Frage vielleicht kann mir ja jemand helfen

ich komme aus dem modellbau und will mit hilfe eines MSP´s einige 
Sonderfunktionen meines Modells auslagern.

Mein Problem:
Als Eingang soll ein PWM signal eines Empängers dienen, die Pulsweite 
liegt zwischen 1 und 2 ms. Durch die verschiedenen Werte des 
einganssignals soll der MSP verschiede Inderrupt programme ausführen.

Für die genauigkeit der daten:

Empfänger: Graupner smc19
Funktionen:
-Beleuchtung
-Kanonenschacht ausfahren 2 Stufig 1.Stufe Schacht, 2.Stufe Kanonen
-Raketnschacht ausfahren

zum Steuern der Rudermaschinen ist ein FT639 im einsatz.

Wäre nett wenn jemand darüber etwas weis und mir helfen kann.

von Christian R. (supachris)


Lesenswert?

Da kannst du mit der Capture-Funktion des Timers die Impulszeit messen 
und dann entsprechend Aktionen auslösen. Wie man die Capture-Funktion 
benutzt, steht im User Guide des Chips und eventuell gibts bei TI sogar 
nen C-Demo schon dazu.

von Chris (Gast)


Lesenswert?

Danke für die Antwort

Ich bin neu auf diesem gebiet, kannst du mir vieleich nochweiterhelfen. 
ich finde nämlich keine Beispielprogramme auf der Texas insstrumens 
Seite.
Und wie ich die Capture Funktion richtig scheibe ist mir auch noch ein 
rätsel?.

von Christian R. (supachris)


Lesenswert?

Die Code-Examples sind hier. 
http://focus.ti.com/mcu/docs/mcuprodcodeexamples.tsp?sectionId=96&tabId=1468

Der User Guide ist hier: http://www.ti.com/litv/pdf/slau049f

Direkten Code wird bissl aufwendig jetzt, außerdem lernst du ja dann nix 
dabei. Schau dir die Beispiele an, und guck im user Guide den Timer A 
an.

Musst halt TACTL Register passend einstellen, Up-Mode, Tacktquelle usw. 
und im TACCTL0 einstellen, was du machen willst, also CAP für Capture, 
Flanke auswählen, Capture-Eingang auswählen, Interrupt aktivieren, Sync 
oder nicht usw.

In der ISR müsstest du dann die flanke umschalten, und beim nächsten mal 
die Zeitdifferenz Messen.

von Chris (Gast)


Lesenswert?

Super Danke.

Werd mir das jezt mal genauer anschauen.

falls ich nicht zurecht komme darf ich dann auf dich zurückkommen??

auf jeden fall DANKE DANKE DANKE, jetzt wirds vielleicht doch noch was 
mit meinem Projekt.

von Christian R. (supachris)


Lesenswert?

Ja kannste gerne fragen, kein Thema, arbeite beruflich nahezu Vollzeit 
mit dem MSP430

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Ich werd aus dem zeug einfach nicht so richtig schlau,
mein Englisch ist jetzt auch nicht mehr das beste und bin mir einfach 
noch sehr unsicher.
wenn jemand mal einen blick auf mein Programm werfen könnte währe ich 
ihm sehr dankbar vielleicht schreib ich da einen völligen scheiß 
zusammen aber ich verstehe hald das datenblatt so.

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist noch ein schaltplan von mir leider nur als schlechtes bild wenn 
einer den Eagle schaltplan braucht kann er gerne haben.

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo hier mal ein schöneres Bild vom Schaltplan.

es scheit so als hab ich alle sprachlos gemacht mit meinem Code.
ihr müsst mir einige fehler verzeien es ist ja mein erstes programm.
Für anregungen und verbesserungen bitte melden ich nehme jegliches 
komentar gerne an!!!.

von Christian R. (supachris)


Lesenswert?

Naja, man kann aus dem schlimmen Schaltplan leider nicht erkenne, welche 
Signale du überhaupt capturen willst....

Schreib mal genau, welches Signal, oder welche da PWM sind....

von chris (Gast)


Lesenswert?

Also die eingänge die ich capturen will sind eingang1 und eingang2 somit 
pin 1.1 und 1.2. Die Signale die ich empfange sind 20ms lang und haben 
eine min Pulslänge von 0,8ms und max Pulslänge von 2,2ms. Es reicht mir 
auch wenn ich einen eingang verwenden kann muss halt dann die abstufung 
der Pulslängen anders auslegen.
Kannst du mir da weiter helfen???.

PS: was kann ich am schaltplan besser machen??

von Christian R. (supachris)


Lesenswert?

Bist du sicher, dass so ein Keramikresonator da überhaupt anschwingt? In 
welchem Datenblatt hast du gesehen, dass man so einen anschließen kann?

Um die Eingämge TA0 und TA1 zu capturen musst du die Register TACCTL0 
und TACCTL1 entsprechend dem User-Guide einstellen. Dann setzt du in 
jedem dieser Register das CCIE Bit, um einen Interrupt ausgelöst zu 
bekommen. In der Timer A0 ISR kannst du dann was mit dem Wert des TACCR0 
machen, in der TimerA1 ISR mit dem TACCR1. In der ISR dann auch die 
Flanken umschalten, denn du willst ja einmal auf High und einmal auf Low 
triggern.

Das sollte ja als Anhaltspunkt reichen, der Rest steht im User Guide 
sehr gut beschrieben.

Der Schaltplan ist halt sehr zusammen gedrängt, Leitungen unter dem Chip 
usw.

von chris (Gast)


Lesenswert?

Der Resonator ist doch ein standard Resonator, und im Datanblatt steht 
dass man einen Standard Resonator bis 8Mhz anschliesen kann. Ich weis 
nicht ob der anschwingt wie kann ich denn das Feststellen?? Es mangelt 
mir an einem Oszi um es zu messen.

"Um die Eingämge TA0 und TA1 zu capturen musst du die Register TACCTL0
und TACCTL1 entsprechend dem User-Guide einstellen"

genau da liegt mein Problem ich weis trotz User-Guide nicht was ich wie 
einstellen muss bin anscheinend zu dämlich dazu. Das nächste ist was 
steht dann in den Registern?? die Zeit von der Steigenden bis zur 
Fallenden Flanke in 8Bit binär oder was kann ich damit anfangen?.
das ich den Capture auf high und low einstellen muss um die Pulslänge zu 
bekommen leuchtet mir ja gerade noch ein.

danke für deine Mühe und den tipp mit dem Schaltplan werd ich bei 
gelegenheit ändern.

Falls du vielleicht nochmal so nett wärst mir zu schreiben wie ich 
register entsprechend einstelle und mir noch sagst wie ich mit einem 
8Mhz quarz die Teiler für die Usat schnittstelle einstelle um eine Baud 
rate von 2400 zu erreichen, dann küss ich den Boden unter dem du gehst 
ich weis wirklich nicht weiter, hab mich glaube fürs erste projekt 
deutlich übernommen.

Sorry das ich so rumnerve.

von Christian R. (supachris)


Lesenswert?

Also baudrate kannst du hier ganz einfach ausrechnen lassen: 
http://mspgcc.sourceforge.net/baudrate.html

Die Register könntest du wie folgt einstellen:

Das generelle Timer A Register:

TACTL = TACLR + MC_2 + ID_3 + TASSEL_2;

Damit läuft der Timer A mit 1 MHz im Continous Mode, also immer durch.

Dann das Register für den Capture-Compare Block 0:

TACCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE;

Damit legst du fest, dass es im Capture-Mode läuft (CAP), den Eingang 
TA0 verwendet (CCIS_0), mit dem takt synchronisiert ist (SCS) und auf 
die steigende Flanke reagiert (CM_1). Außerdem wird ein Interrupt 
ausgelöst (CCIE)

Das gleiche mit dem Register für den Block 1:

TACCTL1 = CM_POS + SCS + CCIS_1 + CAP + CCIE;

Da halt jetzt CCIS_1 für TA1 Eingang.

So, nun werden bei jeder steigenden Flanke an den TAx Pins zuerst der 
aktuelle Stand des TAR Zähler-Registers in die TACCR0 bzw 1 kopiert, und 
dann ein Interrupt ausgelöst.

Die Vektoren sind TIMERA0_VECTOR für den CCR0 Block, sowie 
TIMERA1_VECTOR für den CCR1 Block. Im TimerA1 Vektor sollte man noch 
nach dem TAIV schauen, ob wirklich der CCR1 jetzt kam, der Vektor ist 
mehrfach belegt. Das steht aber in den C-Demos.

In der entsprechenden ISR musst du nun den Wert des TACCRx Registers in 
eine Variable speichern und die Flanke umschalten, also TACCTLx 
entsprechend mit CM_2 beschreiben statt CM_1.

Wird die ISR das nächste mal angesprungen kannst du aus dem aktuellen 
Wert in TACCRx und dem gespeicherten deine Impulslänge berechnen. 
Sinnvoll ist es vielleicht auch, eine Variable zu machen, in der du eine 
Information über die eingestellte Flanke speicherst, willst ja nur die 
High-Phase messen, oder?

Dann hast du eine 16-bit Variable, die dir die Impulszeit auf 1µs genau 
angibt, geht also bis 65,536µs Impulslänge.

Noch Fragen? Wie du eine ISR schreibst, findest du in den C-Demos.

von chris (Gast)


Lesenswert?

Danke du bist genial ich werds jetzt nochmal versuchen und hoffen das 
ich es schaffe.

Danke Danke Danke falls ich noch Fragen habe meld ich mich nochmal.

von Marco B. (Gast)


Lesenswert?

Hallo zusammen,

ich habe auf Basis dieses Beitrag einmal versucht ein PWM-Signal 
auszuwerten.
Grundsätzlich funktioniert es schon. Die Interrupts kommen usw. Nur 
anscheinend ist meine Art der Signalauswertung irgendwie daneben. ICh 
möchte die High-Zeit und die Periodendauer ermitteln. Im moment gebe ich 
danneinfach die High-Zeit auf einem Display aus, aber irgendetwas kann 
da nicht stimmen, da ich Werte um 20 rum rausbekomme. Ohne weitere 
Bearbeitung müssten die Werte doch um einiges höher sein denke ich doch. 
Ich habe auch mal versuchsweise die Periodendauer ausgegeben, aber da 
kommt noch weniger bei raus.

Ich habe hier einmal die Initialisierung vom Cature und die ISR. Wäre 
klasse, wenn da mal jemand drüber schauen könnte. Ich denke es liegt an 
dem Kram in der ISR, das da ein logischer Fehler drin ist.
1
void InitCapture(void)
2
{
3
  TACTL= TACLR + MC_2 + ID_3 + TASSEL_2;
4
  
5
  TACCTL0= CM_1 + SCS + CCIS_0 + CAP + CCIE; 
6
}/* void InitCapture(void) */ 
7
8
9
#pragma vector=TIMERA0_VECTOR
10
__interrupt void Timer_A0 (void)
11
{
12
    if(flanke == 0 && ready == 0) // Wenn erste steigende Flanke kommt
13
    {
14
        rise= TACCR0;             // Zählerstand speichern
15
        periode= rise - start;    // Periodenlänge berechnen
16
        start= rise;              // Wert für spätere Weiterverarbeitung 
17
                                  // zwischenspeichern
18
        flanke++;
19
        TACCTL0 |= CM_2;          // auf fallende Flanke umschalten
20
    }
21
    else if(flanke == 1 && ready == 0)
22
    {
23
        fall= TACCR0;             // Zählerstand speichern
24
        high_time= fall - rise;   // High-Zeit berechnen
25
        flanke= 0;
26
        ready= 1;                 // Wenn ready 1 ist, dürfen die Werte
27
                                  // ausgegeben werden        
28
        TACCTL0 |= CM_1;          // Auf steigende Flanke umschalten
29
        _BIC_SR_IRQ(LPM0_bits);   // Exit LPM0
30
    }
31
}/* __interrupt void Timer_A0 (void) */

von Kilian (Gast)


Lesenswert?

Hallo Marco

Ich bin im Moment auch gerade an einem solchen Projekt. Doch bei mir 
scheint es auch nicht zu funktionieren.
Was an deinem Cod jedoch sichelich falsch ist: Du beschreibst das 
TACCTL0-Register immer nur mit einer Oder-Verknüpfung, d.h. wenn du CM_1 
hast und |=CM_2 schreibst hast du danach CM_3! Dann reagiert dein 
Interrupt auf jede Flanke die kommt.

denn 01 |= 10 => 11!!!

Da must du erst das CM_1 bzw. CM_2 löschen.

von Kilian (Gast)


Lesenswert?

Hallo nochmals

Ich habs nun noch mal aufgebaut. Es funktioniert wunderbar. Du musst 
jedoch bei der Initialisierung CM_3 anwählen (beide Flanken). Im 
Interrupt musst du die Flanken dann nicht mehr ändern, da du ja mit dem 
If-then-else sowiso die flanke abfrägst. So wird deine Interruptrutiene 
auch kürzer.

von Marco B. (Gast)


Lesenswert?

Hallo,

ich habe mal wieder etwas Zeit gefunden mit mit den Sachen zu 
beschäftigen. Ich habe da nun einmal so geändert, dass ich zunächst CM_1 
bzw. CM_2 lösche und dann eben das entsprechende andere Bit setze. Das 
scheint auch schon mal besser zu funktionieren als da andere.

Nun noch eine Verständnisfrage. Mein PWM-Signal hat eine Periodendauer 
von 64µs. Timer A läuft mit 1 MHz im Continous Mode. Wenn ich das 
Programm nun laufen lasse und z.B. 51 erhalte (fall-rise) ist das dann 
schon die HIGHT-Time in µs? Da der Timer mit 1MHz läuft, sollte das doch 
der Fall sein oder bin ich da auf dem Holzweg?


Vielen Dank erst einmal für die Hilfe.

Gruß
Marco

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.