Guten Morgen zusammen,
ich bin gerade auf der Suche nach einer etwas ausführlicheren
Beschreibung der ADCs des STM32F103, als es das Reference Manual RM0008
bieten kann. Mein Anwendungsfall ist folgender:
Ich habe eine PWM mit einer Pulslänge von 2-80µs und einem Duty Cycle
von maximal 30%, d.h. nach jedem Puls ist mindestens 4µs Zeit.
Ich will einen ADC-Kanal während des Pulses so oft wie möglich abtasten.
In der Pause danach ist ja genügend Zeit, das zu verarbeiten. Weiter
will ich die Pause nutzen, um noch mehrere andere ADC-Kanäle abzutasten,
bei denen mir die Abtastrate fast egal ist (OK, 10Hz sollten es schon
mindestens sein).
Vermutlich brauche ich also zwei Interrupt-Routinen in der PWM, die den
ADC zwischen einem interleaved-Messen beider ADCs mit DMA für die
schnellen Kanäle und dem langsamen einzelnen Samplen der langsamen
Kanäle umschalten.
Leider habe ich noch keine schöne Beschreibung der Nutzung dieser Modi
gefunden. RM0008 zeigt zwar schön, was geht, aber ich verstehe noch
nicht, wie man es benutzt.
Viele Grüße
W.T.
Gibt es keine übersichtlichere Dokumentation der ADC-Funktionen als die
"stm32f10x_stdperiph_lib_um.chm" ? Da muß man nach jedem Parameternamen
den Quelltext mit dem RM0008 vergleichen oder Googlen, wenn man nicht
sicher ist, ob er nur das bedeutet, was der Name suggeriert.
OK, wenn hier keine sinnvollen Antworten kommen, dokumentiere ich das,
was ich finde mal selbst - für den Fall, daß jemand per Google
hierhingestoßen wird, weil er dasselbe sucht.
Eine gut lesebare Übersicht über die ADC-Modi liefert die Application
Note AN3116 "STM32's ADC modes and their applications". Damit kennt man
die Namen, die ST benutzt.
Damit wiederum ist dann in der "stm32f10x_stdperiph_lib_um.chm"-Doku das
Beispiel "STM32F10x_StdPeriph_Examples/ADC/3ADCs_DMA/main.c" ganz gut
lesbar.
In fast allen ADC-Beispielen mit DMA steht das folgende Define:
1
#define ADC1_DR_Address ((uint32_t)0x4001244C)
Was bedeutet diese Adresse? Man kann sich in der stm32f10x.h
entlanghangeln zu:
PERIPH_BASE ->
APB2PERIPH_BASE ->
ADC1_BASE + 0x4C
Aber was ist der Offset von 4C?
> Aber was ist der Offset von 4C?
Abschnitt 11.12.13 im REF-2011
ADC injected data register x (ADC_JDRx) (x= 1..4)
Address offset: 0x3C - 0x48
Bits 31:16 Reserved, must be kept at reset value.
Bits 15:0 JDATA[15:0]: Injected data
These bits are read only. They contain the conversion result from
injected channel x. The data is left or right-aligned as shown in Figure
27 and Figure 28.
Danke für die Antwort. Allerdings bin ich jetzt etwas aufgeschmissen.
Ich war bis jetzt davon ausgegangen, den Regular Mode mit DMA zu nutzen.
Momentan sieht mein Plan (mit noch nicht ganz der Zielfunktionalität) so
aus, alle Kanäle per DMA in ein Array zu bringen und nach der Wandlung
des letzten Wertes per Interrupt zur Weiterverarbeitung zu kopieren. So
habe ich zwar noch nicht die ganze maximale ADC-Rate, aber immerhin
schon ein Viertel. Sozusagen zum kennenlernen.
Ist doch auch möglich
11.12.14 ADC regular data register (ADC_DR)
Address offset: 0x4C
RM0008 Seite 247...
ja ist ein wenig verwirrend, aber es geht schon.
Viel Erfolg
Gruß Ert
Nils P. schrieb:> 0x4C
Stimmt, das hatte ich überlesen. Aus irgendeinem Grund funktioniert das
Ganze allerdings noch immer nicht; aus dem struct gls_adc werden alle
Werte als 0 ausgelesen.
Und beim zweiten Aufruf von edm_adc_init() bleibt sie in einer
Endlosschleife hängen.
OK, den DMA1-Clock hatte ich vergessen. Und in keinem Tutorial finde ich
noch eine extra-Aktivierung der Interrupts. Dummerweise funktioniert der
IRQ immer noch nicht.
Die ADC-Wandlung läuft und der IRQ für die fertige Wandlung wird mit der
richtigen Taktfrequenz aufgerufen.
Vorher hatte ich einige Fehler gemacht: Es wird nicht der ADC-Interrupt
sondern der DMA-Interrupt gebraucht.
Durch die Display-Darstellung sieht man, daß das Array
"ADC1ConvertedValues[10]" mit plausiblen Werten gefüllt wird. Allerdings
ergeben sich beim Kopieren in das struct "gls_adc" im
DMA1_Channel1_IRQHandler total inplausible Werte - so als hätte das
Array zum Zeitpunkt des IRQs komplett andere Werte, als wenn es in der
Hauptschleife aufgerufen wird. Wird im IRQHandler der Wert hart gesetzt
(z.B. gls_adc.tOn = 3;) stimmt alles.
"gls_adc" ist wie folgt deklariert und definiert:
Es ist wie verhext. Der IRQ-Handler scheint sehr empfindlich gegenüber
Veränderungen zu sein: Werden zwei zusätzliche Variablen "gl_a" und
"gl_b" einkommentiert, hängt sich das Programm auf. Der Inhalt des
globalen Structs "gls_adc" scheint nichts mit dem Inhalt von
ADC1ConvertedValues zu tun zu haben (siehe obiges Bild);
Warum steht in "gl_a" 19? Nirgendwo wird hineingeschrieben, die Variable
kommt in keiner anderen Datei vor und globale Variablen werden implizit
mit 0 initialisiert. Es sieht aus, als wären in den IRQ-Handlern Reste
vorheriger Builds - oder als ob Zeiger marodierten.