Timer INterrupt + ADC Interrupt Probleme

OP (Firma: keine) #1729330
Lesenswert?

Hi Leute,

hab mal wieder eine Problem, das ich nicht gebacken bekomm.

Also kurze Beschreibung was ich haben möchte.

Muss ein Signal max 2kHz abtasten und den RMS bilden. Jetzt hab ich mir 
das so vorgestellt ich taste immer mit 8192Hz ab. Das habe ich über 
einen Timer Interrupt gelöst der mit externem Quarz funktioniert.
Ok: wenn ich jetzti in dem Timer_interrupt bin möchte ich den AD-Wandler 
anscmeißen er soll mir 1!-Wert auslesen und sich wieder ausstellen.
Nach dem 8192 Aufruf wird RMS gebildet, das ganze geht von vorne los.

Jetzt zum Problem, der Timer geht ohne Probleme, nur das mit dem Wert 
auslesen klappt nicht ganz. Ich seh den Fehler gerade nicht vll. sieht 
jeamdn von euch den auf die schnelle, oder kann mir sagen wie ich das 
ganze inteligenter oder elleganter lösen kann.
1
//******************************************************************************
2
//ADC WANDLUNG MIT 8192Hz um RMS zu bilden
3
//******************************************************************************
4

5
#include  <msp430x14x.h>
6
#include  <math.h>
7

8
void ADC_Init(void);
9
void ADC_Disable(void);
10

11
void main(void)
12
{
13
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
14
  P4DIR |= 0x0F;                            // P4.0 output
15
  P4OUT=0;                                  //Reset Outputs
16
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
17
  CCR0 = 3;                                 //32768/4 =8192Hz
18
  TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
19

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

23
// Timer A0 interrupt service routine
24
#pragma vector=TIMERA0_VECTOR
25
__interrupt void Timer_A (void)
26
{
27
  P4OUT ^= 0x0F;                            // Toggle P1.0
28
  ADC_Init();
29
  ADC_Disable();
30
}
31

32
void ADC_Init(void)
33
{
34
  P6SEL |= 0x01;                            // select A0 input
35
  ADC12CTL0 = ADC12ON+SHT0_0+ENC+ADC12SC;   // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
36
  ADC12CTL1 = CSTARTADD0+SHP+ADC12DIV0+ADC12SSEL_3+CONSEQ_0+SHS_0;  // ADC12MEM0;Triggerd sampling Timer;Clock Divider=0;SMCLK=3Mhz;Single conversion;Conversion active;Source=ADC12SC
37
  ADC12MCTL0 = EOS+INCH_0+SREF_0;           //Enable_end of Sample; Source A0;Source AVCC AVSS; 
38
  ADC12IE = 0x0001;                         // Enable ADC12IFG.0
39
  _BIS_SR(LPM0_bits + GIE);                 // Wait for delay, Enable interrupts
40

41
}
42

43
void ADC_Disable(void){
44
  P6SEL |= 0x00;                            // diselect A0 input
45
  ADC12CTL0 = ADC12ON+SHT0_0;               // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
46
  _BIS_SR(LPM0_bits + GIE);                 //Nur ACLK active
47
  ADC12CTL0 &= ~ENC;
48
}
49

50
#pragma vector=ADC12_VECTOR
51
__interrupt void ADC12ISR (void)
52
{
53
 //aus MEM0 lesen 1 mal und RMS bilden nach 8192 aufrufen
54
}
#1732892
Lesenswert?

Ich kenn zwar den MSP überhaupt nicht.
Aber das hier klingt für mich ziemlich abenteuerlich
1
  ADC_Init();
2
  ADC_Disable();
3
}
4

5
void ADC_Init(void)
6
{
7
  P6SEL |= 0x01;                            // select A0 input
8
  ADC12CTL0 = ADC12ON+SHT0_0+ENC+ADC12SC;   // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
9
  ADC12CTL1 = CSTARTADD0+SHP+ADC12DIV0+ADC12SSEL_3+CONSEQ_0+SHS_0;  // ADC12MEM0;Triggerd sampling Timer;Clock Divider=0;SMCLK=3Mhz;Single conversion;Conversion active;Source=ADC12SC
10
  ADC12MCTL0 = EOS+INCH_0+SREF_0;           //Enable_end of Sample; Source A0;Source AVCC AVSS; 
11
  ADC12IE = 0x0001;                         // Enable ADC12IFG.0
12
  _BIS_SR(LPM0_bits + GIE);                 // Wait for delay, Enable interrupts
13

14
}
15

16
void ADC_Disable(void){
17
  P6SEL |= 0x00;                            // diselect A0 input
18
  ADC12CTL0 = ADC12ON+SHT0_0;               // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
19
  _BIS_SR(LPM0_bits + GIE);                 //Nur ACLK active
20
  ADC12CTL0 &= ~ENC;
21
}

Da wird in der Timer ISR der ADC eingeschaltet um gleich darauf wieder 
ausgeschaltet zu werden. Wie gesagt: ICh kenn den MSP nicht. Kann 
natürlich gut sein, dass sich der ADC ums Ausschalten nicht kümmert, 
solange eine Wandlung im Gange ist. Was er allerdings dazu sagt wenn du 
ihm mitten unter der Wandlung den A0 wegschaltest, wage ich nicht zu 
erraten.

