Forum: Compiler & IDEs ADC am ATTiny24A hängt Controller auf


von Christian B. (luckyfu)


Lesenswert?

Ich habe offensichtlich solch ein Brett vor dem Kopf, daß ich mal 
Unterstützung von außen benötige.
Ich will an einem ATTiny24A am Port PA0 eine analoge Spannung messen. 
Daß das nicht gerade der glücklichste Port dafür ist, das habe ich auch 
schon gemerkt, aber generell funktionieren sollte es ja schon damit, 
oder nicht?

anbei der aktuelle code, Das Problem ist: Im Simulator läuft der 1a 
durch, nur im Controller tut sich nichts.
Er Springt einmal in die Unterfunktion, bleibt dann aber hängen (nachdem 
er sie das 2. mal angesprungen hat), da offensichtlich keine Wandlung 
beendet wird. ich bin nun schon unzählige male durch die Initialisierung 
gegangen und habe das ein paar mal umgeschrieben, auch ein Programm, 
welches auf einem anderen Controller läuft geht hier nicht. Ich bin 
langsam echt am verzweifeln.

hier ist der code der .c Datei
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "mydefs.h"
5
#include "Lipo_Saver.h"
6
#include <util/delay.h>
7
8
#define Durchlaeufe_ADC 5
9
10
 
11
void init(void)
12
{
13
     /*  Schaltausgang 1: PB0
14
       Schaltausgang 2: PB1
15
       Fahrsignal out/In; PB2 
16
       Schaltausgang 3: PA7
17
       Schaltausgang 4: PA6
18
       Schaltausgang 5: PA5
19
       Schaltausgang 6: PA4
20
       Schaltausgang 7: PA3
21
       Schaltausgang 8: PA2
22
       Schalteingang: PA1
23
       AkkuSpannung analog in: PA0
24
     */
25
   DDRA = 0xFC;    //Datenrichtung der Pins festlegen
26
   DDRB = 0x03;
27
   PORTA = 0x01;    // Pull Ups einschalten
28
  
29
   ADMUX = (1 << REFS1);
30
   ADCSRA = (1 << ADPS0) | (1 << ADPS1);
31
   DIDR0 = (1 << ADC0D);      
32
}
33
 
34
int ADC_Messung(uint8_t Kanal)
35
{
36
  uint8_t i;
37
  uint16_t Messwert;
38
  uint32_t Mittelwert = 0;
39
  
40
  ADMUX &= ~((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3));
41
  ADMUX |= Kanal;
42
43
  //for(i = 0; i < Durchlaeufe_ADC; i++)
44
  {
45
    Out4 = ON;
46
    
47
    while(ADCSRA & (1<<ADSC))
48
    {
49
      asm volatile("NOP");
50
    }
//Diese Stelle erreicht er beim 2. Aufruf der Funktion nicht mehr
1
  Out4 = OFF;  
2
  Mittelwert += ADC;
3
  }
4
  
5
  //ADCSRA &= ~(1 << ADSC);
6
  
7
  Messwert = (uint16_t)Mittelwert / Durchlaeufe_ADC;
8
9
  return Messwert;
10
}
11
12
int main(void)
13
{
14
  uint16_t Akkustatus;
15
  ADCSRA |= (1 << ADSC);  //Start der ersten AD Wandlung
16
17
   TCNT0 = 0;
18
   Drive_Out = OFF;
19
  
20
   Out4 = ON;    //nur für debugzwecke
21
   _delay_ms(500); //
22
   Out4 = OFF;    //
23
  _delay_ms(500);  //
24
 
25
//   ADCSRA |= (1 << ADIE);  
26
   ADCSRA |= (1 << ADSC);
27
   while(1)
28
   {      
29
    Akkustatus = ADC_Messung(0);
30
         
31
     if (Akkustatus <= Abschalten)
32
     {
33
       Drive_Out = OFF;  //Ausgang auf Low legen
34
       Drive_DDR = ON;    //Eingang auf Ausgang umschalten -> Puls wird unterdrückt -> Failsave springt an        
35
     } 
36
     else if(Akkustatus <= Warnlevel)
37
     {
38
//       Out4 = ON;      //Vorerst nur debug, Später Blinkmodus einschalten
39
     }
40
     else
41
     {
42
       Drive_DDR = OFF;  //Falls Eingang als Ausgang -> zurück auf Eingang stellen
43
//      Out4 = OFF;
44
     }    
45
    }
46
}

