Forum: Compiler & IDEs ATtiny44 AD Intialisierung


von Michael (Gast)


Lesenswert?

Hallo, ich habe eine Frage und hoffe, dass ihr mir helfen könnt!

Erstmal zu den Fakten!
Ich habe eine Platine, auf welcher sich unter anderem der tiny, 
fototransistor und etliche LED's befinden.

Ich habe eine Eingangsspannung von max. 24V welche aber auf 5V runter 
geschraubt wird!

Was ich machen möchte ist je nachdem wie dunkel es ist mehr LED's 
leuchten lassen! Wenn ich mein Programm flashe, passiert jedoch nichts..

Könnt ihr mir bitte helfen evtl. Fehler zu finden?

Lg Michael
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
6
int main(void)
7
{
8
  unsigned int x;
9
  
10
  DDRA = 0xFE;
11
  DDRB = 0xFF;
12
  
13
  ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));
14
  ADMUX |= (1<<REFS0);
15
  ADMUX &= (1<<REFS1);
16
  ADCSRB &= ~((1<<ADTS2)|(1<<ADTS1)|(1<<ADTS0));   
17
  ADCSRA |= (1<<ADATE);               
18
  ADCSRA |= (1<<ADEN);               
19
  ADCSRA |= (1<<ADSC);    
20
  
21
  while (ADCSRA & (1<<ADSC));
22
    x = ADC;
23
    
24
  while (1)
25
  {
26
    ADCSRA |= (1<<ADSC);
27
    while (ADC>=1 && ADC<=128);
28
    PORTB |= (1<<PB2);
29
    
30
    while (ADC>=1 && ADC<=256);
31
    PORTB |= (1<<PB2);
32
    PORTA = 0x80;
33
    
34
    while (ADC>=1 && ADC<=384);
35
    PORTB |= (1<<PB2);
36
    PORTA = 0xC0;
37
    
38
    while (ADC>=1 && ADC<=512);
39
    PORTB |= (1<<PB2);
40
    PORTA = 0xE0;
41
    
42
    while (ADC>=1 && ADC<=640);
43
    PORTB |= (1<<PB2);
44
    PORTA = 0xF0;
45
    
46
    while (ADC>=1 && ADC<=768);
47
    PORTB |= (1<<PB2);
48
    PORTA = 0xF8;
49
    
50
    while (ADC>=1 && ADC<=896);
51
    PORTB |= (1<<PB2);
52
    PORTA = 0xFC;
53
    
54
    while (ADC>=1 && ADC<=1023);
55
    PORTB |= (1<<PB2);
56
    PORTA = 0xFE;
57
  }        
58
}

von Sudo (Gast)


Lesenswert?

Weil dein Programm Murks ist !
>while (ADC>=1 && ADC<=128);
meist du vielleicht if(...)

von Uwe (Gast)


Lesenswert?

Weil du warten mußt bis der ADC fertig gewandelt hat, der sagt dir das 
indem er ein Bit im Statusregister setzt.

von Uwe (Gast)


Lesenswert?

Wenn man es so schreibt geht natürlich etwas, aber er würde sich immer 
die höchste Helligkeit merken und dei lampen erst wieder auschalten 
nachdem das licht ausgeschaltet worden ist.
Ich denke es ist nicht das was du willst.

  while (1)
  {
    while (ADCSRA & (1<<ADSC));
    x = ADC;


    ADCSRA |= (1<<ADSC);
    while (x>=1 && x<=128);
    PORTB |= (1<<PB2);

    while (x>=1 && x<=256);
    PORTB |= (1<<PB2);
    PORTA = 0x80;

    while (x>=1 && x<=384);
    PORTB |= (1<<PB2);
    PORTA = 0xC0;

    while (x>=1 && x<=512);
    PORTB |= (1<<PB2);
    PORTA = 0xE0;

    while (x>=1 && x<=640);
    PORTB |= (1<<PB2);
    PORTA = 0xF0;

    while (x>=1 && x<=768);
    PORTB |= (1<<PB2);
    PORTA = 0xF8;

    while (x>=1 && x<=896);
    PORTB |= (1<<PB2);
    PORTA = 0xFC;

    while (x>=1 && x<=1023);
    PORTB |= (1<<PB2);
    PORTA = 0xFE;
  }

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:

