Hi, ich mal wider diesmal mit nem anderen Problem, ich arbiete mit nem Handbuch wo nicht wirklich beispiele drin sind deswegen probiere ich ein bischen rum aber komme gerade nicht weiter. Mein Problem ist folgendes hab ne LED an P1.2 die soll mithilfe des Timers Blinken ich hab mir was Überlegt aber das funktioniert nicht und ich weis nicht wiso. Vielleicht könnt ihr ja mal nen blick rauf werfen und mir unter die Arme greifen danke schon mal hier der Code: #include <msp430x20x2.h> int main() { WDTCTL = WDTPW + WDTHOLD; TACTL = TASSEL1 + TACLR; // ???? TACCR1 = 30000; //obere grenze bis zu der hochgezählt werden soll TACTL |= MC1; // das hochgezählt werden soll TACCTL1 = OUTMOD_7;// stzen rücksetzen (mener meinung dann von 30000 auf 0 ???) TACCR0 = 0; // nuntere Grenze P1DIR &= 0x00; // P1DIR |= 0x04; //P1.2 Ausgang rest Eingang P1OUT &= 0x00; //Ausgänge auf 0 P1IN &= 0x00; //Eingänge auf 0 P1SEL &= 0x00; //I/O funktion festgelegt P1REN |=0x02; //Internen Widerstand zuschalten while(1){ if(TACCR0 == 0){P1OUT = ~0x04;} //LED an wenn 0 else{ if(TACCR1 == 30000){P1OUT = 0x04;}//LED aus wenn 30000 } } }
Marek S. schrieb: > int main() > { > > WDTCTL = WDTPW + WDTHOLD; > TACTL = TASSEL1 + TACLR; // ???? > TACCR1 = 30000; //obere grenze bis zu der hochgezählt werden soll > TACTL |= MC1; // das hochgezählt werden soll > TACCTL1 = OUTMOD_7;// stzen rücksetzen (mener meinung dann von 30000 > auf 0 ???) > TACCR0 = 0; // nuntere Grenze > > P1DIR &= 0x00; // > P1DIR |= 0x04; //P1.2 Ausgang rest Eingang > P1OUT &= 0x00; //Ausgänge auf 0 > P1IN &= 0x00; //Eingänge auf 0 > P1SEL &= 0x00; //I/O funktion festgelegt > P1REN |=0x02; //Internen Widerstand zuschalten > > while(1){ > if(TACCR0 == 0){P1OUT = ~0x04;} //LED an wenn 0 > else{ > if(TACCR1 == 30000){P1OUT = 0x04;}//LED aus wenn 30000 > } > } > > } Also so geht das leider überhaupt nicht! Du solltest mit den Beispielen von Ti üben, da ist zu jeder Anwendung etwas dabei. Als Buch kann ich dir die "MSP430 Micrcontroller Basics" von John H. Davies sehr empfehlen. Es gibt noch ein anderes Buch von Matthias Sturm, aber das ist meiner Meinung nach nicht sehr gut gelungen, vor allem nicht, wenn man in C programmiert. Das hier:
1 | while(1) |
2 | {
|
3 | if (TACCR0 == 0) |
4 | {
|
5 | P1OUT = ~0x04;} //LED an wenn 0 |
6 | else
|
7 | {
|
8 | if(TACCR1 == 30000) |
9 | {
|
10 | P1OUT = 0x04; |
11 | } //LED aus wenn 30000 |
12 | }
|
13 | }
|
TACCRx ist nicht zum vergleichen, der Wert wird sich nicht ändern, wenn du ihn einmal gesetzt hast. Du kannst das TAR-Register vergleichen, aber auch dafür ist der Timer nicht gedacht. Wenn du mit CCR0 und CCR1 arbeitest, dann läuft deine Anwendung eher auf PWM hinaus, das hast du ja wahrscheinlich noch garnicht vor. Deswegen bleib bei einem CCR-Register. Und mach dir z.b. nen Interrupt, in dem du die LED togglest.
1 | #include <msp430x20x2.h> |
2 | |
3 | void main (void) |
4 | {
|
5 | |
6 | WDTCTL = WDTPW + WDTHOLD; |
7 | |
8 | P1SEL = 0x00; // I/O funktion festgelegt |
9 | P1DIR |= 0x04; // P1.2 Ausgang, Rest Eingang |
10 | P1REN |= 0x02; // Internen Widerstand zuschalten |
11 | P1OUT = 0x00; // Ausgänge auf 0 |
12 | |
13 | TACTL = TASSEL_2 + ID_3 + MC_1; // SMCLOCK + Teiler 8 + Up-Mode |
14 | TACCTL0 |= CCIE; |
15 | TACCR0 = 65000; // obere grenze bis zu der hochgezählt werden soll |
16 | |
17 | _BIS_SR (GIE); // Globaler Interrupt aktiviert |
18 | |
19 | while (1) {} |
20 | }
|
21 | |
22 | #pragma vector=TIMERB0_VECTOR // ISR Timer
|
23 | __interrupt void seconds (void) |
24 | {
|
25 | P1OUT ^= 0x04; |
26 | }
|
Einen Wert an P1IN kannst du eh nicht schreiben, der soll ja von außen abgefragt werden. Gruß, Dennis
Danke dafür schon mal aber es läuft nicht, es kommt aber auch keine Fehler meldung, auser das bei #pragma ien ausrufe zeichen vor steht bei ausführen. Auserdem würde es bei dir nicht auch nur ein mal blinken und nicht kontinuierlich da du ja bis 65000 hochzählst und dann wenn das erreicht wird solte es blinken un ddann nie wider, meinem veständnis nach. werde mal rumprobieren hab mir auch gerade was überlegt mal schauen ob das klappen wird.
Was steht denn bei dem Ausrufezeichen für ne Meldung? Deine LED soll nur einmal kurz blinken? Jetzt in dem Quelltext wird sie ständig blinken, klar.
Das läuft so: CCR0 ist mit 65000 belegt, also fängt der Controller an, mit jedem Takt einen hochzuzählen. Wenn die 65000 erreicht sind, dann wird ein Interrupt ausgelöst und in der ISR die LED getoggled. Also wenn die an war, geht sie jetzt aus und umgekehrt. Nach der ISR ist der Zähler wieder auf 0 und beginnt von vorne.
Also der inter Zähler ist auf 0, nicht der CCR0, der bleibt die ganze Zeit auf 65000! Zähler CCR0 0 65000 -> loszählen ... 10540 65000 -> nicht gleich, weiterzählen... ... 49000 65000 -> nicht gleich, weiterzählen... ... 65000 65000 -> GLEICH!!! Interrupt -> LED togglen -> Zähler wieder auf 0 ... 0 65000 -> nicht gleich, weiterzählen... USW. Verstehst? : ) Gruß, Dennis
Also wenn ich auf das Ausrufe zeichen klike steht da so was in nem Fenster wo steht add Bookmark #pragma vector=TIMERA0_VECTOR // ISR Timer. Ne die soll schon öfters blinken aber das tut sie gerade nicht keine ahnung wiso nicht.
Ok, womit programmierst du ihn denn? Ich programmier mit IAR, weiß natürlich nicht, ob es überall gleich ist.
Das verstehe ich. Ich mach das mit Code Composer Essentials v2 da höhere versionen auf der ollen Win 2000 version auf den Rechner wo ich dran arbeite nicht laufen.
Ich hab mir mal was neues einfallen lassen ich. Laufen tut es trotzdem nicht. Vielleicht weil ich den Timer falsch initialisiere aber wie das richtig geht weis ich nicht weil das User Manuell mach mich nicht gerade schlauer. Hier kommt der code: #include <msp430x20x2.h> void main(void) { WDTCTL = WDTPW + WDTHOLD; TACTL = TASSEL1 + TACLR; // ???? TACTL |= MC_2;// das kontinuirlich gezählt werden soll von 0 bis // ffff dann von 0 bis fffff usw. TACTL |= 0x02; //interupt freigabe P1DIR &= 0x00; // P1DIR |= 0x04; //P1.2 Ausgang rest Eingang P1OUT &= 0x00; //Ausgänge auf 0 P1SEL &= 0x00; //I/O funktion festgelegt while(1){ if((TACTL & TAIFG)==1){P1OUT = ~0x04;}//TAIFG das überlauf forhanden? else{P1OUT = 0x04;} } }
Dann mach es mit dem OUTMOD_7, dann brauchste aber halt noch den CCR1 den legste dann auf den halben Wert von CCR0. Musst aber dann gucken mit dem Pin, wo die LED dran ist, der muss natürlich zum Timer gehören und dann musste noch die Sonderfunktion mit P1SEL |=0x__ einstellen. Guck mal ins Handbuch von dem Controller!
Achja, ISR kannste dann natürlich löschen, die Interruptfreigabe auch und das CCIE ebenfalls.
So funst das auch aber ich weis noch nicht wiso muß ich mir mal überlegen und schauen wiso das geht. Hab das gerade kopiert aber verstehe das nicht wirklich schaue ich mir mal und lese mal weiter das Manuel aber danke für deine Hilfe. #include <msp430x20x2.h> void main (void) { WDTCTL = WDTPW + WDTHOLD; TACTL = TASSEL_2 + TACLR + TAIE; //SMCLK + Timer löschen CCTL0 = OUTMOD_4; //up mode CCR0 = 0xFFFF; CCTL1 = OUTMOD_7; //reset/set CCR1 = 0x7FFF; P1DIR |= 0x04; //P1.2 ausgang P1SEL |= 0x04; //P1.2 = TA1 ausgang TACTL |= MC1; // up mode while(1); } mfg Marek
Marek S. schrieb: > So funst das auch aber ich weis noch nicht wiso muß ich mir mal > überlegen und schauen wiso das geht. Ich würde Dir den User-Guide trotzdem nochmal eindringlich empfehlen! Besonders das Thema "Basic Clocks" des MSP430. Es macht nämlich einen entscheidenden Unterschied, ob der Timer mal mit ACLK oder mit SMCLK gespeist wird...
@Stefan(Gast) Danke für den hinweis. Das hab ich die ganze Zeit vor mir aber, woher soll ich denn wissen wann ich welche zu benutzen habe wenn mir das keiner sagt und aus dem was da drinne steht wird man nicht so recht schlau. Ich beschäftige mich erst seit gestern damit zumindest mit dem mikrocontroller davor einen anderen gehabt der war komplexer. Da mußte ich aber auch nicht alleine dran sitzen und da wurde wir halb drauf gestoßen wo wir nachschauen sollen und jetzt sitzt du da hast keine Ahnung und hast ne idee und fängst einfach an weil du denkst das könnte gehen geht dann aber nicht und dann ist man verzweifelt warum das nicht geht. Woran kanst du denn erkennnen welcher Timer besser geeignet ist für die aufgabe die ich lösen sollte. Da ich das gerne verstehen würde wiso das so geht in dem von mir zuletzt eingefügten code. So in der schreib weise sehe ich das auch zum ertsen mal z.b. TACTL = TASSEL_2 + TACLR + TAIE; das steht da auch nirgends drinne das man das so machen soll. Ich danke dir schon jetzt für deine antwort. mfg marek
Marek S. schrieb: > Danke für den hinweis. Das hab ich die ganze Zeit vor mir aber, woher > soll ich denn wissen wann ich welche zu benutzen habe wenn mir das > keiner sagt Das kann dir keiner sagen, weil die Anforderungen für jeden anders sind! Deshalb mein Hinweis auf die "Basic Clocks" im User Guide. Man sollte verstehen, dass es verschiedene Clocks gibt, die man aus unterschiedlichen Quellen und mit unterschiedlichen Frequenzen takten kann! > und aus dem was da drinne steht wird man nicht so recht > schlau. Aller Anfang ist schwer... aber ich finde den User Guide sooo schlecht nicht?! > So in der > schreib weise sehe ich das auch zum ertsen mal z.b. > TACTL = TASSEL_2 + TACLR + TAIE; das steht da auch nirgends drinne das > man das so machen soll. Ich danke dir schon jetzt für deine antwort. Nun, das ist lediglich das Setzen der einzelnen Bits im Register TACTL. Das ist aber alles genau im User Guide beschrieben! Das einzig "ungewöhliche" ist die am Anfang vielleicht etwas verwirrende Schreibweise TASSEL_2 im Unterschied zu TASSEL1 Das eine sind die einzelnen Bits (TASSEL0 und TASSEL1), während TASSEL_x die Kombination beider Bits repräsentiert:
1 | TASSEL_0 = 0 |
2 | TASSEL_1 = 0 + TASSEL0 |
3 | TASSEL_2 = TASSEL1 + 0 |
4 | TASSEL_3 = TASSEL1 + TASSEL0 |
[... im Übrigen hättest Du somit schon erkennen können/müssen, dass ich oben Schmarrn geschrieben habe, denn Dein Timer wurde immer mit SMCLK betrieben, da TASSEL_2 = TASSEL1 ;-) ]
Marek S. schrieb: > Ich hab mir mal was neues einfallen lassen ich. Laufen tut es trotzdem > nicht. > > #include <msp430x20x2.h> > > void main(void) > { > WDTCTL = WDTPW + WDTHOLD; > TACTL = TASSEL1 + TACLR; // ???? > TACTL |= MC_2;// das kontinuirlich gezählt werden soll von 0 bis > // ffff dann von 0 bis fffff usw. > TACTL |= 0x02; //interupt freigabe > > > P1DIR &= 0x00; // > P1DIR |= 0x04; //P1.2 Ausgang rest Eingang > P1OUT &= 0x00; //Ausgänge auf 0 > P1SEL &= 0x00; //I/O funktion festgelegt > > while(1){ > if((TACTL & TAIFG)==1){P1OUT = ~0x04;}//TAIFG das überlauf forhanden? > else{P1OUT = 0x04;} > } > } Das funzt nicht, weil: 1.) TACTL |= 0x02; //interupt freigabe Du gibst einen Interrupt frei, der auch eintreten wird.... ABER Du hast keine Interrupt-Service-Routine definiert... Dein Controller hängt sich auf! 2.) if((TACTL & TAIFG)==1) TAIFG muss hier per Software zurückgesetzt werden.
Zieh dir mal die Code-Examples von Ti, da sind ne Menge Anwendungen drin beschrieben. Wir mussten uns während des Studiums das "ez430F2013"-Entwicklungs-Tool besorgen und ab da gabs leider keine große Hilfe mehr. Aber unsere Praktikumsaufgaben mussten wir auch abgeben. Und ne Klausur mit Programmieraufgabe kam dann natürlich auch noch. Vom Unterricht her keine wirkliche Hilfe zur Programmierung...:\ War ziemlich blöd. Uns wurde angeraten, mit den Ti-Examples zu arbeiten, das waren unsere einzigen Hilfen dazu, aber da ist echt ne Menge dabei. Wir sollten z.B. in einer Aufgabe ne PWM programmieren und haben einfach mal drauf losgelegt...vieeel zu umständlich - hier meine Aufgabenlösung, nur mal zur Veranschaulichung:
1 | /*********************************************************
|
2 | * Embedded Systems: MSP430F2013 Education Tool *
|
3 | *********************************************************
|
4 | * Dennis Eichmann (11049644) SS09 *
|
5 | * *
|
6 | * Aufgabe 3.2: PWM / Analogausgabe *
|
7 | * -------------------------------- *
|
8 | * *
|
9 | * Ausgabe eines stetig an- und absteigenden 8Bit *
|
10 | * PWM-Signals am Port P1.0 (LED) *
|
11 | * Die LED soll damit gedimmt, bzw sanft ein- und aus- *
|
12 | * geschaltet werden *
|
13 | * *
|
14 | *********************************************************
|
15 | * Konfiguration des MSP430F2013: *
|
16 | * ------------------------------ *
|
17 | * *
|
18 | * P1.0: LED gegen Masse *
|
19 | * P1.1: Taster gegen Masse *
|
20 | * P1.4: Schleifer Potentiometer (3V3 / Masse) *
|
21 | * -> Bei Benutzung S1 schliessen! *
|
22 | * P1.5: Schalter gegen Masse *
|
23 | * P1.6: Draht zur freien Benutzung *
|
24 | * -> Fuer Ausgang S1 oeffnen! *
|
25 | * *
|
26 | *********************************************************
|
27 | * Port-Verwendung: *
|
28 | * ---------------- *
|
29 | * *
|
30 | * P1IN: Auslesen gibt logischen Wert zurueck *
|
31 | * P1OUT: Schreiben legt logischen Wert an *
|
32 | * P1DIR: logische '0' setzt Pin auf Eingang (defaut) *
|
33 | * logische '1' setzt Pin auf Ausgang *
|
34 | * P1REN: '1' aktiviert Widerstand (dafault: inaktiv) *
|
35 | * Bitmuster P1OUT: Pull- Up('1') / Down('0') *
|
36 | * P1SEL: '0' fuer Standard I/O (default) *
|
37 | * '1' fuer alternative Funktionen *
|
38 | * P1IE: Interrupt bei Pegelwechsel; default '0' (aus) *
|
39 | * aktiv bei '1' *
|
40 | * P1IES: Interrupt positive ('0') / negative ('1') *
|
41 | * Flanke *
|
42 | * P1IFG: Interrupt-Flag-Bit - nach IRQ loeschen *
|
43 | * Auch fuer Software-Interrupt *
|
44 | * *
|
45 | * IRV: #pragma vector=PORT1_VECTOR *
|
46 | * *
|
47 | *********************************************************
|
48 | * Maskierungen von Bits: *
|
49 | * ---------------------- *
|
50 | * *
|
51 | * OR: Verknuepfung mit '0' laesst Wert unveraendert *
|
52 | * Verknuepfung mit '1' aendert Wert zu '1' *
|
53 | * P1OUT = P1OUT | BIT1 oder P1OUT |= BIT1 *
|
54 | * AND: Verknuepfung mit '1' laesst Wert unveraendert *
|
55 | * Verknuepfung mit '0' aendert Wert zu '0' *
|
56 | * P1OUT &= ~BIT1 -> '~' AND mit '0' *
|
57 | * XOR: (TOGGLE) Wechsel von '0' nach '1' oder umgekehrt *
|
58 | * P1OUT ^= BIT1 *
|
59 | * *
|
60 | *********************************************************
|
61 | * 16-Bit-Sigma-Delta-ADC Einstellungen: *
|
62 | * ------------------------------------- *
|
63 | * *
|
64 | * SD16 INput ConTroL Register: *
|
65 | * SD16INCTL = SD16INCH_ 1 (Eingang des Multiplexers) *
|
66 | * 2 ... (6 fuer Temperatursensor) *
|
67 | * *
|
68 | * SD16 ConTroL Register: *
|
69 | * SD16CTL = SD16SSEL_ + SD16REFON (fuer interne 1V2) *
|
70 | * *
|
71 | * SD16SSEL_0 MCLK Master Clock *
|
72 | * 1 SMCLK Subsystem Master Clock *
|
73 | * 2 ACLK Auxiliary Clock *
|
74 | * 3 TACLK Externes Clock-Signal *
|
75 | * (1,1MHz max) *
|
76 | * *
|
77 | * SD16 Capture ConTroL Register: *
|
78 | * SD16CCTL0 = SD16IE + SD16SNGL + SD16UNI *
|
79 | * Interrupt Enable (Interrupt wenn fertig) *
|
80 | * Single Conversion (einfache Wandlung) *
|
81 | * Unipolar (Spannung gegen GND) *
|
82 | * *
|
83 | * Wandlung starten mit: SD16CCTL0 |= SD16SC *
|
84 | * SD16 Start Conversion *
|
85 | * *
|
86 | * Ergebnis auslesen: Variable = SD16MEM0 *
|
87 | * SD16 Memory 0 *
|
88 | * *
|
89 | * IRV: #pragma vector=SD16_VECTOR *
|
90 | * *
|
91 | *********************************************************
|
92 | * 16-Bit-Timer Einstellungen: *
|
93 | * --------------------------- *
|
94 | * *
|
95 | * Timer A ConTroL-Register: *
|
96 | * TACTL = TASSEL_ + ID_ + MC_ *
|
97 | * *
|
98 | * Timer A Source SELect: *
|
99 | * TASSEL_0 TACLK Externes Clock-Signal *
|
100 | * 1 ACLK Auxiliary Clock (externer Quarz) *
|
101 | * 2 SMCLK Subsystem Master Clock *
|
102 | * 3 INCLK Invertierter TACLK *
|
103 | * *
|
104 | * Input Divider: *
|
105 | * ID_0 Teiler durch 1 (keine Teilung) *
|
106 | * 1 Teiler durch 2 *
|
107 | * 2 Teiler durch 4 *
|
108 | * 3 Teiler durch 8 *
|
109 | * *
|
110 | * Mode Control: *
|
111 | * MC_0 Stop Mode (Timer haelt ohne Aenderung an) *
|
112 | * 1 Up-Mode (Zaehlt bis zu angegebenen Wert CCR0) *
|
113 | * 2 Continous Mode (Zaehlt immer wieder bis Maximum) *
|
114 | * 3 Up-/Down-Mode (Zaehlt bis CCR0, dann zurueck) *
|
115 | * *
|
116 | * CCTL0 = CCIE: Interrupt durch Capture / Compare *
|
117 | * IRV: #pragma vector=TIMAERA0_VECTOR *
|
118 | * *
|
119 | *********************************************************
|
120 | * Low-Power-Modi: *
|
121 | * --------------- *
|
122 | * *
|
123 | * | LPM0 LPM1 LPM2 LPM3 LPM4 *
|
124 | * ------------------------------------- *
|
125 | * CPU | aus aus aus aus aus *
|
126 | * MCLK | aus aus aus aus aus *
|
127 | * SMCLK | an an aus aus aus *
|
128 | * ACLK | an an an an aus *
|
129 | * DCOdc | an aus an aus aus *
|
130 | * DCOosc | an an aus aus aus *
|
131 | * *
|
132 | * Im LPM4 nurnoch Interrupts durch Portpins *
|
133 | * *
|
134 | * Low-Power-Mode aktivieren: _BIS_SR(LPM0_bits + GIE) *
|
135 | * Low Power Mode verlassen: _BIC_SR_IRQ(LPM0_bits) *
|
136 | * *
|
137 | *********************************************************
|
138 | * Globale Interrupts zulassen: _BIS_SR(GIE) *
|
139 | *********************************************************
|
140 | * HEX - binaer: *
|
141 | * ------------- *
|
142 | * *
|
143 | * 0x00 0000 0000 0x06 0000 0110 0x0C 0000 1100 *
|
144 | * 0x01 0000 0001 0x07 0000 0111 0x0D 0000 1101 *
|
145 | * 0x02 0000 0010 0x08 0000 1000 0x0E 0000 1110 *
|
146 | * 0x03 0000 0011 0x09 0000 1001 0x0F 0000 1111 *
|
147 | * 0x04 0000 0100 0x0A 0000 1010 0x10 0001 0000 *
|
148 | * 0x05 0000 0101 0x0B 0000 1011 0x11 0001 0001 *
|
149 | * ... *
|
150 | * 0x22 0010 0010 0xDD 1101 1101 0xFF 1111 1111 *
|
151 | * *
|
152 | *********************************************************/
|
153 | |
154 | |
155 | #include "msp430x20x3.h" |
156 | |
157 | int periodendauer = 255; // 8Bit Periodendauer |
158 | int pulsweite = 1; // Pulsweite wird in Schritten von 1 geaendert |
159 | int anaus = 0; // Variable zum Wechsel zwischen an- und aus-Zeit |
160 | int hochrunter = 0; // '0' fuer heller, '1' fuer dunkler |
161 | |
162 | |
163 | void aenderung (void) // Routine fuer heller / dunkler und Pulsweitenaenderung |
164 | {
|
165 | switch (hochrunter) // Abfrage ob heller oder dunkler werden |
166 | {
|
167 | case 0: // hochrunter ist '0' -> heller werden |
168 | {
|
169 | pulsweite = pulsweite + 1; // Pulsweite um 1 erhoehen -> laengere an- / kuerzere aus-Zeit |
170 | |
171 | if (pulsweite >= 255) // Wenn pulsweite 255 erreicht hat (an maximal / aus minimal) |
172 | {
|
173 | hochrunter = 1; // hochrunter auf '1' -> ab jetzt dunkler werden |
174 | }
|
175 | |
176 | break; |
177 | }
|
178 | |
179 | case 1: // hochrunter ist '1' -> dunkler werden |
180 | {
|
181 | pulsweite = pulsweite - 1; // Pulsweite um 1 verringern -> laengere aus- / kuerzere an-Zeit |
182 | |
183 | if (pulsweite <= 1) // Wenn pulsweite 1 erreicht hat (an minimal / aus maximal) |
184 | {
|
185 | hochrunter = 0; // hochrunter auf '0' -> ab jetzt heller werden |
186 | }
|
187 | |
188 | break; |
189 | }
|
190 | |
191 | default: break; |
192 | }
|
193 | }
|
194 | |
195 | |
196 | int main( void ) |
197 | {
|
198 | WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten |
199 | |
200 | P1DIR |= 0x01; // Setzt P1.0 auf Ausgang (LED) |
201 | |
202 | CCTL0 = CCIE; // Interrupt durch CCR0 moeglich |
203 | CCR0 = periodendauer; // |
204 | TACTL = TASSEL_2 + ID_3 + MC_1; // SMCLK + Teiler 8 + UpMode |
205 | CCR0 = periodendauer; // Startet Capture-Compare und zaehlt bis 255 -> dann Interrupt |
206 | |
207 | _BIS_SR(LPM1_bits + GIE); // Low-Power-Mode 1 + Globaler Interrupt aktiviert |
208 | }
|
209 | |
210 | |
211 | #pragma vector=TIMERA0_VECTOR // Interrupt-Service-Routine beim Erreichen von CCR0
|
212 | __interrupt void timer (void) |
213 | {
|
214 | |
215 | switch(anaus) // Abfrage: LED an oder aus |
216 | {
|
217 | case 0: // LED an-Zeit |
218 | {
|
219 | CCR0 = pulsweite; // CCR0 bekommt Wert von pulsweite (steigt und faellt) |
220 | P1OUT |= 0x01; // LED anschalten |
221 | anaus = 1; // anaus jetzt '1' -> naechste Runde LED aus-Zeit |
222 | break; |
223 | }
|
224 | |
225 | case 1: // LED aus-Zeit |
226 | {
|
227 | CCR0 = periodendauer - pulsweite; // CCR0 bekommt Wert von periodendauer - pulsweite (steigt und faellt) |
228 | P1OUT &= ~0x01; // LED ausschalten |
229 | anaus = 0; // anaus jetzt '0' -> naechste Runde LED an-Zeit |
230 | |
231 | aenderung(); // Aufruf der Routine zuer Aenderung der Richtung und der Pulsweite |
232 | |
233 | break; |
234 | }
|
235 | |
236 | default: break; |
237 | }
|
238 | }
|
So, der Anfang ist natürlich nur Kommentar, damit ich mir nicht immer alles wieder raussuchen musste, daher habe ich das in jede Aufgabe mit reinkopiert. Aber guck dir mal den Teil für die PWM an, Horror! Mit dem "OUTMOD" kannste das ganze z.B. bequem in Hardware lösen und der Quelltext würde fast keine Zeile an Code mehr beeinhalten, außer die Konfiguration natürlich - nur die CCR-Register müsste man periodisch ändern. Aber die verbesserte Version finde ich grad nicht. Nur worauf ich hinaus will: Wie man es am einfachsten macht, hat man dann in den Code-Examples gefunden - muss man halt nurmal reingucken :-) Nichts desto trotz, vielleicht hilft dir ja auch mein Kommentar am Anfang des Codes, du fängst ja quasi auch gerade genau da an - dann musst du vorerst nicht immer für jede Info das Manual wälzen...aber das wirst du später noch oft genug :P Frohes Schaffen! Gruß, Dennis
Stefan schrieb: > TACTL |= 0x02; //interupt freigabe Sowas ist eh ne Katastrophe! Du weisst vielleicht jetzt, dass das das Bit für TAIE ist, aber niemand anderes kann das im nachhinein nachvollziehen - ganz ehrlich ich weiß grad auch nicht, ob es das Bit ist, das müsste ich jetzt selber nachgucken...OK, ich hab grad nachgeguckt, es stimmt! Aber benutz doch die Synonyme, wenn es sie schon gibt, sonst wird da keiner mehr Lust haben, drüber zu gucken.
Ales klar ich danke euch für die Unterstützung ich beschäftige mich weiter hin damit vielleicht lege ich mir doch mal ein Buch für zu um dann einiges besser zu verstehen investitionen müßen halt auch mal getan werden aber viel dank für eure anregungen. Bei weiteren problem werde ich mich bestimmt noch mal melden. Werde mir jetzt noch mal das blinken zu gemüte führen wiso das funktioniert wie es funktioniert mann soll das ja auch verstehen können. Die beispiele von TI hab ich mir gestern runter geladen und werde mir die auch mal heute anschauen. Ansonsten genist die Sonne heut ebei 30°C sollen es in Berlin werden und ich hänge vor dem Rechner naaj es gibt schlimmeres. Bis denn. mfg MArek
Sei froh, ich muss nach der Arbeit noch meine Terrasse im Garten weiter bauen, da hoffe ich, dass es keine 30° gibt :) Pass auf, ich lad dir noch mein anderen Praktikumsaufgaben hoch, vielleicht kannste da ja mal drauf gucken, immerhin haben wir ja genau da angefangen, wo du grad bist. Die sind zwar für den 2013, aber du benutzt ja nen 2012, die sind ja nahezu gleich, nur dass der 2013 nen 16Bit AD hat. Viel Spaß noch! Dennis
Sorry, ist ein bisschen groß, hab grad gesehen, dass in einer Aufgabe ein Video von der PWM drin war.
Kein Problem ich werde das auch schon noch ihrgend wie hin kriegen ander haben das ja auch vor mir geschaft dann solt eich das auch ihrgend wie schafen. Dir auch noch viel spaß beim Bauen. mfg
Ich hab mich mal wider beschäftigt mit dem Blinken. Ich hab hir mal was zusammen geschrieben was meiner meinung nach gehen solte aber ich glaube er geht nicht in die interrupt service routine ich weis aber nicht wiso. Wenn wer kurz zeit hat mal nen blick drauf zu werfen und mir vielleicht nen hinweis geben kann oder sagen kann wo da der fehler ist würde mir helfen. Danke schon mal. #include <msp430x20x2.h> int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten TACTL = TASSEL_2 + MC_1; // SMCLK + UpMode P1DIR |= 0x04; // Setzt P1.2 auf Ausgang CCTL0 = CCIE; // Interrupt durch CCR0 CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF _BIS_SR(GIE); // Globaler Interrupt enable } // Timer interrupt service routine __interrupt void Timer(void) { P1OUT ^= 0x04; // Toggle P1.2 }
Marek S. schrieb: > CCTL0 = CCIE; // Interrupt durch CCR0 > CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF Er geht da rein, weil du es so wolltest!
setz mal einen Breakpoint dann siehst du ob er da rein geht. und InterruptFlag muss wieder gelöscht werden...
Aso, sorry, hab das nicht überlesen. Dir fehlt der Interrupt Vektor! #pragma vector=timera0_vector
test schrieb: > und InterruptFlag muss wieder gelöscht werden... Das Flag löscht sich von selber in der ISR.
Das ist ne Tierisch schwere Geburt mit dem Ding. Ich hab das jetzt mal eingefügt den Vektor woher weis ich denn wie ich den Zu bennen habe nur mal so neben bei? #include <msp430x20x2.h> int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten TACTL = TASSEL_2 + MC_1; // SMCLK + UpMode P1DIR |= 0x04; // Setzt P1.2 auf Ausgang CCTL0 = CCIE; // Interrupt durch CCR0 CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF _BIS_SR(GIE); // Globaler Interrupt enable } // Timer interrupt service routine #pragma VECTOR=TIMERA0_VECTOR __interrupt void Timer(void) { P1OUT ^= 0x04; // Toggle P1.2 } Funktionieren tut es trotzdem nicht. Im Datenblat steht an dem PIN1.2 noch TA1 also dachte ich mal machste aus dem VECTOR=TIMERA0_VECTOR ein VECTOR=TIMERA1_VECTOR aber gehen tut es dann trotzdem nicht. Langsam gehen mir die ideen aus. mfg
Marek S. schrieb: > #pragma VECTOR=TIMERA0_VECTOR Das hat mit TA1 nichts zu tun - der TimerA0 bezieht sich auf CCR0! Deine main() braucht noch eine
1 | while (1) {} |
Dennis schrieb: > Deine main() braucht noch einewhile (1) {} Wäre ein "schöner" Programmierstil braucht's aber nicht, weil das der IAR automatisch macht. Marek S. schrieb: > Funktionieren tut es trotzdem nicht. Was bedeutet das jetzt mal ganz genau? Springt er in der IRQ oder nicht? Nur mal so als Hinweis... Deine LED würde in deiner jetzigen Konfiguration mit ca. 7Hz blinken...
Stefan schrieb: > Wäre ein "schöner" Programmierstil braucht's aber nicht, weil das der > IAR automatisch macht. Besser wär noch ihn schlafen zu schicken, aber das is wohl erstmal nicht wichtig. Macht IAR das? Wusste ich garnicht, dachte er meckert dann mit "program exit reached" oder so ähnlich rum...nun ja, er benutzt aber eh CCE. Stefan schrieb: > Konfiguration mit ca. 7Hz blinken... Das kommt hin, das sollte er noch sehen mit bloßem Auge. Ansonsten noch nen Divider rein.
Marek S. schrieb: > int main( void ) Meckert er eigentlich nicht, wegen fehlendem Rückgabewert?
1 | #include <msp430x20x2.h> |
2 | |
3 | void main (void ) |
4 | {
|
5 | WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten |
6 | P1SEL = 0x00; // Port 1 komplett GPIO |
7 | P1OUT = 0x00; // Port 1 Ausgaenge auf 'low' |
8 | P1DIR = 0x04; // P1.2 Ausgang, Rest Eingang |
9 | |
10 | CCTL0 |= CCIE; // CCR0 kann Interrupt ausloesen |
11 | CCR0 = 0xFFFF; // CCR0 laden |
12 | |
13 | TACTL = TASSEL_2 + MC_1; // SMCLK + UpMode |
14 | |
15 | unsigned long int i; |
16 | |
17 | for (i=0; i<10000000; i++) // Schleife zur LED-Kontrolle |
18 | {
|
19 | P1OUT |= 0x04; // LED an |
20 | }
|
21 | |
22 | P1OUT &= ~0x04; // LED aus |
23 | |
24 | |
25 | _BIS_SR (GIE); // Globale Interrupts aktiv |
26 | |
27 | while (1) // Nichts tun... |
28 | {}
|
29 | }
|
30 | |
31 | #pragma vector=timera0_vector
|
32 | __interrupt void Timer(void) |
33 | {
|
34 | P1OUT ^= 0x04; // Toggle LED |
35 | }
|
Kopier das mal bitte in deinen Compiler! Und sag mal Bescheid, ob die LED am Anfang wenigstens kurz angeht. Dennis
Also ich machen step bei step und das geht nur bis while(1) und bleibt dann da stehen ohne das ein step in die Routine rein geht. Ich weis auch nicht wiso, es kommt auch keine Fehlermeldung und ich hab keine ahnung wiso. Die LED funktioniert aber. #include <msp430x20x2.h> int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten TACTL = TASSEL_2 + MC_1; // SMCLK + UpMode P1DIR |= 0x04; // Setzt P1.2 auf Ausgang CCTL0 = CCIE; // Interrupt durch CCR0 CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF _BIS_SR(GIE); // Globaler Interrupt enable while(1); } // Timer interrupt service routine #pragma VECTOR=TIMERA0_VECTOR __interrupt void Timer(void) { P1OUT ^= 0x04; // Toggle P1.2 }
Dennis schrieb: > WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten Mach daraus mal:
1 | WDTCTL = (WDTPW | WDTHOLD); |
und hier: TACTL = TASSEL_2 + MC_1;
1 | TACTL = (TASSEL_2 | MC_1); |
Vielleicht ist das auch Compiler-abhängig...
So jetzt geht das ich hab rausgefunden woran das ligt schau dir mal den unteren teil an also da wo die ISR ist. So wie es da steht geht das jetzt. Aber viellen viellen dank trotzdem. #include <msp430x20x2.h> int main( void ) { WDTCTL = (WDTPW | WDTHOLD); // Watchdog-Timer ausschalten TACTL = (TASSEL_2 | MC_1); // SMCLK + UpMode P1DIR |= 0x04; // Setzt P1.2 auf Ausgang CCTL0 = CCIE; // Interrupt durch CCR0 CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF _BIS_SR(GIE); // Globaler Interrupt enable while(1){} } // Timer interrupt service routine __interrupt void Timer(void); TIMERA0_ISR(Timer) __interrupt void Timer(void) { P1OUT ^= 0x04; // Toggle P1.2 } mfg
Übrigens: Ich hoffe, du hast da nicht ne normale LED mit 20mA dran! Das tut dem MSP nicht so gut :) 2mA solltest du für den Dauerbetrieb nicht überschreiten.
Jo ich denke mal ja da die Version so alt ist kennst der Debbuger und so das mit #pragma ... nicht aber auf dem rechner wo ich nun mal dranssitze läuft nichts besseres. Vielleicht holle ich mir mal so einen Programieradapter und nen microcontroller und werde mich zuhause damit gescheit beschäftigen. mfg
Marek S. schrieb: > Jo ich denke mal ja da die Version so alt ist kennst der Debbuger und so > das mit #pragma ... nicht Nun ja, jede Toolchain hat da ihre eigene Art der Definition. Bin allerdings (fälschlicherweise) die ganze Zeit davon ausgegangen, dass Du auch IAR benutzt... da hätte 'pragma... gepasst ;-)
Na da bin ich mal wider. Ich hab gerade Probiert das blinken so zu steuern wenn ein Interrupt an P1.1 soll es blinken. Ich hab an P1.1 einen Taster. Es kommt keine Fehler meldung und es Blinkt auch fleisich aber die ganzezeit egal ob ich den Taster drücke oder nicht. Weil mit der do while schleife sage ich ihm doch blos das er den Interupt auslösen soll wenn ich den taster gedruckt habe oder verstehe ich da was falsch. Danke mal wider. Ist es sin voll das so zu machen ich hab auch an einen Interupt in der Interupt routine des Tasters gedacht von wo aus das dan getoggelt wird. Man hat mir aber davon abgeraten. Was meint ihr. #include <msp430x20x2.h> int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Watchdog-Timer ausschalten TACTL = TASSEL_2 + ID_3 + MC_1; // SMCLK + Teiler durch 8 + UpMode P1DIR |= 0x04; // Setzt P1.2 auf Ausgang P1IES = 0x02; //P1.1 An dem der Taster hängt (L -> H wechsel) P1IE = 0x02; // Interrupt enable für P1.1 do{ CCTL0 = CCIE; // Interrupt durch CCR0 CCR0 = 0xFFFF; // Startet Capture-Compare und zählt bis FFFF _BIS_SR(GIE);} // Globaler Interrupt enable while((P1IFG & 0x02)==1); } // Timer interrupt service routine __interrupt void Timer(void); TIMERA0_ISR(Timer) __interrupt void Timer(void) { P1OUT ^= 0x04; // Toggle P1.2 }
Marek S. schrieb: > wenn ein Interrupt an P1.1 soll es blinken. Dein Polling des P1IFG-Flags kann man nicht wirklich als Interrupt bezeichnen ;-) Wenn schon Interrupt, dann aktiviere ihn auch und schreibe eine Interrupt-Routine dazu. ABER: Bei Tasten ist ein Interrupt keine gute Wahl! Du musst den Taster entprellen! > while schleife sage ich ihm doch blos das er den Interupt auslösen soll > wenn ich den taster gedruckt habe oder verstehe ich da was falsch. Ja, allerdings. Zuerst musst Du Deine ganze Peripherie (hier der Timer)einmal initialisieren. Danach würde ich den Timer je nach Zustand des Tasters entweder aktivieren oder stoppen. Deine do-while ist kompletter Murks! > ich hab auch an einen > Interupt in der Interupt routine des Tasters gedacht von wo aus das dan > getoggelt wird. Man hat mir aber davon abgeraten. Was meint ihr. Derjenige, der Dir abgeraten hat ist ein kluger Kopf! Selbst sehr Erfahrene Programmierer meiden verschachtelte Interrupts so gut wie immer! Kann sehr unübersichtlich werden...
Stefan schrieb: > Zuerst musst Du Deine ganze Peripherie (hier der Timer)einmal > initialisieren. Hab ich das nicht schon damit gemacht Hab ich ihn nicht schon damit TACTL = TASSEL_2 + ID_3 + MC_1;. Muß ich das dann noch mal machen in der while schleife?
Marek S. schrieb: > Muß ich das dann noch mal machen in der > while schleife? Na eben nicht! In while() überprüfst Du nur noch, ob die Taste gedrückt ist oder nicht. Hier eine Möglichkeit von zig tausend...:
1 | volatile char LED_Enable; |
2 | |
3 | void main( void ) |
4 | {
|
5 | WDTCTL = WDTPW + WDTHOLD; |
6 | |
7 | P1DIR |= 0x04; |
8 | |
9 | CCTL0 = CCIE; |
10 | CCR0 = 0xFFFF; |
11 | TACTL = TASSEL_2 + ID_3 + MC_1; |
12 | |
13 | LED_Enable = 0; |
14 | |
15 | _BIS_SR(GIE); |
16 | |
17 | while(1) |
18 | { // (Tastenabfrage eventuell noch entprellen...) |
19 | if (P1IN & 0x02) // Taster abfragen (hier high-aktiv) |
20 | LED_Enable = 1; // Blinken aktivieren |
21 | |
22 | else
|
23 | {
|
24 | LED_Enable = 0; // Blinken deaktivieren |
25 | P1OUT &= ~0x04; // LED aus |
26 | }
|
27 | }
|
28 | }
|
29 | |
30 | // Timer interrupt service routine
|
31 | __interrupt void Timer(void); |
32 | TIMERA0_ISR(Timer) |
33 | __interrupt void Timer(void) |
34 | {
|
35 | if(LED_Enable) |
36 | P1OUT ^= 0x04; |
37 | }
|
Dan war das mein Fehler dann hab ich deine Antwort falsch verstanden sorry, ich dachte das solt eich dann noch mal in der While schleife machen was mir aber komisch vorkam aber trotzdem danke. mfg
Stefan schrieb: > while(1) > { // (Tastenabfrage eventuell noch entprellen...) > if (P1IN & 0x02) // Taster abfragen (hier high-aktiv) > LED_Enable = 1; // Blinken aktivieren > > else > { > LED_Enable = 0; // Blinken deaktivieren > P1OUT &= ~0x04; // LED aus > } > } Kannst auch:
1 | while (1) |
2 | {
|
3 | if (P1IN & 0x02) |
4 | TACTL0 |= CCIE; |
5 | else
|
6 | TACTL0 &= ~CCIE; |
7 | }
|
Dann behält die LED ihren Status vor dem Tastendruck. Wie schon gesagt wurde, es gibt zich Möglichkeiten.
@Dennis (Gast) Du sagst ein Blick in das MSP430 Microcontroller Basiccs Buch lohnt sich. Kann man daraus gut was lernen und mit arbeiten? Dan würde ich mir das mal kaufen. Englisch solte ja nicht das Problem sein im notfall überstetzt man mal paar Wörter. mfg
Marek S. schrieb: > Du sagst ein Blick in das MSP430 Microcontroller Basiccs Buch lohnt > sich. Ja, also ich habe ein paar Bücher "durchgearbeitet" und meiner Meinung nach ist das das beste von allen über den MSP430. Es ist komplett in Englisch, klar, aber wer mit Elektronik zu tun hat, der kommt an englisch sowieso nicht vorbei. Da sind viele Programme drin, mit Anwendungen, wie man sie auch immer mal wieder braucht. Von meiner Seite aus jedenfalls absolute Kaufempfehlung. Leider ist der MSP ja nicht so der gebräuchlichste Controller, das siehst du hier ja auch, die meisten programmieren auf Atmel. Das habe ich noch nie gemacht, kann daher nur vom MSP sprechen. Aber für den ist Davies Buch auf jedenfall die Investition wert. Plus natürlich sie Code-Examples, da kann man ebenfalls ne Menge finden! Gruß, Dennis
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.