Hallo,
Ich kämpfe hier gerade mit dem ADC im STM32F4 (Sourcen anbei).
Ich habe das ADC Beispiel aus den Standardtreibern
(STM32F4xx_StdPeriph_Examples\ADC\VBAT_Measurement) leicht abgewandelt
(kein VBat, sondern PC1 als Analogeingang), aber bei der 2 Konvertierung
wird nie das EOC Bit aktiv -->
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
wird nie fertig :(.
Wär toll wenn mir jemand einen Tipp geben könnte, was ich hier falsch
gemacht habe.
Beste Grüße, Tom
Hallo,
Das hatte ich ursprünglich so (wie in dem StdPeriph ADC Beispiel) hat
aber auch nicht funktioniert :(.
Jetzt noch mal mit ContinuousMode=ENABLE wiederholt --> eine
Konvertierung klappt (EOC wird 1), bei der 2. bleibt EOC 0.
Beste Grüße, Tom
hm...
lass mal die beiden Zeilen in deiner u16 ADCDriver-Funktion weg
wenn du den ContinuousMode=ENABLE hast.
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1,
ADC_SampleTime_15Cycles);
// Start the conversion
ADC_SoftwareStartConv(ADC1);
Im kontinuierlichen Modus muss man das nur 1 mal starten, wenn ich mich
jetzt nicht schwer irre. Ehrlich gesagt rate ich jetzt ins Blaue. Ev.
kennt sich da jemand besser aus.
Hab jetzt deinen Code nicht angeschaut, aber hier mal meine Funkion zum
initialisieren des ADC und die Zum Einlesen eines Channels des ADC3s.
Vielleicht hilft dir das weiter. Ist allerdings ohne DMA!
An den Kommentaren nicht stören die könnten noch falsch sein!
Stefan O. schrieb:> Ach noch was nimm für den ADC einen Impedanzwandler oder Opamp her sonst> hast du damit nur probleme!
Hab ich doch geschrieben mit Opamp :-)
Ok, probiere ich nachher mal aus.
Was den Impedanzwandler angeht: Ich will mit dem ADC nur eine
Akkuspannung messen (nicht aufs mV genau, nur um Tiefentladung zu
verhindern). Der Spannungsteiler hat ca. 5kOhm. Das sollte ich wohl
keine extra Schaltung brauchen, oder?
Thomas Horn schrieb:> @Stefan> Ich habe jetzt deine Kode 1:1 übernommen und trotzdem hängt die> Konvertierung.> Mhhh...
Sicher das da nicht irgendwo anders noch was im Argen liegt? Schon mal
debugger laufen lassen? Viell. hängt dein Programm irgendwo in einer
default interrupt funktion oder so. Check das mal.
Benutze Eclipse CDT, arm-none-eabi-gcc . Breakpoints for und nach dem
while. Wenn ich dann unterbreche, dann steckt der µC in der
ADC_GetFlagStatus. Außerdem sehe ich im ADC1->SR2 bzw ADC3->SR2 das das
EOC nicht hochgeht.
Ich habe sicherheitshalber auch mal alle andere Sachen aus dem Programm
rausgeschmissen, keine Änderung.
Hallo,
Ich habe für die Clock-Einstellung das ST Tool (so ein Excel-sheet)
benutzt.
Naja, Prozessor läuft, Baudraten sind richtig, I2C Zeiten stimmen und in
den Inits werden AHB1 bzw. AHB2 Takte eingestellt.
Und.... die erste Konvertierung funktioniert.
Im SR steht 0x30 , also OVR und STRT sind gesetzt. Könnte das etwas
bedeuten, muss ich die evt. vorher löschen?
Die aktuelle Clock Einstellung kann man übrigens auch auslesen und mit
printf() anzeigen lassen ... ;-)
Hatte das Problem auch. Und zudem das Problem, dass 25MHz statt 8Mhz
eingestellt war im Standard. Wo das printf() dann auch nicht hilft.
Also das gleiche Problem hatte ich auch mal. Ich habe den ADC nicht im
continouous mode laufen gehabt sondern zum einzeln anstossen.
Damit das mehr als nur einmal funktioniert musste ich vor dem erneuten
Startem von ADC und DMA alle Flags löschen:
Erst danach ging es, was etwas merkwürdig ist, da die DMA-Flags garnicht
aktiviert waren und nur für Interrupts gedacht sind die ich auch nicht
genutzt habe.
Ich glaube es kam hauptsächlich auf die DMA-Flags an, die ADC-Flags
wurden nur zur Sicherheit mit gelöscht.
Hallo,
@Ingo
Nein, ich hatte auf den Teil dann erst mal in der SW verzichtet und bin
seitdem nicht mehr zum Testen gekommen.
@Star Keeper
Das wäre ja recht komisch, wenn die DMA Flags diesen Einfluss auf den
ADC haben.
Ich muss im Laufe des Monats mal wieder an den STM32 ran, dann werde ich
das auch mal in meine SW einbauen. Ich melde dann, wie es gewirkt hat.
Beste Grüße, Tom
Achso, wichtig ist das der ADC bereits initialisiert ist bevor man ihn
benutzt. Das ist z.B. nicht der Fall, wenn der ADC durch Timerinterrupts
getriggert wird. Hierzu sollte man sich ein Flag erstellen, welches nach
der ADC-Initialisierung gesetzt wird. Erst wenn das Flag gesetzt ist,
darf man auf den ADC zugreifen.
Ingo
Was bezeichnest Du als "Initialisierung"?
(Einschalten der Clks, GPIO vorbereiten, Modes einstellen...,
oder bereits das Starten eine Wandlung?)
Warum initialisiert man ihn nicht bereits nach dem Hochfahren
des Systems (einmalig)?
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
Gibt es vielleicht etwas wie InitStructureAdc(&InitStructure)?
(bei Windows wird so etwas benutzt)
Oder vielleicht hilft auch einfach ein
memset(&InitStructure, 0, sizeof(InitStructure));
damit die ganzen Felder einen Default-Wert (?) haben?
Helfender schrieb:> Was bezeichnest Du als "Initialisierung"?> (Einschalten der Clks, GPIO vorbereiten, Modes einstellen...,> oder bereits das Starten eine Wandlung?)
Ja, genau das.
Helfender schrieb:> Warum initialisiert man ihn nicht bereits nach dem Hochfahren> des Systems (einmalig)?
Macht man doch
> Ja, genau das.
A oder B?
> Macht man doch
Wenn man den ADC initialisiert, bevor ein Timer überhaupt laufen kann
oder zuschlagen kann, braucht man an dieser Stelle auch nicht
aufpassen oder ein Flag, um sich dies zu merken?
Sollte nicht erst einmal alles vorbereitet werden
und am Schluss gibt es ein "GO", mit dem das System zum Laufen
gebracht wird? Sonst hat man ja eine Unmenge an Fälle, die
man behandeln muss...
Es gibt für jedes Struct der STM32Lib auch eine Funktion die dieses
struct initialisiert. Diese Funktion sollte man natürlich benutzen, wenn
man nicht selber alle Werte setzt. Woher soll die Library denn nun
wissen welche Teile des struct korrekte Werte enthalten und welche
nicht...
Helfender schrieb:> Wenn man den ADC initialisiert, bevor ein Timer überhaupt laufen kann> oder zuschlagen kann, braucht man an dieser Stelle auch nicht> aufpassen oder ein Flag, um sich dies zu merken?
Also ich persönlich initialisiere hier z.B. ein neben einem EAGOGM163,
einen U2270, ein MCP3901, einen Pegelwandler und ein Modem, sowie
diverse Peripherie des Controllers. Beim LCD z.B. läuft der Systick
Timer schon, damit ich schöde Delays sauber einhalten kann. Es war wie
gesagt nur eine Möglichkeit, letztendlich kann das jeder machen wie er
will...
Star Keeper schrieb:> Es gibt für jedes Struct der STM32Lib auch eine Funktion die dieses> struct initialisiert. Diese Funktion sollte man natürlich benutzen, wenn> man nicht selber alle Werte setzt.
Meinst du die DeInit?
Ingo
Hallo Ingo,
Das wäre ja der Hammer. Bei allen anderen Sachen (GPIO, Timer) hatte ich
die xxx_StructInit genutzt, nur beim ADC nicht, da so aus
STM32F4xx_StdPeriph_Examples\ADC\VBAT_Measurement (TrueStudio?) kopiert.
Beste Grüße, Tom