> Ich denke es ist nicht das was du willst.

Aber deines auch nicht.

Die while Schleifen sind Quatsch.
Du sollst nur einmal den ADC auslesen und dann entscheidest du anhand 
des Messwertes, wieviele LED einzuschalten sind.

"entscheidest" - da steckt schon der Hinweis drinn. Eine Entscheidung 
wird mit einem if gemacht und nicht mit einer SChleife.

1
  while( 1 )
2
  {
3
    while (ADCSRA & (1<<ADSC))
4
      ;
5
    x = ADC;
6
7
    if( x < 128 )
8
      1 LED einschalten
9
10
    else if( x < 256 )
11
      2 LED einschalten
12
13
    else if( ....
14
  }

@TO
Die Initialisierung ist auch zu überdenken. Es gibt in diesem Programm 
keinen wirklichen Grund ADATE zu verwenden. Benutze den ADC ganz 
konventionell, d.h. du startest ihn manuell und du wartest darauf, dass 
er fertig wird.
1
  while( 1 )
2
  {
3
    ADCSRA |= ( 1<<ADSC);          // ADC starten
4
    while (ADCSRA & (1<<ADSC))     // auf das Ergebnis warten
5
      ;
6
    x = ADC;                       // Ergbnis abholen
7
8
    if( x < 128 )
9
      1 LED einschalten, alle anderen aus
10
11
    else if( x < 256 )
12
      2 LED einschalten, alle anderen aus
13
14
    else if( ....
15
16
  }

Das vemeidet dann auch Probleme, dass du ADCSRA genau zum richtigen 
Zeitpunkt abfragen musst. Nämlich genau in der zeitlichen Lücke, in der 
der ADC gerade fertig geworden ist und eigenständig den nächsten 
Messzyklus anfängt. Denn nur exakt in dieser zeitlichen Lücke ist das 
ADSC Bit dann auch tatsächlich auf 0.

von Michael (Gast)


Lesenswert?

Huch, danke erstmal für die vielen Antworten!

Ich möchte tatsächlich, dass das Licht immer den aktuellsten 
Helligkeitswerten angepasst ist!

Dh. sehr dunkel alle LED's, mittel 4 LED's z.B.

Danke für den Tipp mit der Intialisierung, werd ich mir nochmal 
anschauen!

lg

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> Danke für den Tipp mit der Intialisierung, werd ich mir nochmal
> anschauen!

Du solltest dir vor allen Dingen das
AVR-GCC-Tutorial
anschauen und ganz konkret in diesem Tut nach "ADC" suchen. Da gibt es 
eine Verlinkung zu einer Subseite, auf der du alles über den ADC 
findest. Inklusive fertiger C-Funktionen, in denen du nur noch die 
Referenzspannung einstellen musst, die du aber ansonsten so verwenden 
kannst, wie sie sind.

von Michael (Gast)


Lesenswert?

Ich hab das Programm jetzt "etwas" angepasst, und nun funktioniert es 
einwandfrei.

Danke für eure Hilfe, und unten nochmals den Code, falls es jemanden 
interessiert ;)

lg Michael
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
6
int main(void)
7
{
8
  unsigned int x;
9
  
10
  DDRA = 0xFE;
11
  DDRB = 0xFF;
12
  
13
  ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));
14
  //ADMUX = (1<<REFS0);                
15
  ADCSRA |= (1<<ADEN);               
16
17
    
18
  while (1)
