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 }
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
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
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 }
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
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 }
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
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
P.S. "DCO" sind Buchstaben, das letzte ist keine Null, sondern der Buchstabe zwischen N und P ;)
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 }
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.