von g457 (Gast)


Lesenswert?

> ich bin nun schon unzählige male durch die Initialisierung gegangen

Wozu? Die wird doch garnicht ausgeführt ∗hüstel∗

von Christian B. (luckyfu)


Lesenswert?

oh weia ist das peinlich!
das scheint irgendwo zwischendrin rausgeflogen zu sein.

ok, mit ausführen der init scheint er jetzt AD Wandlungen zu machen, 
leider bleibt es beim Anschein, denn: der AD Wert ist immer 0, den ich 
zurücklese. Ich hab jetzt das Ganze soweit umgebaut, daß er nur noch bei 
einem AD Wert von 0 den Ausgang setzt, sonst nicht.

Leider ist der Ausgang immer gesetzt.

desweiteren hab ich diese Zeile
1
 ADMUX = (1 << REFS1);
ebenfalls gelöscht, somit sollte er ja automatisch VCC als Referenz 
nutzen.

ich hänge nochmal den ganzen Code an:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "mydefs.h"
5
#include "Lipo_Saver.h"
6
#include <util/delay.h>
7
 
8
void init(void)
9
{
10
     /*  Schaltausgang 1: PB0
11
       Schaltausgang 2: PB1
12
       Fahrsignal out/In; PB2 
13
       Schaltausgang 3: PA7
14
       Schaltausgang 4: PA6
15
       Schaltausgang 5: PA5
16
       Schaltausgang 6: PA4
17
       Schaltausgang 7: PA3
18
       Schaltausgang 8: PA2
19
       Schalteingang: PA1
20
       AkkuSpannung analog in: PA0
21
     */
22
   DDRA = 0xFC;    //Datenrichtung der Pins festlegen
23
   DDRB = 0x03;
24
   PORTA = 0x01;    // Pull Ups einschalten
25
 
26
   ADCSRA = (1 << ADPS0) | (1 << ADPS2);
27
   DIDR0 = (1 << ADC0D);      
28
}
29
 
