Hallo,
ich besitze ein STK600 und versuche gerade, ein paar kleine Programme zu
schreiben.
Mein jetziges Ziel ist es, einen analogen Pegel auszulesen.
Ich lege an den PIN PF0 eine analoge Spannung. Diese wird intern in
einen 10Bit Wert gewandelt. Die untern 8 Bit sollen an den PORTB
ausgegeben werden.
1
#include<avr/io.h>
2
3
// inernet Takt 128kHz
4
// Port E hat ADC (ADC0) PF0
5
// Ausgänge sind negiert
6
7
8
intmain(void)
9
10
{
11
12
13
#include<avr/io.h>
14
15
// Internet Takt 128kHz
16
// Der ADC ist an PortF angeschlossen, ADC0 --> PF0
17
// Ausgänge des PortB sind negiert
18
19
20
intmain(void)
21
22
{
23
24
ADCSRA=0b11100000;// Free running mode mit Takt: 128/2khz
25
ADCSRB=0b00000000;// Letzen 3 Bits stehen auch für free running mode
26
ADMUX=0b11100000;// Referenz ADLAR und Eingang // ADLAR gesetzt
27
charWert=0xff;
28
DDRB=0b11111111;// Port B ist ein Ausgang 0b11111111 = 0xff
29
30
31
while(1)
32
{
33
Wert=~ADCH;
34
PORTB=Wert;
35
}
36
37
38
return0;
39
}
Dieser Code funktioniert!
Wenn ich jedoch ADLAR ausschalte (Bit --> 0), so dass die untern 8 Bits
in dem Register ADCL stehen sollten und ich schreibe:
1
while(1)
2
{
3
Wert=~ADCL;
4
PORTB=Wert;
5
}
Dann funktioniert das Programm nicht mehr!
Aus irgendeinem Grund kann ich nur das Register ADCH und nicht das
Register ADCL auslesen. Hat jemand hierfür eine Erklärung?
Der Grund dafür ist im Datenblatt erklärt:
When ADCL is read, the ADC Data Register is not updated until ADCH is
read
Also einfach einen Dummy-Read von ADCH hinterher machen, oder ADCW lesen
und nur die unteren 8Bit verwenden.
>Der Grund dafür ist im Datenblatt erklärt:>When ADCL is read, the ADC Data Register is not updated until ADCH is>read
Danke!
Wenn ich danach suche, dann finde ich das auch.
Habe irgendwie nur bis zur Grafik geschaut.
>oder ADCW lesen und nur die unteren 8Bit verwenden.
Hast du einen Vorschlag, wie man das etwas einfacher machen kann?
>Tip für später:>außerdem könntest du auch noch warten bis der neue Wert gewandelt wurde>(oder einen Interrupt verwenden)
Danke,
das warten habe ich schon eingebaut.
In Interrupts muss ich mich beim Atmega noch einlesen.
1
#include<avr/io.h>
2
3
// Internet Takt 128kHz
4
// Der ADC ist an PortF angeschlossen, ADC0 --> PF0
5
// Ausgaege des PortB sind negiert
6
7
8
intmain(void)
9
10
{
11
12
ADCSRA=0b11100000;// Free running mode mit 128/2khz
13
ADCSRB=0b00000000;// Letzen 3 stehen auch für free running mode
14
ADMUX=0b11000000;// Referenz ADLAR und Eingang // ADLAR nicht gesetzt
15
DDRB=0b11111111;// Port B ist ein Ausgang 0b11111111 = 0xff
A. R. schrieb:>>oder ADCW lesen und nur die unteren 8Bit verwenden.>> Hast du einen Vorschlag, wie man das etwas einfacher machen kann?
Frag dich ganz einfach, wozu du eigentlich in deinem Code die Variable
s_Wert brauchst.
A. R. schrieb:> if((ADCSRA & 0b00010000)==0b00010000)
wenn statt kryptischer Bitfolgen die bekannten Konstanten verwendest,
ist das Programm für Dich und vor allem auch andere leichter
verständlich
du schreibst ja auch nicht anstatt ADCSRA irgendeine Zahl hin
Für mich wars so einfacher, weil ich genau weiß, welches Bit gemeint
ist. Währe bei 2^5 (32) wohl auch erstichtlich gewesen.
Aber dies ist wohl eher die Preferenz des jeweiligen Programmierers.
Kann es sein, das GCC nicht mit Arrays arbeiten kann?
Folgender Code wird bei mir komplett übersprungen.
> if((ADCSRA & 0b00010000)==0b00010000)
kann man auch so schreiben:
if (ADCSRA & (1<<ADIF))
oder so:
if (ADCSRA & _BV(ADIF))
ist so denke mal viel leserlicher, oder ?
A. R. schrieb:> Für mich wars so einfacher, weil ich genau weiß, welches Bit gemeint> ist. Währe bei 2^5 (32) wohl auch erstichtlich gewesen.
Davon war aber auch nicht die Rede!
Jedes Bit hat einen Namen! Der wird im Datenblatt verwendet und durch
die Header Files ist dieser Name auch für dein C-Programm verfügbar.
Die meisten Programmierer wollen nämlich gar nicht wissen, welche
Bitnummer abgefragt wird, der symbolische Name ist völlig ausreichend.
Das hat dann auch den Vorteil, dass der Compiler die Anpassung vornimmt,
wenn dieses Bit bei einem anderen Prozessor zwar an anderer Stelle aber
noch im gleichen Register beheimatet ist. Der Programmierer muss sich
dann nicht darum kümmern.
> Kann es sein, das GCC nicht mit Arrays arbeiten kann?
Ehe wir hier weitermachen:
In 99.999% aller Fälle, in denen Programmierer den Compiler eines
Fehlers bezichtigen, stellt sich hinten nach raus, dass die Kentnisse
der Programmierer lückenhaft, wenn nicht gar fehlerhaft sind.
Also: Ehe du den Compiler eines Fehlers bezichtigst, stell sicher, dasss
nicht du der mit dem Fehler bist.
>> Folgender Code wird bei mir komplett übersprungen.>>
1
>chararray[100];
2
>inti=0;
3
>while(i<100)
4
>{
5
>array[i]=0;
6
>i++;
7
>}
8
>
Der Compiler kann ja auch rausgefunden haben, dass der Nettoeffekt darin
besteht, dass Array komplett auf 0 zu setzen. Und der Compiler mag dafür
bessere, schnellere Methoden haben, als das was du da hingeschrieben
hast. Im Debugger siehst du dann keine 1 zu 1 Korrelation mehr zwischen
den abgearbeiteten Anweisungen und dem was auf dem µC tatsächlich
passiert. Solange das Endergebnis aber dasselbe ist, darf der Compiler
das.
>>if (ADCSRA & (1<<ADIF))>>oder so:>>if (ADCSRA & _BV(ADIF))>>ist so denke mal viel leserlicher, oder ?
Danke für den Hinweis.
>Die meisten Programmierer wollen nämlich gar nicht wissen, welche>Bitnummer abgefragt wird, der symbolische Name ist völlig ausreichend.>Das hat dann auch den Vorteil, dass der Compiler die Anpassung vornimmt,>wenn dieses Bit bei einem anderen Prozessor zwar an anderer Stelle aber>noch im gleichen Register beheimatet ist. Der Programmierer muss sich>dann nicht darum kümmern.
Klingt logisch!
Also sind für die Namen wie DDB0, DDB1, ADLAR etc. die jeweiligen
Wertigkeiten hinterlegt. Bzw. die Wertigkeit n-1. Also für ADIF (2^5)
ist eine 4 hinterlegt.
>Also: Ehe du den Compiler eines Fehlers bezichtigst, stell sicher, dasss>nicht du der mit dem Fehler bist.
Da hast du vollkommen recht!
Deswegen habe ich hier nachgefragt, ob GCC arrays beherrscht bzw. wo der
Fehler sein könnte.
Ich habe nun folgendes Programm erstellt.
Es soll eine 2 Dimensionale Matrix mit der Größe 3600Bytes erstellt
werden.
1
#include<avr/io.h>
2
intmain(void)
3
{
4
chararray[360][10];
5
for(inti=0;i<360;i++)
6
{
7
for(intk=0;k<10;k++)
8
{
9
array[i][k]=0x7E;
10
}
11
}
12
return0;
13
}
Beim offline Debugging überspringt er die komplette Schleife.
Meinst du, dass der Compiler so intelligent ist?
Der Compiler ist so intelligent!
Wenn später nicht auf das Array zugreife, so wird es erst gar nicht
angelegt.
Wenn ich später eine Abfrage ergänze so klappt alles wie gewollt.
Eine eigene Frage?
Dieser Thread ist über 15 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.