Hallo!
Ich habe vor einigen Wochen ein Programm für einen ATtiny13 entworfen,
dass über den ADC ein Potentiometer ausliest und den erhaltenen Wert
über PWM an eine LED ausgibt. Nun möchte ich das gleiche mit einem
ATmega16 probieren aber auf dem Chip funktioniert es einfach nicht.
(Nur für die die denken: "So ein Idiot, der weiß nicht, dass die
Register, Ports und Pins anders sind." Ich hab natürlich das Programm an
den Chip angepasst!)
Hier noch das Programm für den ATmega16:
Mathias Pichler schrieb:> x=ADCH;
Habe gerade keine Zeit, die ganzen Initialisierungen nachzuprüfen.
Aber mit dieser Codezeile liest du nur die obersten beiden Bits des
Ergebnisses aus.
Versuchs mal mit:
Danke für die Rasche Antwort Chris aber ich hab ADC und ADCW schon
probiert und für dieses Programm, das ja nur ein "Testprogramm" für ein
anderes Projekt ist, ist der ADCH-Wert genau genug.
Mathias Pichler schrieb:> ATmega16 probieren aber auf dem Chip funktioniert es einfach nicht.
Wenn man wenigstens wüßte was es werden soll und was "nicht
funktioniert". Aus dem Programm kann man es wohl nicht entnehmen, da es
da ja wohl "nicht funktioniert".
> (Nur für die die denken: "So ein Idiot, der weiß nicht, dass die> Register, Ports und Pins anders sind." Ich hab natürlich das Programm an> den Chip angepasst!)
Ob du das richtig angepaßt hast können wir auch nicht überprüfen mangels
ursprünglichen Sourcecodes.
> Hier noch das Programm für den ATmega16:
Ohne aussagekräftige Kommentare im Begleittext oder im Programm ...
mache ich auch nicht weiter mit irgendwelchen Überprüfungen (gegen was
auch?)
Eigentlich hast du nur ein nicht funktonierendes Programm gepostet oder
ist es am Ende vielleicht die HW.
Mathias Pichler schrieb:> #define F_CPU 16e6
Wird F_CPU irgendwo in
> #include <avr/io.h>> #include <util/delay.h>
verwendet? Soweit ich weiß ist die nnEm Notation nur für float
und double erlaubt:
format_int.c
1
#include<stdio.h>
2
3
intmain(intargc,char*argv[]){
4
5
printf("%ld\n",16e6);
6
7
return0;
8
}
gcc> format_int.c:5:3: warning: format ‘%ld’ expects argument of type
‘long int’, but argument 2 has type ‘double’ [-Wformat]
$ ./format_int
140725075173912
Nullen mit ODER zu verknüpfen kannst du dir schenken, in diesem Beispiel
wird bei FOC0 der Wert stehen, der im TCCR0-Register an der Stelle von
FOC0 steht, so wirst du ihn nie zu 0 setzen können.
1
x=ADCW;
Da das Ergebniss wird ja nicht verwendet, warum also auslesen? Zeile ist
überflüssig! Besser steht da
1
(void)ADCW
1
x=ADCH;
Macht nur Sinn, wenn man das ADLAR gesetzt ist, also das ADC-Ergebniss
auch nach links schieben lässt. Sonst hat man nur zwei Bit und die sind
mal für so gar nix gut.
nörgel schrieb:
>Wenn man wenigstens wüsste was es werden soll
Die Ansteuerung einer LED über PWM, dimmbar über ein Potentiometer, das
am ADC ausgelesen wird. Der ADC funktioniert in dem Programm nicht.
Funktionierendes Programm für ATtiny13:
while(ADCSRA&(1<<ADSC)){}//Warte bis die Messung abgeschlossen ist
42
(void)ADCW;//Verwerfung des ersten Messwertes
43
44
45
46
47
//Hauptschleife (hoffentlich selbsterklärend[funktion wie Dummy Conversation])
48
while(1)
49
{
50
x=0;
51
ADCSRA|=(1<<ADSC);
52
while(ADCSRA&(1<<ADSC));
53
x=ADCH;//Zuordnung des ADCH wertes an x
54
OCR0=x;//Übernahme des x Wertes von OCR0 (diese schritte sind eigentlich Überflüssig)
55
}
56
}
@Alexander S.: bis jetzt gab es keine Probleme mit der Frequenz weil der
PWM Generator auch von der verwendeten Frequenz abhängt.
@Michael Köhler: alle Tips übernommen
@Dieter: PWM funktioniert
Mathias Pichler schrieb:> @ Fritz Ganter>> Hab ich ausprobiert und es hat nicht geholfen.
Aber ADC wäre zumindest der richtige Registername bei Atmega16, nicht
wie du z.B. geschrieben hast ADCW.
Dann fällt mir grade auf, einmal schreibst du
1
while(ADCSRA&(1<<ADSC)){}
und einmal schreibst du
1
while(ADCSRA&(1<<ADSC));
Sage uns doch bitte, was du dir dabei gedacht hast? Warum diese
unterschiedliche Schreibweise?
1
DDRA|=0b00000000;
Eine ODER-Verknüpfung mit 0 kann keine Bits verändern, warum versuchst
du das immer noch? Die Zeile hat keinen Effekt ausser Prozessorzeit zu
verbraten.
Und dass die LED dunkel bleibt, ich hab mir die PWM-Sachen nicht genau
angeschaut aber du benutzt hat nur das ADCH-Register zum Einstellen der
PWM…also nur 2 von 16 Bits die in OCR0 rein passen. Wie lang ist bzw.
soll deine LED so an sein? Je nach PWM-Mode hast du bis zu 255 Counts,
deine ADC-Auslesetechnik aber führt dazu, dass du nach maximal 4 Counts
schalten lässt.
Vielleicht ist auch dein LED falsch angeschlossen oder kaputt. Schließe
einfach mal ein Oszilloskop an PB3 und schau nach, was der Portpin
macht.
@ Michael Köhler
Dabei habe ich mir gar nichts gedacht sondern nur vergessen die zweite
Wartesequenz zu ändern.
Ich habe jetzt beide abschnitte in
1
while(ADCSRA&(1<<ADSC))//Warte bis die Messung abgeschlossen ist
2
{
3
}
geändert.
Es tut miraußerdem leid, dass ich jedes mal vergesse diese Zuweisung zu
ändern.
->geändert in
1
DDRA=0b00000000;
2
DDRB=0b11111111;
Ich hoffe sie ist jetzt richtig
Bezüglich ADC und ADCW ist kein unterschied, denn im iom16.h File steht:
1
/* Combine ADCL and ADCH */
2
#ifndef __ASSEMBLER__
3
#define ADC _SFR_IO16(0x04)
4
#endif
5
#define ADCW _SFR_IO16(0x04)
6
#define ADCL _SFR_IO8(0x04)
7
#define ADCH _SFR_IO8(0x05)
Soweit ich mir das angesehen habe bedeutet das, dass ADC funktioniert,
wenn es nicht im Assembler Code geschrieben ist, ADCW aber immer
funktioniert.
oder liege ich da falsch???
Die LED funktioniert einwandfrei, denn ich habe jetzt eine Sequenz in
mein Programm eingefügt, bei der jedes mal, wenn das System einen Reset
erfährt einmal kurz hoch- und runter- dimmt(Ich habe die LED richtig
herum eingebaut ;-) )
1
//Testen ob LED funktioniert
2
for(intx=0;x<=255;x++)//Max: 255
3
{
4
OCR0=x;
5
_delay_ms(5);
6
}
7
8
for(intx=255;x>=0;x--)//Max: 255
9
{
10
OCR0=x;
11
_delay_ms(5);
12
}
Damit ist das überprüfen mittels Oszi überflüssig und bewiesen, dass der
PWM-ausgang funktioniert.
Ich lasse das ADC Ergebnis jetzt auch durch vier teilen (,weil wie du
richtig bemerkt hast der PWM-Mode nur 255 schaltstufen kennt der ADC
aber 1024 werte ausgibt)
1
//Hauptschleife (hoffentlich selbsterklärend[funktion wie Dummy Conversation])
2
while(1)
3
{
4
x=0;
5
ADCSRA|=(1<<ADSC);
6
while(ADCSRA&(1<<ADSC))
7
{
8
}
9
x=ADCW;//Zuordnung des ADC wertes an x
10
x/=4;
11
OCR0=x;//Übernahme des x Wertes von OCR0
12
}
Ich hoffe, dass das genügend Infos waren, dass Ihr mir helfen könnt,
denn es funktioniert leider immer noch nicht.
Lg MP
sein?
Lass dir doch mal den ADC Wert per RS Ausgeben. Damit sieht du ob
überhaupt was gewandelt wird.
Zeig mal deine Beschaltung. Nicht das da was fehlt. Läuft der µC mit
16Mhz?
@ Steffen
OMG wie konnte ich das übersehen...
Jetzt Funktioniert es endlich!!
Ich danke dir und allen anderen Leuten, die sich dazu herabgelassen
haben, mir zu helfen.
Vielenvielen Dank an euch alle.
Lg MP
Mathias Pichler schrieb:> OMG wie konnte ich das übersehen...
Mit deinen eigenen Worten gesagt:
Mathias Pichler schrieb:> (Nur für die die denken: "So ein Idiot, der weiß nicht, dass die> Register, Ports und Pins anders sind." Ich hab natürlich das Programm an> den Chip angepasst!)
;-)