Wie gesagt: Ich kenn den MSP überhaupt nicht. Aber das was du da hast 
ist nicht logisch.
Die Erwartungshaltung wäre gewesen:
In der Timer ISR wird der ADC gestartet. Dar macht sein Ding. Wenn er 
fertig ist, wird die ADC-ISR aufgerufen und erst dort wird der ADC 
wieder abgeschaltet.
#1732929
Lesenswert?

Fabian Hof schrieb:
1
> #pragma vector=TIMERA0_VECTOR
2
> __interrupt void Timer_A (void)
3
> {
4
>   P4OUT ^= 0x0F;                            // Toggle P1.0
5
>   ADC_Init();
6
>   ADC_Disable();
7
> }
8

9
> 
10
> void ADC_Init(void)
11
> {
12
[...]
13
>   _BIS_SR(LPM0_bits + GIE);                 // Wait for delay, Enable
14
> interrupts
15
> 
16
> }
17
> 
18
> void ADC_Disable(void){
19
[...]
20
>   _BIS_SR(LPM0_bits + GIE);                 //Nur ACLK active
21
>   ADC12CTL0 &= ~ENC;
22
> }
23
>

Du schickst den Prozessor mitten in einer ISR wieder in den LPM. Das 
heißt, der Timer-Interrupt wird nie beendet. Ein _BIS_SR solltest Du 
niemals in einer Interrupt-Routine machen, allerhöchstens ein 
_BIS_SR_on_exit. Am Ende eines Interrupts wird ohnehin das SR wieder 
zurückgeladen, und der Prozessor geht wieder in den LPM-Modus, in dem er 
vorher war.

fchk
OP (Firma: keine) #1732949
Lesenswert?

Ok, lassen wir mal die LPM weg.

Seh ich gerade ein Problem, in der Zeile
ADC12CTL1 = CSTARTADD0+SHP+ADC12DIV0+ADC12SSEL_3+CONSEQ_0+SHS_0;
Schreibt er mir nichts in das Register auch wenn ich ADC12CTL1 = 0x0218; 
mach schreibt er überhaupt nichts rein.

Ich seh gereade nicht was ich falsch mache.

Noch eine Frage im Timer_A interrupt soll er ja solange bleiben bis der 
ADC Interrupt kommt, muss ich da eine Schleife rein machen? Wenn ja 
bleib ich da nach dem ADC_Interrupt nicht hängen?




1
#include  <msp430x14x.h>
2
#include  <math.h>
3

4
void ADC_Init(void);
5
void ADC_Disable(void);
6

7
double sum;
8
unsigned int i=0;
9
double RMS;
10

11
void main(void)
12
{
13
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
14
  P4DIR |= 0x0F;                            // P4.0 output
15
  P4OUT=0;                                  //Reset Outputs
16
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
17
  CCR0 = 3;                                 //32768/4 =8192
18
  TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
19
  //Test
20
  ADC12IE = 0x0001;                         // Enable ADC12IFG.0
21
  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
22
}
23

24
// Timer A0 interrupt service routine
25
#pragma vector=TIMERA0_VECTOR
26
__interrupt void Timer_A (void)
27
{
28
  P4OUT ^= 0x0F;                            // Toggle P1.0
29
  ADC_Init();
30
}
31

32
void ADC_Init(void)
33
{
34
  P6SEL |= 0x01;                            // select A0 input
35
  ADC12CTL0 = ADC12ON+SHT0_0+ENC+ADC12SC;   // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
36
  ADC12CTL1 = CSTARTADD0+SHP+ADC12DIV0+ADC12SSEL_3+CONSEQ_0+SHS_0;  // ADC12MEM0;Triggerd sampling Timer;Clock Divider=0;SMCLK=3Mhz;Single conversion;Conversion active;Source=ADC12SC
37
  ADC12MCTL0 = EOS+INCH_0+SREF_0;           //Enable_end of Sample; Source A0;Source AVCC AVSS; 
38
  ADC12IE = 0x0001;                         // Enable ADC12IFG.0
39

40
}
41

42
void ADC_Disable(void){
43
  P6SEL |= 0x00;                            // diselect A0 input
44
  ADC12CTL0 = ADC12ON+SHT0_0;               // Setup ADC12; 4 Cycles Sample Time; Enable Conversion;Start conversion
45
  ADC12CTL0 &= ~ENC;
46
}
47

48
#pragma vector=ADC12_VECTOR
49
__interrupt void ADC12ISR (void)
50
{
51
 double temp=0.0;
52
  if(i<8192.0){
53
    
54
    temp=((ADC12MEM0)*732.421875E-6);
55
    sum=sum+temp*temp;
56
    i++;
57
  }else{
58
    RMS=sqrt(sum/8192.0);
59
    i=0;
60
    sum=0;
61
  }
62
  static double test;
63
  test=(ADC12MEM0*732.421875E-6);
64
 ADC_Disable();
65
}
#1732986
Lesenswert?

Fabian Hof schrieb:
> Ok. Keine Schleife.
> Die Zeile _BIS_SR(LPM0_bits + GIE); im main auch raus?

nein, die nicht. Der soll ja außerhalb der Interrupts im LPM0 sein, 
oder?

Und kein Floating-Point im Interrupt. Das ist (a) sehr langsam und 
könnte (b) auch zu Problemen führen.

> Bzw. was ist das Problem warum er mir ADC12CTL1 nicht initiiert?

Lies das MSP430x1xx Family User's Guide. Da stehts drin. Tip: Unter 
Abschnitt 17.3 schauen.

Und es gibt auch ein Paket mit Beispielcode von TI. Das ist auch sehr 
hilfreich.

fchk

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren