Hi Leute, darf mich mal als neu outen in der Welt der uC. Jetzt möchte ich gerne auf dem MSP430F149 ein Signal AD wandeln. Das Signal soll überabgetastet werden, also mit 8KHz abgestastet werden. Da kommt schon mein Problem ich habe an ACLK ein 32kHz Quarz. Jetzt geb ich ACLK als ADC12CLK vor und teile den durch 4 super ich habe 8kHz. Jetzt will ich das testen, ich springe also jedesmal wenn ich ein AD-Wandlung abgeschlossen habe in einen Interrupt und XOR den Pin, spric er toggelt, jetzt sollte ich doch die Abtastrate sehen oder? Nur ich seh jetzt runde 1kHz, was läuft da schief? Hoff da kann mir jemand weiterhelfen, dreh heute noch durch. CODE: #include <msp430x14x.h> #define Num_of_Results 8 static unsigned int results[Num_of_Results]; // Needs to be global in this // example. Otherwise, the // compiler removes it because it // is not used for anything. void main(void) { WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer P6SEL |= 0x01; // Enable A/D channel A0 BCSCTL1 = DIVA_0 + RSEL0 + RSEL1 + RSEL2; P5DIR |= 0x70; // P5.6,5,4 outputs P5SEL |= 0x70; // P5.6,5,5 options ADC12CTL0 = ADC12ON+SHT1_0+SHT0_0+MSC; // Turn on ADC12, set sampling time ADC12CTL1 = ADC12SSEL_1+SHP+CONSEQ_2; // Use sampling timer, set mode ADC12IE = 0x01; // Enable ADC12IFG.0 ADC12CTL0 |= ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion _BIS_SR(LPM0_bits + GIE); // Enter LPM0,Enable interrupts } #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) { static unsigned int index = 0; results[index] = ADC12MEM0; // Move results index = (index+1)%Num_of_Results; // Increment results index, modulo P4DIR |=0xFF; P4OUT ^=0xFF; }
Super Sache. Jetzt hab ich mal die Zeilen rausgemacht jetzt hab ich 56kHz anliegen super!!!!!! Mensch ich brauch ne Aussage was ich machen muss nicht was ich mir anschauen soll sonst hätt ich es schon richtig. Um das nochmal zu klären ich würde einfach gerne im P4 meine Smplerate am Oszi sehen mehr nicht. hier der erneuerte Code: #include <msp430x14x.h> #define Num_of_Results 8 static unsigned int results[Num_of_Results]; // Needs to be global in this // example. Otherwise, the // compiler removes it because it // is not used for anything. void main(void) { WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer P6SEL |= 0x01; // Enable A/D channel A0 BCSCTL1 = DIVA_0 + RSEL0 + RSEL1 + RSEL2; P5DIR |= 0x70; // P5.6,5,4 outputs P5SEL |= 0x70; // P5.6,5,5 options ADC12CTL0 = ADC12ON+SHT1_0+SHT0_0+MSC; // Turn on ADC12, set sampling time ADC12CTL1 = ADC12SSEL_1+SHP+CONSEQ_2; // Use sampling timer, set mode ADC12IE = 0x01; // Enable ADC12IFG.0 ADC12CTL0 |= ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion _BIS_SR(LPM0_bits + GIE); // Enter LPM0,Enable interrupts } #pragma vector=ADC12_VECTOR __interrupt void ADC12OV (void) { P4DIR |=0xFF; P4OUT ^=0xFF; }
Wo laeuft den dein Prozessor am Schluss des Programmes hin ? Mach da mal ein while(1); am Schluss rein sonst laeuft der ins Leere.
Ok hab ich gemacht, geändert hat sich trotzdem nichts? Steh hier auf einem Feuerwehrschlauch ich sags euch.
>Da kommt schon mein Problem ich habe an ACLK ein 32kHz Quarz. >Jetzt geb ich ACLK als ADC12CLK vor und teile den durch 4 super ich habe >8kHz. Jetzt will ich das testen, ich springe also jedesmal wenn ich ein >AD-Wandlung abgeschlossen habe in einen Interrupt und XOR den Pin, spric >er toggelt, jetzt sollte ich doch die Abtastrate sehen oder? >Nur ich seh jetzt runde 1kHz, was läuft da schief? Deine ADC12CLK ist nicht die Sampleclock , sondern der Arbeitstakt deines ADCs. Deine Wandlung ist erst nach 13 Takten fertig. Also 8KHz / 13 = Wandlungsrate. Und da kommen deine 1 KHz schon in etwa hin. Nimm mal den ADC12OSC als Arbeitstakt oder sorgt dafuer das die ACLK schneller wird. >Steh hier auf einem Feuerwehrschlauch ich sags euch. Nicht so aufregen sonst gibt noch einen Herzinfarkt.
Helmut Lenzen schrieb: > Deine Wandlung ist erst nach 13 Takten fertig. Also 8KHz / 13 = > Wandlungsrate. Und da kommen deine 1 KHz schon in etwa hin. Nicht ganz. 4 Takte für S/H kommen noch dazu. Ausserdem sehe ich nirgends, dass ADC12CLK = ACLK / 4 eingestellt wird! ADC12CLK = ACLK! > Nimm mal den ADC12OSC als Arbeitstakt oder sorgt dafuer das die ACLK > schneller wird. Dann braucht man ACLK nicht mehr. CPU läuft über'n DCO
Das ist doch mal ne Aussage. Ok Hab jetzt mal den ADC12OSC als Arbeitstakt genommen. sollte ja um die 5MHz sein teil ich das durch 13 kommen knappe 390kHz raus am Oszi werden mir aber 80kHz angezeigt, stell ich ein Teiler von 8 ein DIVA_3 kommen immernoch 80kHz raus, was stimmt da nicht? CODE: #include <msp430x14x.h> void main(void) { WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer P6SEL |= 0x01; // Enable A/D channel A0 BCSCTL1 = DIVA_0 + RSEL0 + RSEL1 + RSEL2; P5DIR |= 0x70; // P5.6,5,4 outputs P5SEL |= 0x70; // P5.6,5,5 options ADC12CTL0 = ADC12ON+SHT1_0+SHT0_0+MSC; // Turn on ADC12, set sampling time ADC12CTL1 = ADC12SSEL_0+SHP+CONSEQ_2; // Use sampling timer, set mode ADC12IE = 0xFF; // Enable ADC12IFG.0 ADC12CTL0 |= ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion _BIS_SR(LPM0_bits + GIE); // Enter LPM0,Enable interrupts while(1); } #pragma vector=ADC12_VECTOR __interrupt void ADC12OV (void) { P4DIR |=0x01; P4OUT ^=0xFF; }
Wie schnell ist denn deine MCLK fuer dein Prozessor getaktet ?
>Nicht ganz. 4 Takte für S/H kommen noch dazu.
Ok habe ich geschlabbert.
Ok, kommt trotzdem nicht hin. SMCLK/MCLK führ ich ja raus kommen knapp 3.1Mhz raus. Aber das Problem ist, wenn ich DIVA ändere sollte sich doch auch das Signal am Ausgang ändern macht es aber gerade mal garnicht, das versteh ich nicht.
> ADC12IE = 0xFF; // Enable ADC12IFG.0
Du willst nur den Interrupt von Kanal 0 schaltest aber alle ein.
Irgendwie sehe ich auch nicht wo CSTARTADD in ADC12CTL1 gesetzt wird. Auch must du in den Registern ADC12MCTLx das EOS bit setzen. Dein Interrupt kommt nur wenn er die Messsequenz abgearbeitet hat und das ist bei dir Zufall was da drin steht.
So jetzt nochmal zum Verständnis. Ich lege ACLK mit DIVA_0 an heisst mein ADC12CLK ist 32Khz. Passt soweit auch kann ich ja am P2.6 abnehmen. So nun ist SHT0_0 SHT1_= und MSC_1 damit sollte eine Sample Time 32kHz/4 also 8kHz herauskommen. Ok. Nun ist A0 als ADC eingang geschaltet. ADC12MCTL0 = EOS+INCH_0+SREF_0; Hier setze ich End of Sample (weiß ich nicht wirklich für was das gut ist) SREF auf AVCC und AVSS, INput Channel auf A0. Soweit so gut. Jetzt sollte er ja nach jedem schreiben in den Memory in mein INterrupt springen, also ist das meine Abtastfrequenz? Oder bin ich da falsch? Oder gibt es eine Fausformel wie ich auf meine Abtastfrequenz komme ohne groß zu überlegen. Ich muss halt eine bestimmte Abtastfrequenz haben weil ich Mittelwert über ~1s bilden will. CODE: #include <msp430x14x.h> void main(void) { WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer P6SEL |= 0x01; // Enable A/D channel A0 BCSCTL1 = DIVA_0 + RSEL0 + RSEL1 + RSEL2; P5DIR |= 0x70; // P5.6,5,4 outputs P5SEL |= 0x70; // P5.6,5,5 options P2DIR |= 0x40; P2SEL |= 0x40; ADC12CTL0 = ADC12ON+SHT1_0+SHT0_0+MSC; // Turn on ADC12, set sampling time ADC12CTL1 = CSTARTADD_0+ADC12SSEL_1+SHP+CONSEQ_2; // Use sampling timer, set mode ADC12MCTL0 = EOS+INCH_0+SREF_0; //End of Sequence; Reference AVCC AVSS; Input Channel A0 ADC12IE = 0x01; // Enable ADC12IFG.0 ADC12CTL0 |= ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion _BIS_SR(LPM0_bits + GIE); // Enter LPM0,Enable interrupts while(1); } #pragma vector=ADC12_VECTOR __interrupt void ADC12OV (void) { P4DIR |=0x01; P4OUT ^=0xFF; }
EOS ist end of sequence, brauchst du, wenn du mehrere Kanäle hintereinander wandeln willst. Durch das XOR in deiner ISR bekommst du eh nur die halbe Abtastfrequenz am P4 raus, weil ja zu einer Periode 2 Flankenwechsel gehören. Was kommt denn raus an P4?
Fabian Hof schrieb: > So nun ist SHT0_0 SHT1_= und MSC_1 damit sollte eine Sample Time 32kHz/4 > also 8kHz herauskommen. Nö! SHTx stellt die Samplingzeit ein und die beträgt bei Dir nun 4 Taktzyklen. Dazu kommen noch 13 Takzyklen Wandlungsdauer... macht zusammen 17 Taktzyklen bei einem Clock von 32kHz! Werf mal einen (erneuten) Blick in den User Guide :-)
Also an P4 liegt ~80kHz, d.h. ich hab eine Effektive Abtastrate von 40kHz. Ok 17 Zyklen von 32kHz = 531,25us solange dauert es einmal ein Wert einzulesen, das wäre dann eine Abtastrate von 1,882kHz. Was macht denn der gute uC bei tsample ? Was heißt 4 Taktcyklen Smaplingtime? Heißt das er braucht 4*1/32kHz um einen Wert am ADC anliegen zu haben und nochmal 13 Zyklen um ihn in einen Digitalen Wert zu Wandeln?
Fabian Hof schrieb: > Was macht denn der gute uC bei tsample ? Was heißt 4 Taktcyklen > Smaplingtime? Die Eingangskapazität des ADC muss aufgeladen werden (RC-Glied). D.h. man muss eine gewisse "Wartezeit" einhalten und die stellt man mit SHTx ein. > Heißt das er braucht 4*1/32kHz um einen Wert am ADC anliegen zu haben > und nochmal 13 Zyklen um ihn in einen Digitalen Wert zu Wandeln? So sieht's aus!
Schau mal in den User Guide, da sind alle deine Fragen erklärt. Bei 80kHz am P4 wird deine ISR mit 160khz aufgerufen. Durch das XOR machst du dann 80kHz draus. Ich schätze, da läuft mit dem Takt was falsch, sicherlich liegt der SMCLK als ADC-Takt an, oder der ADC Oszillator.
Der User Guide, da schau ich seit 3 Tagen rein. Am ADC12CLK liegt definitiv 32kHz an also kann ich mir die 160kHz überhaupt nicht erklären. Also wenn ich 8kHz Abtastfrequenz haben will brauch ich 125us als tsample = 17*1/fs also ~136kHz.
Mach das ganze mal grundlegend anders. Lass den ADC mit seinem internen Takt laufen, berechne die Setup und Hold Zeiten entsprechend den Angaben im user Guide betreffs Ausgangswiderstand der zu messenden Quelle usw. und mach die feste Abtastrate über den Timer. Du kannst beim ADC einstellen, dass er durch den Timer gestartet wird. Dann musst du nur den Timer so einstellen, dass er aus dem SMCLK die 8kHz generiert und der Rest läuft dann alleine ab. In den Codebespielen, genauer in "fet140_adc12_11.c" ist diese Vorgehensweise genauestens beschrieben:
1 | //*****************************************************************************
|
2 | // MSP-FET430P140 Demo - ADC12, Single Channel Rpt Mode, TA1 as Sample Trigger
|
3 | //
|
4 | // Description: Sample and convert A0 using Timer_A as sample trigger in
|
5 | // Pulse Sample mode. Put "Num_of_Results" ADC12MEM0 values in results[]
|
6 | // and illuminate LED (P1.0) when done.
|
7 | //
|
8 | // MSP430F149
|
9 | // ---------------
|
10 | // | |
|
11 | // Vin -->|P6.0/A0 P1.0|--> LED
|
12 | // | |
|
13 | //
|
14 | // H. Grewal / G. Morton
|
15 | // Texas Instruments Inc.
|
16 | // May 2005
|
17 | // Built with Code Composer Essentials Version: 1.0
|
18 | //*****************************************************************************
|
19 | #include <msp430x14x.h> |
20 | |
21 | #define Num_of_Results 512
|
22 | int results[Num_of_Results] = {0}; |
23 | |
24 | void ADC_Init(void); |
25 | |
26 | void main(void) |
27 | {
|
28 | WDTCTL = WDTPW | WDTHOLD; // Disable the Watchdog. |
29 | ADC_Init(); // Initialize ADC12 |
30 | ADC12CTL0 |= ENC; // Start conversion |
31 | _BIS_SR(LPM0_bits); // Enter LPM0 |
32 | }
|
33 | |
34 | |
35 | void ADC_Init(void) |
36 | {
|
37 | P1DIR = 0xff; // set port to outputs |
38 | P1OUT = 0; // reset port outputs |
39 | P6SEL |= 0x01; // select A0 input |
40 | ADC12CTL0 = ADC12ON+SHT0_1+REF2_5V+REFON; // Setup ADC12 |
41 | ADC12CTL1 = SHP+CONSEQ_2+SHS_1; // Timer triggers sampling |
42 | ADC12MCTL0 = INCH_0 + SREF_1; |
43 | ADC12IE = 0x0001; // Enable ADC12IFG.0 |
44 | |
45 | |
46 | TACCR0 = 1500; // Delay to allow Ref to settle |
47 | TACCTL0 |= CCIE; // Compare-mode interrupt. |
48 | TACTL = TASSEL_1 | MC_1; // TACLK = ACLK, Up mode. |
49 | _BIS_SR(LPM3_bits + GIE); // Wait for delay, Enable interrupts |
50 | TACCTL0 &= ~CCIE; // Disable timer |
51 | |
52 | P2SEL |= BIT3; // Set for Timer A1 |
53 | P2DIR |= 0x08; |
54 | TACCR0 = 7; // Init TACCR0 w/ sample prd=CCR0+1 |
55 | TACCR1 = 4; // Trig for ADC12 sample & convert |
56 | TACCTL1 = OUTMOD_3; // Set/reset |
57 | TACTL = TACLR | MC_1 | TASSEL_1; // ACLK, clear TAR, up mode |
58 | }
|
59 | |
60 | // Timer_A0 Interrupt Service Routine
|
61 | __interrupt void ta0_isr(void); |
62 | TIMERA0_ISR(ta0_isr) |
63 | __interrupt void ta0_isr(void) |
64 | {
|
65 | TACTL = 0; |
66 | LPM3_EXIT; // Exit LPM3 on return |
67 | }
|
68 | |
69 | |
70 | // ADC12 Interrupt Service Routine
|
71 | __interrupt void ADC_ISR (void); |
72 | ADC12_ISR(ADC_ISR) |
73 | __interrupt void ADC_ISR (void) |
74 | {
|
75 | static unsigned int index = 0; |
76 | |
77 | results[index++] = ADC12MEM0; // Move results |
78 | |
79 | if (index == 512) |
80 | {
|
81 | ADC12CTL0 &= ~ENC; // Stop conversion |
82 | index = 0; |
83 | P1OUT |= 0x01; |
84 | _BIS_SR(LPM3_bits); // Enter LPM3, SET BREAKPOINT HERE |
85 | }
|
86 | }
|
Ich würde die 8kHz Samplerate nicht mit dem Versorgungstakt des ADC's bestimmen, sondern z.B. mit einem Timer die Messung anstossen und den ADC dann selber machen lassen, mit einem vernünftigen Takt. Die Timings hast Du dann wahrscheinlich besser im Griff und kannst auch den Takt und die Einstellungen am ADC optimieren, ohne dass sich ständig Deine Samplerate ändert.
@ Christian R. Kannst du mir mal bitte sagen wo ich da mein Timer Intervall einstell? Wenn TACCR0 ändere, bekomm ich an P2.3 immer 4kHz, aber wie kann ich die Frequenz nun ändern?
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.