Hallo liebe Mikrocontroller-Gemeinde!
Ich bin gerade dabei mich mit Mikrocontrollern und C zu beschäftigen.
Also seid nicht zu brutal zu mir!
Ich habe ein Array mit 10 Werten. Es soll der erste Wert des Arrays mit
einem Pointer ausgelesen werden. Dieser Wert soll 10mal am Port A
ausgegeben werden.
Nach dem zehnten Durchlauf soll der zweite Wert im Array genommen werden
und auch wieder 10mal ausgegeben werden.
Das geht so weiter bis zum letzten Wert.
Nachdem nun die while-Schleife durchgelaufen ist, soll das Array wieder
von vorne ausgelesen und die Werte wieder mittels Pointer ausgegeben
werden.
Also quasi eine Endlosschleife.
Im AVR-Studio mit avr-gcc wird der Quellcode ohne Fehler compiliert,
aber ich bin mir nicht sicher, ob sich meine Funktionsbeschreibung mit
meinem Code deckt.
Mir ist auch noch aufgefallen, dass am Ende der while-Schleife nicht
wieder in die while-Schleife zurückgesprungen wird und dass das Programm
somit hängen bleibt.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<inttypes.h>
4
#include<stdlib.h>
5
#include<avr/pgmspace.h>
6
#define CLK 3686400
7
8
unsignedchari;
9
unsignedcharArray[10]=
10
{0,1,2,3,4,5,6,7,8,9};
11
12
unsignedchar*ptr;
13
14
intmain(void)
15
{
16
for(;;)
17
{
18
while(ptr<(Array+(sizeof(Array)/sizeof(int))))
19
{
20
for(i=0;i<10;i++)
21
{
22
PORTA=*ptr++;
23
}
24
}
25
}
26
}
Es wäre wohl auch gut einen Timer einzubauen, aber im Moment möchte ich
mich erst einmal mit Arrays und Pointern auseinander setzen!
Vielleicht kann mir jemand bei meinem Problem behilflich sein?!
Es wäre jedenfalls schön, wenn mein Code genau das macht, was meine
Funktionsbeschreibung vorgibt.
Vielen Dank!
Marc L. wrote:
>> unsigned char *ptr;>> int main(void)> {> for(;;)> {
ptr hat zu diesem Zeitpunkt noch keinen Wert, zeigt also
irgendwo hin
> while (ptr < (Array+(sizeof(Array)/sizeof(int))))
wieso sizeof int?
Array ist ein unsigned char Array!
Ich zeig dir weiter unten wie du das besser schreiben kannst,
so dass hier kein Datentyp auftaucht.
> {> for(i=0; i<10; i++)> {> PORTA = *ptr++;
PORTA ist nie auf Ausgang geschaltet worden!
Hier wird bei jedem Durchlauf durch die for Schleife der Pointer
erhöht. Das deckt sich nicht mit deiner Beschreibung dessen was
du erreichen willst.
1
....
2
3
unsignedchar*ptr;
4
5
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
6
7
intmain(void)
8
{
9
DDRA=0xFF;
10
11
for(;;)
12
{
13
ptr=Array;// ptr zeigt auf den Anfang des Arrays
14
15
while(ptr<Array+ARRAY_SIZE(Array))
16
{
17
// den Wert, auf den ptr zeigt, jetzt 10 mal ausgeben
18
for(i=0;i<10;i++)
19
{
20
PORTA=*ptr;
21
}
22
// und ptr auf das nächste Array Element vorschieben
23
ptr++;
24
}
25
}
26
}
Alternativ könnte man die while Schleife auch so formulieren.
Dadurch hat man die Pointer Manipulation(en) an einer Stelle
beisammen ...
1
for(;;)
2
{
3
for(ptr=Array;ptr<Array+ARRAY_SIZE(Array);ptr++)
4
{
5
for(i=0;i<10;i++)
6
{
7
PORTA=*ptr;
8
}
9
}
10
}
11
}
... und es wird die Analogie zu einer Index-basierten Schleife
über ein Array deutlicher
Oh man, ihr seid ja schneller als die Feuerwehr!
Danke für den kurzen Hinweis, Stefan!
Und einen besonderen Dank an Karl heinz Buchegger für die ausführliche
Beschreibung!
>>while (ptr < (Array+(sizeof(Array)/sizeof(int))))>>wieso sizeof int?
Da hast du doch glatt einen Fehler von mir entdeckt!
Ich hatte das Array vom Typ INT auf CHAR geändert, da ich vorerst nur
8bit brauche. Dabei vergaß ich das sizeof(int) zu ändern!
Deine Beschreibung zum Array mit Pointern habe ich mir ausgedruckt, fett
rot eingerahmt und auf meinen Schreibtisch griffbereit hingelegt!
Ich werde mir deine Code-Snippets genau angucken und versuchen zu
verstehen.
Es ist aber im Grunde ganz logisch, wie jede digitale Schaltung ;)
So nebenbei bemerkt, auf ptr++ hätte ich auch drauf kommen können!
Jedenfalls kann ich mich jetzt in das Thema gut einarbeiten und die
Funktion "umschreiben".
Denn am Ende soll ein ADC-Wert eingelesen und an einer bestimmten
Position im Array gespeichert werden (mit Pointer).
Nach der Speicherung des ADC-Wertes soll der gesamte Inhalt des Arrays
10mal hintereinander byteweise am PORTA ausgegeben werden.
Danach erfolgt eine neue Messung am ADC und das Spiel geht weiter, bis
das Array voll ist und wieder von vorne begonnen werden muss.
Ich muss zugeben, dass die finale Funktion anders ist als meine zur Zeit
aufgestellte Funktion, aber irgendwie musste ich in das Thema
einsteigen.
Um Arrays und Pointer verstehen zu können, wollte ich nicht gleich mit
einer komplexen Aufgabe anfangen, sondern mich Stück für Stück an das
Problen rantasten!
Marc L. wrote:
> Nach der Speicherung des ADC-Wertes soll der gesamte Inhalt des Arrays> 10mal hintereinander byteweise am PORTA ausgegeben werden.
NB: Du solltest du nochmal nachhaken. Denn so wie das jetzt
geschrieben ist, kannst du hardwaremässig am Port nicht feststellen,
dass die Ausgabe 10 mal gemacht wurde. Der Port nimmt beim ersten
mal die Pegel an und die restlichen 9 Ausgaben verändern diese
nicht. Im Grunde ist das also äquivalent zu:
einmal ausgeben
eine kurze Wartezeit einlegen.
Ob das das ist, was du haben möchtest, musst du entscheiden.
Sinn macht diese innere Schleife nicht wirklich.
Hallo Karl heinz Buchegger.
> Denn so wie das jetzt> geschrieben ist, kannst du hardwaremässig am Port nicht feststellen,> dass die Ausgabe 10 mal gemacht wurde. Der Port nimmt beim ersten> mal die Pegel an und die restlichen 9 Ausgaben verändern diese> nicht.
So soll es sein!
Man könnte es doch eventuell mit einem Oszilloskop testen, wenn ich neun
Einsen und eine Null in das Array schreibe. Somit müsste doch am PA0
9mal ein High und 1mal ein Low zu erkennen sein?!
Es ist egal, was am ADC anliegt, wenn das Array ausgegeben wird, solange
der Takt hoch genug ist.
> Sinn macht diese innere Schleife nicht wirklich.
Ja, das stimmt schon, aber ich mache noch einen Bogen um die Timer.
Natürlich könnte man anstatt der Schleife eine Zeit einbringen, aber es
sollen alle Werte im Array 10mal hintereinander ausgegeben werden.
Der Timer muss sich auf das gesamte Array auswirken, nicht nur auf die
einzelne Ausgabe.
Darum macht wohl eine Schleife wieder Sinn?!
Ich muss mir jetzt wohl auch Gedanken machen, mit welcher Frequenz ich
den ADC takte.
So wie es scheint, komme ich dann nicht um die Timer herum...
Marc L. wrote:
> Hallo liebe Mikrocontroller-Gemeinde!>> Ich bin gerade dabei mich mit Mikrocontrollern und C zu beschäftigen.> Also seid nicht zu brutal zu mir!
Ich? Waer ich doch niemals ;)
> Ich habe ein Array mit 10 Werten. Es soll der erste Wert des Arrays mit> einem Pointer ausgelesen werden. Dieser Wert soll 10mal am Port A> ausgegeben werden.> Nach dem zehnten Durchlauf soll der zweite Wert im Array genommen werden> und auch wieder 10mal ausgegeben werden.
Was macht das fuer einen Sinn? Wenn Du den selben Wert 10 mal in Folge
ausgibst bewirkt das keine Veraenderung ausser dass Du ueberfluessige
Operationen durchfuehrst.
Was willst Du denn machen, vielleicht faengst besser mal so an.
Lg,
Michael
Marc L. wrote:
> Hallo Karl heinz Buchegger.>>> Denn so wie das jetzt>> geschrieben ist, kannst du hardwaremässig am Port nicht feststellen,>> dass die Ausgabe 10 mal gemacht wurde. Der Port nimmt beim ersten>> mal die Pegel an und die restlichen 9 Ausgaben verändern diese>> nicht.> So soll es sein!> Man könnte es doch eventuell mit einem Oszilloskop testen, wenn ich neun> Einsen und eine Null in das Array schreibe. Somit müsste doch am PA0> 9mal ein High und 1mal ein Low zu erkennen sein?!> Es ist egal, was am ADC anliegt, wenn das Array ausgegeben wird, solange> der Takt hoch genug ist.
Du verstehst mich nicht, oder ich drücke mich schlecht aus.
Ich rede von der inneren Schleife. Dieser hier
1
....
2
for(i=0;i<10;i++)
3
{
4
PORTA=*ptr;
5
}
6
....
Die macht nicht wirklich Sinn. Das könnte man auch so schreiben
1
#include<util/delay.h>
2
3
...
4
PORTA=*ptr;
5
_delay_ms(1);
6
...
(wenn man beispielsweise haben möchte, daß der Werte 1ms am
Port ansteht, bis dann der nächste Wert kommt. Hüte dich
vor selbst geschriebenen Schleifen um irgendwelche Verzögerungen
zu erreichen. In dem Fall hat der Optimizer keine Chance (weil
PORTA eine volatile Variable ist), aber in anderen Fällen
optimiert dir der Compiler solche Schleifen mit Leidenschaft
aus dem Code heraus.
> So wie es scheint, komme ich dann nicht um die Timer herum...
Die meisten Programme haben einen Timer der einen Basistakt
vorgibt. Da wirst du wahrschienlich auch nicht umhin kommen,
dir das mal zu Gemüte zu führen.
Hallo Michael G.
ich wollte eigentlich mein Vorhaben nicht preisgeben, denn es wird
sowieso nicht klappen, wie ich es mir vorstelle...
Trotzdem bin ich guter Dinge und möchte es schwarz auf weiß sehen, ob
mein Vorhaben klappt oder nicht.
Also, ich habe ein analoges Oszilloskop, das mir bei langsamen Signalen
kein ausreichend gutes Bild ausgibt (Punkt statt Strich).
Stellt man die Zeit am Oszi runter, sieht man zwar einen Strich, doch
diese Frequenz ist zu groß, um zum Beispiel eine Ladekurve eines
Kondensators sichtbar zu machen.
Eine Lösung lautet: ein DSO (digitales Speicher-Oszilloskop) kaufen.
Nur ich möchte mir kein weiteres Oszi kaufen, darum habe ich mir
gedacht, ich könnte doch mit dem AVR ein Signal mit dem ADC messen und
es geloopt mittels R2R-Netzwerk wieder ausgeben.
Somit würde ich doch eine langsame Eingangskurve bei hoher Oszi-Frequenz
sichtbar machen?!
-------
Hallo Karl heinz Buchegger,
stimmt, ob ich nun in einer Schleife hintereinander das Selbe ausgebe
oder einfach nur "warte", das ist von der Funktion her das Gleiche.
Und danke für den Hinweis mit dem Umgang selbstgeschriebener Schleifen,
die eine Verzögerung erzeugen sollen!
Also Update der ToDo-Liste: Mit Timern beschäftigen!
Marc L. wrote:
> Hallo Michael G.>> ich wollte eigentlich mein Vorhaben nicht preisgeben, denn es wird> sowieso nicht klappen, wie ich es mir vorstelle...> Trotzdem bin ich guter Dinge und möchte es schwarz auf weiß sehen, ob> mein Vorhaben klappt oder nicht.
Naja das halte ich fuer keine brauchbare Einstellung. Auf der Grundlage
bin ich auch nicht bereit zu helfen, wenn Du Informationen
vorenthaeltst. Auch wenn Du so pessimistisch an die Sache herangehst hat
das wenig Aussicht auf Erfolg.
Trotzdem viel Spass noch.
Michael
Hallo Michael G.,
also, wenn ich keinen Ehrgeiz hätte, würde ich von Anfang an mir ein DSO
zulegen und den AVR zur Seite legen.
Aber ich will mein Vorhaben absolut umsetzen!
Sorry, dass ich so pessimistisch rüberkam, aber ich bekomme halt viel zu
hören, dass meine Vorhaben nicht zu realisieren sind.
Und wenn es doch klappt, bin ich der Einzige, der sich über das Resultat
freut und die "Das geht sowieso nicht"-Sager sehen nicht ein, dass die
sich getäuscht haben.
Die Sache an sich habe ich doch nicht mehr vorenthalten.
Ich möchte mir ein DSO-Vorschaltgerät für ein analoges Oszi
zusammenbauen.
Und um meine Vorstellung umsetzen zu können, muss ich mich mit Pointern
und Arrays beschäftigen.
Das Projekt muss nicht beim ersten Anschalten sofort funktionieren.
Der Reiz liegt dann beim Optimieren!
Ich wollte halt nicht das Thema komplett vorstellen, weil ich erst mit
dem AVR anfange und dieses Thema somit nicht innerhalb eines Tages
fertig zu stellen wäre!
Ich möchte die Zwischenschritte verstehen und nicht einen vorgefertigten
Code bekommen. Das bringt mich auch nicht weiter!
Über kleinere Code-Snippets bin ich sehr dankbar, denn damit kann ich
weiterarbeiten und es hilft mir "Routinen" zu verstehen.
Aber wie schon geschrieben, einen komplett fertigen Code möchte ich
nicht haben.
Also, sorry nochmal!
Wirklich eine super Idee! Wieso soll das nicht klappen? Lass' dir bloß
nichts einschwatzen. Weitermachen!
Wie bereits gesagt: Finger weg von selbstgebauten delay-Schleifen. Dafür
gibts _delay_us und _delay_ms (Optimierung einschalten, am besten -Os)
[1]. Timer sind gut - aber für Verzögerungen etwas overdosed.
[1] http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
Hallo,
vielen Dank für die moralische Unterstützung!
Ich glaube, ich bin der Einzige in meinem Umkreis von 50km, die sich
intensiv mit der Elektronik beschäftigen wollen oder ich kenne nur die
falschen Leute! ;(
// ...warum dann nicht
Ja, warum dann eigentlich nicht? grins
Ich habe mich ein wenig in das Datenblatt des ATmega32 eingelesen
(dieser Mikrocontroller wird damit am Ende beschäftigt) und versuchte
meinen Programm-Code zu erweitern:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
#define nop() asm volatile("nop")
5
#define CLK 3686400
6
7
unsignedcharadc_wert;
8
unsignedchari=0;
9
unsignedcharArray[5]=
10
{0,1,2,3,4};
11
unsignedchar*ptr;
12
13
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
14
#define ARRAY_LENGTH(x) (sizeof(x))
15
16
intmain(void)
17
{
18
DDRA=0xFF;
19
for(;;)
20
{
21
ADMUX=0b01100000;// PA0 -> ADC0, ADLAR=1 (8bit)
22
ADCSRA=0b11000100;// ADC-Vorteiler = 16
23
while(ADCSRA&(1<<ADSC))nop();// noppen, solange noch nicht fertig
24
adc_wert=ADCH;// Ergebnis einlesen (8bit)
25
26
ptr=Array;// ptr zeigt auf den Anfang des Arrays
27
while(ptr<Array+ARRAY_SIZE(Array))
28
{
29
// Hier kommt wohl die ADC-Routine zum Schreiben des Arrays rein?
ptr++;// ptr auf das nächste Array Element vorschieben
35
}// for(i = 0; i < ARRAY_LENGTH(Array); i++ )
36
ptr++;// ptr auf das nächste Array Element vorschieben
37
}// while( ptr < Array + ARRAY_SIZE(Array) )
38
}// for(;;)
39
}// main(void)
Ich muss die Abarbeitung eines Codes verstehen, aber ich denke, das
kommt mit der Zeit.
Wer also Fehler findet, der kann es mir ruhig sagen!
Ich möchte schließlich etwas lernen!
Hhm, und wie ich einen ADC-Wert dem Pointer übergebe und dann an der
bestimmten Stelle im Array speichern soll, weiß ich auch noch nicht so
ganz.
Bestimmt mit
1
*ptr=adc_wert;
???
Jedenfalls ist das noch nicht im Programm implementiert.
Zur Erinnerung, das Programm soll folgendes machen:
Es soll ein ADC-Wert eingelesen und an einer bestimmten
Position im Array gespeichert werden (mit Pointer).
Nach der Speicherung des ADC-Wertes soll der gesamte Inhalt des Arrays
mehrmals hintereinander (entspricht das: verzögert?) byteweise am
PORTA ausgegeben werden.
Danach erfolgt eine neue Messung am ADC und das Spiel geht weiter, bis
das Array voll ist und wieder von vorne begonnen werden muss.
Bin ich schon auf einem guten Weg oder sinkt mein Boot?
Marc L. wrote:
>> ptr = Array; // ptr zeigt auf den Anfang des Arrays> while( ptr < Array + ARRAY_SIZE(Array) )> {> // Hier kommt wohl die ADC-Routine zum Schreiben des Arrays rein?> for(i = 0; i < ARRAY_LENGTH(Array); i++ ) // gesamtes Array ausgeben> {> PORTA = *ptr;> delay_ms(1);> ptr++; // ptr auf das nächste Array Element vorschieben> } // for(i = 0; i < ARRAY_LENGTH(Array); i++ )> ptr++; // ptr auf das nächste Array Element vorschieben> } // while( ptr < Array + ARRAY_SIZE(Array) )
Das kann nicht stimmen. ptr wird da viel zu oft erhöht.
Warum willst du das eigentlich unbedingt mit Pointern machen.
Ist doch Schwachsinn (verzeih dieses böse Wort).
Wenn du durch ein Array durchwillst, dann nimm doch Array Indizes,
also Zugriffe der Art Array[i], und überlass das Optimieren dem
Compiler.
> Hhm, und wie ich einen ADC-Wert dem Pointer übergebe
einem Pointer kann man nichts übergeben.
Ein Pointer ist einfach nur eine Variable, die eine Adresse im
Speicher beinhaltet. So wie eine int Variable eine Variable ist
die eine ganze Zahl speichert.
>> Zur Erinnerung, das Programm soll folgendes machen:> Es soll ein ADC-Wert eingelesen und an einer bestimmten> Position im Array gespeichert werden (mit Pointer).
void foo( int* Ziel )
{
....
*Ziel = adc_wert;
}
int main()
{
int Werte[10];
int i;
for( i = 0; i < ARRAY_SIZE(Werte); ++i )
foo( &Werte[i] );
>> Bin ich schon auf einem guten Weg oder sinkt mein Boot?
Ich denke, du machst dir das unnötig kompliziert. Pointer
benutzt man, wenn man es muss und nicht weil draussen so ein
schöner Tag ist.
Hallo Karl heinz Buchegger.
> Warum willst du das eigentlich unbedingt mit Pointern machen.> Ist doch Schwachsinn (verzeih dieses böse Wort).> Wenn du durch ein Array durchwillst, dann nimm doch Array Indizes,> also Zugriffe der Art Array[i], und überlass das Optimieren dem> Compiler.
Von wollen kann keine Rede sein.
Ich habe mir absolut keine Vorgaben gesetzt, dachte nur, dass Pointer zu
Arrays einfach dazugehören.
>> Bin ich schon auf einem guten Weg oder sinkt mein Boot?> Ich denke, du machst dir das unnötig kompliziert. Pointer> benutzt man, wenn man es muss und nicht weil draussen so ein> schöner Tag ist.
Cooler Spruch, den muss ich mir merken. ;)
Okay, in meinem Fall könnte man also auf Pointer verzichten und auf
Array Indizes zurückgreifen.
Ich mache es mir wirklich kompliziert, da hast du schon Recht.
Du würdest "mein Problem" in 10min lösen können, weil du weiß, was
möglich ist und wie man am effizientesten programmiert.
Davon bin ich noch ein wenig entfernt, leider...
Marc L. wrote:
> Ich mache es mir wirklich kompliziert, da hast du schon Recht.> Du würdest "mein Problem" in 10min lösen können, weil du weiß, was> möglich ist und wie man am effizientesten programmiert.> Davon bin ich noch ein wenig entfernt, leider...
Der springende Punkt ist:
Du hast mit Array Indizes ein absolut taugliches Mittel,
dieses ganze Schleifen-Gedöngs in den Griff zu kriegen.
Pointer machen das keinen Deut einfacher oder übersichtlicher.
Hallo daniel,
vielen Dank für dein kleines Übungsprogramm.
Das muss ich erst einmal auseinander nehmen und Schritt für Schritt für
mich kommentieren.
Am besten ist es, wenn ich mir jetzt wirklich ein gutes C-Buch mit den
Grundlagen zulege!
Und auch vielen Dank an Karl heinz Buchegger.
Nicht jeder hat soviel Verständnis mit einem Anfänger wie ich es nun mal
noch immer bin!
Ich bin gerade nicht zu Hause (hab demnach kein AVR-Studio zum
Compilieren zur Hand) und trotzdem lässt mich das Thema nicht in Ruhe!
Ich habe mein Programm umgeschrieben, aber so langsam wird es echt
peinlich, wenn ich noch immer Fehler im Code habe.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
#define nop() asm volatile("nop")
5
#define CLK 3686400
6
#define ARRAY_LENGTH(x) (sizeof(x))
7
8
unsignedinti=0;
9
unsignedintj=0;
10
unsignedcharadc_wert;
11
unsignedcharArray[5]=
12
{0,1,2,3,4};
13
14
intmain(void)
15
{
16
DDRA=0xFF;
17
for(;;)
18
{
19
ADMUX=0b01100000;// PA0 -> ADC0, ADLAR=1 (8bit)
20
ADCSRA=0b11000100;// ADC-Vorteiler = 16
21
22
for(j=0;j<ARRAY_LENGTH(Array);j++)
23
{
24
while(ADCSRA&(1<<ADSC))nop();// noppen, bis die Umwandlung fertig ist
#define ARRAY_LENGTH(x) (sizeof(x))
Marc ich glaube dich verwirrt dieses Makro
je nach maschine kann sizeof unterschiedliche Werte
für dasselbe Datentyp ausgeben, meistens gilt aber auf einer 32bit
maschine
sizeof(char) = 8
sizeof(short) = 16
sizeof(int) = 32
sizeof(long) = 32
sizeof(long long) = 64
wenn jetzt dein Array aus 5 Elementen besteht, dann
char x[5]; // 5 * sizeof(char) = 5
genau das gibt dir auch sizeof(x) = 5
wie dir hier auffällt kann sizeof sowohl variable
als auch datentyp bekommen.
Aus der Grösse eines Arrays kann man nicht unbedingt auf
die Anzahl der Elemente folgern!
int x[5]; // sizeof(x) => 32*4=128
dh du kannst nicht über 128 Elemente iterieren
for(int i=0; i<sizeof(x); i++) /**/ ;
das schreit nach segmentation fault
also nach speicherzugriffsverletzung
um von der Grösse eines Arrays auf die Anzahl der Elemente
zu kommen, musst du Gesamtgrösse durch Grösse_eines_Elements teilen
sizeof(x)/sizeof(x[0])
x[0] ist das erste Element des Arrays
oder in Makroform
#define SIZE(x) sizeof(x)/sizeof(x[0])
grüsse, daniel
Hallo!
Nach längerer Pause (war und bin eigentlich noch immer beruflich sehr
eingespannt) habe ich mich heute mal wieder kurz an mein Projekt setzen
können und "spielte" wieder ein wenig mit dem AVR-Studio und meinem Code
rum.
daniel wrote:
> #define ARRAY_LENGTH(x) (sizeof(x))> Marc ich glaube dich verwirrt dieses Makro
Vielen Dank für die Info!
Du hast dir echt sehr viel Mühe gegeben mir die "Größenberechnung" von
Arrays näher zu bringen. Und du hast Recht!
Ich habe nicht daran gedacht, dass Elemente im Array ein Byte oder gar
ein Word lang sein können.
Hier nun meine weitere Version des Codes.
Ich bin mir nicht sicher, ob der funktioniert...
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
#define nop() asm volatile("nop")
5
#define CLK 3686400
6
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
7
8
unsignedinti;
9
unsignedintj;
10
unsignedcharadc_wert;
11
unsignedcharArray[5]={0,0,0,0,0};
12
13
intmain(void)
14
{
15
ADMUX|=(1<<REFS0)|(1<<ADLAR);// AVCC w ext. cap at AREF pin, ADC0, ADLAR=1 (8bit)
16
ADCSRA=(1<<ADEN)|(1<<ADPS2);// ADC-Vorteiler = 16
17
DDRA=0xFF;
18
for(;;)
19
{
20
for(j=0;j<ARRAY_LENGTH(Array);j++)
21
{
22
ADMUX=0|(1<<ADLAR);
23
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung durchführen
24
while(ADCSRA&(1<<ADSC))nop();// noppen, bis die Umwandlung fertig ist
Ich bekomme beim Compilieren die Warnung #warning "Compiler
optimizations disabled; functions from <util/delay.h> won't work as
designed".
Wieso bekomme ich denn diese Warnung? Der Pfad zur delay.h stimmt!
Bitte werft ein Auge auf den Code. Könnte der funktionieren?
Jedenfalls das AVR-Studio compiliert mir den Code ohne einen Fehler!
Marc L. wrote:
> Ich bekomme beim Compilieren die Warnung #warning "Compiler> optimizations disabled; functions from <util/delay.h> won't work as> designed".> Wieso bekomme ich denn diese Warnung? Der Pfad zur delay.h stimmt!
Warum die Warnug kommt, steht doch in der Meldung: Du hast die
Compiler-Optimierung nicht aktiviert. Die ist aber für die korrekte
Funktionalität der delay-Funktionen unbedingt erforderlich. Ohne
Optimierung kann erstens das Programm extrem aufgebläht werden, und
zweitens machen die delays nicht das, was Du willst.
hi,
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Taktfrequenz
speziell
Diese funktionieren nur dann korrekt, wenn F_CPU mit der tatsächlichen
Taktfrequenz übereinstimmt. F_CPU muss dazu jedoch nicht unbedingt im
makefile definiert werden. Es reicht aus, wird aber bei mehrfacher
Anwendung unübersichtlich, vor #include <util/delay.h> (veraltet:
#include <avr/delay.h>) ein #define F_CPU [hier Takt in Hz]UL
einzufügen.
es ist keine besonders schöne lösung den makros
aus delay.h die information über vorherzudefinierende
makros mit einem wert zu übergeben .. aber so scheint
avr-gcc es zu handeln^^
grüsse,daniel
Marc L. wrote:
> Bitte werft ein Auge auf den Code. Könnte der funktionieren?> Jedenfalls das AVR-Studio compiliert mir den Code ohne einen Fehler!
Fehler sehe ich jetzt keine. Das nop in der Warteschleife des ADC
kannste aber im Prinzip weglassen. Aber es stört in diesem Fall auch
nicht...
daniel wrote:
> es ist keine besonders schöne lösung den makros> aus delay.h die information über vorherzudefinierende> makros mit einem wert zu übergeben .. aber so scheint> avr-gcc es zu handeln^^
Wie willst Du das sonst machen? Aber an sich ist es richtig, was Du
sagst: F_CPU muss entweder im Makefile oder im Code (und dann vor dem
#include<util/delay.h>) angegeben werden, sonst funktioniert es nicht.
@Johannes
keine Ahnung, viele Möglichkeiten bieten sich ja nicht an
-D option an Compiler übersieht man eher als
#define F_CPU vor dem include.
Ich denke der Weg über eine globale nichtstatische Variable,
die man irgendwo im Code einfügt ist noch schlimmer,
weil diese eventuell mehrmals mit unterschiedlichen Werten
vorkommen könnten und der Linker irgendeine nehmen würde.
Auf jeden Fall etwas nicht gutes. und zum anderen muss es
vielleicht compile-time constante sein, weil delay es so braucht.
(ich kenne die implementierung von delay nicht)
da fällt mir gerade was ein .. was ist wenn ich in a.c
und b.c delay include, aber jeweils andere F_CPU werte eingebe?
ich shcätze ich muss doch die implementierung oder dokumentation
anschauen :)
es war kein Vorwurf von mir an avr-gcc, tut mir leid wenn
es so rüberkam ;)
grüsse, daniel
Guten Tag!
Johannes M. wrote:
>> Marc L. wrote:>> Bitte werft ein Auge auf den Code. Könnte der funktionieren?> Fehler sehe ich jetzt keine. Das nop in der Warteschleife des ADC> kannste aber im Prinzip weglassen. Aber es stört in diesem Fall auch> nicht...
Vielen Dank! Das nop könnte ich wirklich weglassen, stört mich aber
auch nicht! :)
Johannes M. wrote:
>> Marc L. wrote:>> Ich bekomme beim Compilieren die Warnung #warning "Compiler>> optimizations disabled; functions from <util/delay.h> won't work as>> designed".>> Wieso bekomme ich denn diese Warnung? Der Pfad zur delay.h stimmt!> Warum die Warnug kommt, steht doch in der Meldung: Du hast die> Compiler-Optimierung nicht aktiviert.
Ach, okay, danke! Ich hatte zwar den Takt angegeben gehabt und bekam
beim compilieren folgende Meldung:
avr-gcc.exe -mmcu=atmega32 -Wall -gdwarf-2 -DF_CPU=3686400UL -O0
-fsigned-char -MD -MP -MT DKO.o -MF dep/DKO.o.d -c ../DKO.c
Ich wusste nicht, dass die Delay-Funktion eine Optimierung braucht.
Zum Testen wollte ich den Code eigentlich nicht optimieren, aber wenn es
nicht anders geht...
Stelle ich nun die Optimierung auf -Os, so bekomme ich keine Warnung
mehr.
Danke für die Info!
Mir ist aber aufgefallen, dass bei meinem Takt von 3.6864MHz der µC
keine 1ms wartet, sondern nur 0,92ms.
daniel wrote:
> F_CPU muss dazu jedoch nicht unbedingt im> makefile definiert werden. Es reicht aus, wird aber bei mehrfacher> Anwendung unübersichtlich, vor #include <util/delay.h> (veraltet:> #include <avr/delay.h>) ein #define F_CPU [hier Takt in Hz]UL> einzufügen.
Im Makefile habe ich den Takt zwar angegeben, aber aus Vorsicht könnte
man ja auch folgendes in den Code schreiben:
1
#ifndef F_CPU
2
#define F_CPU 3686400UL
3
#endif
4
5
#include<util/delay.h>
6
#include<avr/io.h>
7
8
...
So, und nun wieder zum eigentlichen Thema...
Ich habe mein Array folgendermaßen angegeben:
unsigned char Array[5] = { 0,0,0,0,0 } ;
Wenn ich jetzt nur unsigned char Array[5]; schreibe, sind dann die
einzelnen Elemente auch Null oder muss ich explizit angeben, dass alle
Elemente am Anfang Null sein sollen?
Das Array wird ja nirgends gespeichert und es sollten die Elemente beim
Einschalten des µC's wieder auf Null gesetzt werden?!
Oder brauche ich auf jeden Fall eine Angabe wie { 0,0,0,0,0 } ?
Marc L. wrote:
> unsigned char Array[5] = { 0,0,0,0,0 } ;> Wenn ich jetzt nur unsigned char Array[5]; schreibe, sind dann die> einzelnen Elemente auch Null oder muss ich explizit angeben, dass alle> Elemente am Anfang Null sein sollen?> Das Array wird ja nirgends gespeichert und es sollten die Elemente beim> Einschalten des µC's wieder auf Null gesetzt werden?!> Oder brauche ich auf jeden Fall eine Angabe wie { 0,0,0,0,0 } ?
Globale Variablen werden automatisch zu 0 initialisiert. Solange Dein
Array global ist, kannst Du Dir die manuelle Initialisierung sparen. Bei
lokalen Variablen hingegen wäre sie erforderlich, wenn gewährleistet
sein soll, dass bei jedem Aufruf der betreffenden Funktion alle Elemente
0 sind.
soweit ich mich rictig erinnern kann
werden globale und static (in der funktion) variablen
mit ihrem default, also 0 initialisiert.
funktionslokale werden nicht initialisiert,
intel c compiler icc tat aber auch dies.
aber c standard deckt es nicht ab.
es reicht aber in deinem fall einfach
char feld[10]={0};
um alle auf 0 zu setzen. wenn ich nicht ganz falsch
liege reicht auch {}; aber die erste geht sicher.
grüsse, daniel
Hallo,
man macht es am besten so, wie es Johannes M. geschrieben hat:
Beitrag "Re: Arrays, Pointer und Schleifen (avr-gcc)"
Denn auf einer WWW-Seite fand ich folgende Info:
Nutzung des SRAM durch avr-gcc:
.bss = Statische und (modul-)globale, initialisierte Daten, die zu 0
initialisiert sind bzw. *keinen Initializer haben (und also auch zu 0
initialisiert werden)*.
Das heiß doch, wenn ich Johannes M. und die Info von der Seite richtige
verstanden habe, dass ein *unsigned char Array[5];* außerhalb der
Funktionen und nach den Includes bzw. Defines ausreichen sollte, um alle
Elemente eine 0 zuzuweisen.
daniel wrote:
> je nach maschine kann sizeof unterschiedliche Werte> für dasselbe Datentyp ausgeben, meistens gilt aber auf einer 32bit> maschine> sizeof(char) = 8> sizeof(short) = 16> sizeof(int) = 32> sizeof(long) = 32> sizeof(long long) = 64
Nein. sizeof(char) ist per definitionem in C immer gleich 1 -- selbst
dann, falls der Datentyp char 16 oder 32 bits umfasst. (Gibt's wohl
auf einigen DSPs, sonst eher nicht.)
Die anderen Werte wären dann für eine gängige 32-bit-Maschine 2, 4, 4,
8.
@Marc L
ja, bei globalen muss man nicht explizit initialisieren.
ich mach meistens
int glob; // = 0
als hinweis für mich oder anderen leser, dass es
nicht unabsichtlich vergessen wurde.
int glob = 0;
sollte aber auch nach .bss gehen, und nicht .data
@Jörg
erwischt ;) .. ich habe in bits gedacht
grüsse,daniel
Jörg Wunsch wrote:
> sizeof(char) ist per definitionem in C immer gleich 1 -- selbst> dann, falls der Datentyp char 16 oder 32 bits umfasst. (Gibt's wohl> auf einigen DSPs, sonst eher nicht.)
1
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
Wenn ich Array[5] als unsigned char definiere, ist dann sizeof(Array) =>
5 * 1 Byte = 5 Byte.
sizeof(Array[0]) wären dann demnach 1Byte.
Bytes statt Bits zu verwenden ergibt folglich Sinn, denn die Schleife
for(j=0; j<ARRAY_LENGTH(Array); j++) soll ja nur 5mal durchlaufen werden
und nicht 40mal! g
Ich hatte vorher auch nicht darauf geachtet.
Danke!
daniel wrote:
> @Marc L> ja, bei globalen muss man nicht explizit initialisieren.> ich mach meistens> int glob; // = 0> als hinweis für mich oder anderen leser, dass es> nicht unabsichtlich vergessen wurde.
Vielen Dank daniel!
Quellcode zu kommentieren macht ja bekanntlich immer Sinn und sollte auf
keinen Fall fehlen, auch wenn es im ersten Moment länger dauert den Code
fertig zu stellen, aber nach ein paar Wochen weiß man selber nicht mehr,
was man gemacht hat und weiß die Kommentare zu schätzen! ;)
Auch für "fremde" Leser sind Kommentare unverzichtbar, das stimmt!
>Ich glaube, ich bin der Einzige in meinem Umkreis von 50km, die sich>intensiv mit der Elektronik beschäftigen wollen oder ich kenne nur die>falschen Leute! ;(
Aus welcher Gegend bist du denn? PLZ?
Rolf Magnus wrote:
>> Quellcode zu kommentieren macht ja bekanntlich immer Sinn>> Mitnichten.
Hä? ;)
Synonyme für mitnichten:
keinesfalls, keineswegs, nicht, ausgeschlossen, längst nicht, nein,
undenkbar, auf keinem Fall, unter keinen Umständen, unter keiner
Bedingung
Matthias Lipinsky wrote:
>>Ich glaube, ich bin der Einzige in meinem Umkreis von 50km, die sich>>intensiv mit der Elektronik beschäftigen wollen oder ich kenne nur die>>falschen Leute! ;(>> Aus welcher Gegend bist du denn? PLZ?
Ich habe eigentlich nur mein Gefühl genannt.
Es kommt mir halt so vor, dass ich mich immer mit Sachen beschäftige,
die Leute in meinem Umkreis kaum interessieren.
Darum habe ich auch keinen "persönlichen" Kontakt zu Leuten, mit denen
ich gemeinsam µC-Schaltungen aufbauen, programmieren und optimieren
kann.
Ich komme aus der Gegend von Salzgitter/Braunschweig (Niedersachsen).
Bernhard R. wrote:
> Und was ist mit TU Braunschzweig / FH Wolfenbüttel... ? Da sitzen doch> einige (Edel-)Bastler.
Wäre eine Möglichkeit, aber da kenne ich keinen.
Kann ja nicht mal so eben dort aufschlagen und mich durchfragen bzw.
nach einer Arbeitsgruppe suchen, oder doch? ;)
Ach, da fällt mir ein, vielleicht sollte ich mal einen Lehrer von mir
fragen, der kennt bestimmt "E-Techniker", die auf diesem Gebiet fit
sind!