30
int ADC_Messung(uint8_t Kanal)
31
{
32
  uint8_t i;
33
  uint16_t Messwert;
34
  uint32_t Mittelwert = 0;
35
  
36
  ADMUX &= ~((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3));
37
  ADMUX |= Kanal;
38
  Mittelwert = 0;
39
  
40
  for(i = 0; i < ADC_Messungen; i++)
41
  {
42
    ADCSRA |= (1 << ADSC);
43
    while(ADCSRA & (1<<ADSC))
44
    {
45
      asm volatile("NOP");
46
    }
47
    Mittelwert += ADC;
48
  }
49
  
50
  ADCSRA &= ~(1 << ADSC);
51
  
52
  Messwert = (uint16_t)(Mittelwert / ADC_Messungen);
53
54
  return Messwert;
55
}
56
57
int main(void)
58
{
59
  uint16_t Akkustatus;
60
  
61
  init();
62
  
63
  ADCSRA |= (1 << ADSC);  //Start der ersten AD Wandlung
64
65
   TCNT0 = 0;
66
   Drive_Out = OFF;
67
  
68
   Out4 = ON;    //nur für debugzwecke
69
   _delay_ms(500); //
70
   Out4 = OFF;    //
71
  _delay_ms(500);  //
72
 
73
   ADCSRA |= (1 << ADSC);
74
   while(1)
75
   {      
76
    Akkustatus = ADC_Messung(0);
77
         
78
     if (Akkustatus <= Abschalten)
79
     {
80
       Drive_Out = OFF;  //Ausgang auf Low legen
81
       Drive_DDR = ON;    //Eingang auf Ausgang umschalten -> Puls wird unterdrückt -> Failsave springt an        
82
     } 
83
     /*else*/ if(Akkustatus <= Warnlevel)
84
     {
85
       Out4 = ON;      //Vorerst nur debug, Später Blinkmodus einschalten
86
     }
87
     else
88
     {
89
       Drive_DDR = OFF;  //Falls Eingang als Ausgang -> zurück auf Eingang stellen
90
      Out4 = OFF;
91
     }    
92
    }
93
}
die Lip_Saver.h hat folenden Aufbau
1
#ifndef _Lipo_Saver_h_
2
#define _Lipo_Saver_h_
3
4
#define  Out1    SBIT( PORTB, 0 )
5
#define  Out2    SBIT( PORTB, 1 )
6
#define  Out3    SBIT( PORTA, 7 )
7
#define  Out4    SBIT( PORTA, 6 )
8
#define  Out5    SBIT( PORTA, 5 )
9
#define  Out6    SBIT( PORTA, 4 )
10
#define  Out7    SBIT( PORTA, 3 )
11
#define  Out8    SBIT( PORTA, 2 )
12
13
#define  Drive_Out  SBIT( PORTB, 2 )
14
#define  Drive_In  SBIT( PINB, 2 )
15
#define  Drive_DDR  SBIT( DDRB, 2 )
16
17
#define  In1      SBIT( PINA, 1 )
18
19
/*
20
Schaltausgang 1: PB0
21
Schaltausgang 2: PB1
22
Fahrsignal out/In; PB2
23
Schaltausgang 3: PA7
24
Schaltausgang 4: PA6
25
Schaltausgang 5: PA5
26
Schaltausgang 6: PA4
27
Schaltausgang 7: PA3
28
Schaltausgang 8: PA2
29
Schalteingang: PA1
30
AkkuSpannung analog in: PA0 */
31
32
#define Warnlevel 0    //Warnwert, max 1024
33
#define Abschalten 200    //Abschaltwert, max 1024
34
#define ADC_Messungen 1  //Anzahl der Messungen aus welchen der Mittelwert gebildet wird. Maximal möglich: 4194304
35
36
#define ON 1
37
#define OFF 0
38
39
#endif
ich wird morgen mal nen anderen Controller ausprobieren, vielleicht hat 
der durch meine Experimente auch nen Treffer abbekommen.

von Stefan E. (sternst)


Lesenswert?

Christian B. schrieb:
> scheint er jetzt AD Wandlungen zu machen

Sehr erstaunlich, wo doch der ADC niemals enabled wird.

von Peter D. (peda)


Lesenswert?

Christian B. schrieb:
> Ich will an einem ATTiny24A am Port PA0 eine analoge Spannung messen.
> Daß das nicht gerade der glücklichste Port dafür ist, das habe ich auch
> schon gemerkt,

Woran hast Du das gemerkt?


Christian B. schrieb:
> ich hänge nochmal den ganzen Code an:

Dann tue das auch!

Antwort schreiben
Wichtige Regeln - erst lesen, dann posten!

    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Christian B. (luckyfu)


Lesenswert?

so, nun bitte ich nochmals um Entschuldigung. ich habe so viel hin und 
her probiert, daß offensichtlich auch das ADEN setzen zwischendrin 
entfallen war. ABER: auch das hat keine Besserung gebracht.

Heute habe ich den Controller gewechselt und siehe da: es funktioniert 
auf Anhieb (nachdem ich das ADEN vorher beim alten Controller gesetzt 
habe)

es lag also am Hardwaredefekt. Beim Herumprobieren hab ich dann 
offensichtlich noch mehr "Schaden" angerichtet, der sich aber wieder 
richten lies :)

Vielen Dank an alle die geholfen haben, wenngleich es alles nichts 
nützte

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.