19
  {
20
    ADCSRA |= (1<<ADSC);
21
    while (ADCSRA & (1<<ADSC))
22
    {
23
    }
24
    x = ADC;
25
    
26
    if( (x >= 0) && (x < 36))
27
    {
28
    PORTA = 0x01; 
29
    }
30
    
31
    else if( (x >= 36) && (x < 72))
32
    {
33
    PORTA = 0x03;
34
    }
35
    
36
    else if( (x >= 72) && (x < 108))
37
    {
38
    PORTA = 0x07;
39
    }
40
    
41
    else if( (x >= 108) && (x < 144))
42
    {
43
    PORTA = 0x0F;
44
    }
45
    
46
    else if( (x >= 144) && (x < 180))
47
    {
48
    PORTA = 0x1F;
49
    }
50
    
51
    else if( (x >= 180) && (x < 216))
52
    {
53
    PORTA = 0x3F;
54
    }
55
    
56
    else if( (x >= 216) && (x < 252))
57
    {
58
    PORTA = 0x7F;
59
    }
60
    
61
    else if( (x >= 252) && (x < 288))
62
    {
63
    PORTB |= (1<<PB2);
64
    PORTA = 0x7F;
65
    }
66
  }        
67
}

von Karl H. (kbuchegg)


Lesenswert?

Wenn das Programm hier ....
1
    
2
    else if( (x >= 36) && (x < 72))
3
    {
4
    PORTA = 0x03;
5
    }

... jemals zur Abfrage kommt, dann steht bereits fest, dass x 
großer/gleich 36 sein MUSS. Denn wenn x kleiner wäre, dann würde das 
Programm gar nicht bis hier her kommen, sondern wegen
1
    if( (x >= 0) && (x < 36))
2
    {
3
    PORTA = 0x01; 
4
    }
5
    
6
    else if( (x >= 36) && (x < 72))
7
    {
8
    PORTA = 0x03;
9
    }
10
...
bereits im ersten if hängen bleiben. Dann wird aber alles nachfolgende 
nach dem else gar nicht mehr betrachtet.

D.h.
* du bürdest deinem µC eine Fleissaufgabe auf, indem du etwas testest, 
was gar nicht mehr möglich ist (genauso wie x als unsigned Wert nicht 
kleiner als 0 sein KANN).

* schlimmer aber: du baust dir eine potentielle Falle, indem du an 2 
Stellen im Programm denselben Zahlenwert hinschreiben musst. Und das ist 
ein 'Muss', das der Compiler für dich nicht überwachen kann. D.h. du 
hast dir da in den Code etwas eingebaut, was nur darauf angewiesen ist, 
das du als Programmierer sorgfältig bist. Und das geht dann eben öfter 
schied als einem lieb ist.

So
1
    if( x < 36 )
2
    {
3
      PORTA = 0x01; 
4
    }
5
    
6
    else if( x < 72 )
7
    {
8
      PORTA = 0x03;
9
    }
10
    
11
    else if( x < 108 )
12
    {
13
      PORTA = 0x07;
14
    }
15
    
16
    else if( x < 144 )
17
    {
18
      PORTA = 0x0F;
19
    }
20
    
21
    else if( x < 180 )
22
    {
23
      PORTA = 0x1F;
24
    }
25
    
26
    else if( x < 216 )
27
    {
28
      PORTA = 0x3F;
29
    }
30
    
31
    else if( x < 252 )
32
    {
33
      PORTA = 0x7F;
34
    }
35
    
36
    else if( x < 288 )
37
    {
38
      PORTB |= (1<<PB2);
39
      PORTA = 0x7F;
40
    }

... ist das haarscharf dieselbe Auswertung. Mit dem einen Unterschied, 
dass jede Grenze nur einmal in Form einer Zahl im Programm vorkommt. 
D.h. hier kann es dir per Definition nicht passieren, dass die Werte in 
2 aufeinanderfolgenden if -Abfragen nicht zusammenpassen.

von Karl H. (kbuchegg)


Lesenswert?

1
  DDRA = 0xFE;
2
3
...    
4
    PORTA = 0x01;

bist du dir da ganz sicher?
Bit 0 vom Port A ist nicht auf Ausgang geschaltet.

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.