Ein STM32F1xx würde ich mal sagen. Aber wer das am Code nicht
erkennt wird die Frage kaum beantworten können ;)
Die Pinzuordnung steht im Datenblatt (nicht das "Reference Manual")
unter "Pinouts and pin assignment". Beim STM32F100 ist das Kapitel 3.
Such mal nach z. B. "ADC1_IN4".
Interessant an dieser "Peripherial Lib" finde ich das jeder
STM32 Fan sie einerseits lobt (leichter Einstieg usw.), sie
andererseits aber kaum verwendet wird. So ist zumindest mein
Eindruck.
Welcher Pin zu welchen Kanälen gehört findet man im Datasheet:
ADC_Channel_11: PC1
ADC_Channel_12: PC2
ADC_Channel_13: PC3
Hinter PA3/4/5 stecken ADC_Channel_3/4/5
Datasheet Seite 27:
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00220364.pdf
Du hast also die Falschen kanäle eingelesen/die Falschen pins
Konfiguriert.
btw. Ein grauenhaftes Datenblatt/User Manual...Sehr unübersichtlich und
die Pin Configuration ist im User Manual gar nicht zu finden. Zumindest
habe ich sie nicht gefunden.
Ulf schrieb:> ich kann ich Datanblatt und der CMSIS Lib nicht nachvollziehen, wie man> einen GPIO-Pin eines beliebigen Ports mit einem ADC-Kanal verbindet.
Soweit mir erinnerlich tut man das überhaupt nicht, das hat ST für dich
schon erledigt. Nur eben nicht "beliebig", sondern ein bestimmter
ADC-Kanal sitzt auf einem bestimmten Portpin.
Antwort schrieb:> btw. Ein grauenhaftes Datenblatt/User Manual...Sehr unübersichtlich und> die Pin Configuration ist im User Manual gar nicht zu finden. Zumindest> habe ich sie nicht gefunden.
Apropos übersichtlich: Seit sie die Webseite neu definiert haben finde
ich nicht einmal mehr die Datasheets wieder. In der Reference können die
Pinout allerdings auch nicht drinstehen, die sind immerhin
modellspezifisch.
Man muss schon einiges virtuelle Papier zusammenkratzen um die ganze
Doku zu haben: Reference, Datasheet, Programming Manual und das vom
Cortex.
A. K. schrieb:> Apropos übersichtlich: Seit sie die Webseite neu definiert haben finde> ich nicht einmal mehr die Datasheets wieder. In der Reference können die> Pinout allerdings auch nicht drinstehen, die sind immerhin> modellspezifisch.>> Man muss schon einiges virtuelle Papier zusammenkratzen um die ganze> Doku zu haben: Reference, Datasheet, Programming Manual und das vom> Cortex.
Hm, also die Aufteilung gefällt mir überhaupt nicht. Da Lobe ich mir die
User Manuals von NXP/Atmel. Da steht immer alles in einem Dokument und
ist auch auf der Seite elicht zu finden.
Aber das hat mit dem Problem des Thread-Autors nichts zu tuen. Daher
würde ich diese Absschweifung gerne an dieser Stelle beenden und zum
eigentlich Problem zurückkehren.
Leute! Super geil!
Ich bin auch total am verzweifeln mit diesem - tschuldigung -
DRECKS-MANUAL.
Jeder Atmega hat ein bessere Doc. Bin bisher mit der Doku von Freescale
(S12X...) ganz gut ausgekommen und kann mich mit der von ST nich
anfreunden.
Vielen lieben Dank und einen schönen Abend euch.
Ulf
P.S.: der Oberwitz ist ja, dass dieses im Vergleich zum "Reference
Manual" sehr sinnvolle Dokument nicht mal einen anständigen Namen hat,
sodass man es chance hätte es wieder zu finden. Ich muss es jetzt unter
"STM32F107xx.pdf" speichern...
---> Und die Hompepage von ST ist an Unübersichtlichkeit kaum zu
übertreffen. Grauenhaft.
bye
So, jetzt habe ich meine ganzen ADC Einstellungen hinter mir.
Mein System zur Motorsteuerung hat ein Shunt, an dem ich zweimal pro PWM
zyklus per Injection die Spannung messen möchte, und 5 weitere Kanäle,
die einfach im autoscan-mode gewandelt werden sollten.
Die Injections starte ich ja per Software durch den Befehl:
ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);
Bekomme ich dann sofort nach Ende der ersten Conversion einen Interrupt,
oder erst wenn beide Messungen durch sind? Ich habe gelesen, dass man
den DMA-Controller nutzen muss... stimmt das? Muss ich da aktiv was
machen oder ist dieser per default aktiv?
mein ADC-Interrupt sieht im Moment so aus:
ADC_ClearFlag(ADC1, ADC_FLAG_JEOC);
Shunt_Messung1 =
ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
Shunt_Messung2 =
ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2);
Bei der regular channels muss ich doch bestimmt noch ein paar Befehle
ausführen um die Conversion zu starten, oder?
Und wie mache ich den Zugriff auf die kontinuierlich gewandelten
Messwerte? Würde diese gerne im Pollingmodus abholen.
Anbei aktueller Code zur Initialisierung der ADC Kanäle nach dem Studium
des "guten" Dokuments...
/* Configure ADC */
/* enable ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
RCC_APB2Periph_ADC1, ENABLE);
/* ADC Channel Mapping Port A
Pin A1: Onboard Poti --> ADC Channel 1
Pin A3: U_Shunt --> ADC Channel 3
Pin A6: U_DC_BUS --> ADC Channel 6
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC Channel Mapping Port B
Pin B0: Current Phase A --> ADC Channel 8
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* ADC Channel Mapping Port C
Pin C4: Temperature LOW SIDE --> ADC Channel 14
Pin C5: Current Phase B --> ADC Channel 15
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure ADC1 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 5;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_InjectedSequencerLengthConfig(ADC1, 2);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 1,
ADC_SampleTime_7Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 2,
ADC_SampleTime_7Cycles5);
/* ADC1 injected external trigger configuration */
ADC_ExternalTrigInjectedConvConfig(ADC1,
ADC_ExternalTrigInjecConv_None);
/* Enable ADC1 JEOC interrupt */
ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration */
while (ADC_GetResetCalibrationStatus(ADC1) == SET) ;
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while (ADC_GetCalibrationStatus(ADC1) == SET) ;
/* Start ADC1 Software Conversion */
ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the ADC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
Danke für die Mithilfe und guten Abend!
dann den Wert von "ADC_FB_VOLTAGE" oder von dem ADC_Channel_1 ? Also
bezieht sich der Index der InjectedChannel auf das Ranking der CHannels
oder muss man das noch irgendwo mappen?
bekommst du denn Wert von ADC_FB_VOLTAGE.
Allerdings habe ich auch eine Frage zu:
Ulf schrieb:> ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 1,> ADC_SampleTime_7Cycles5);> ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 2,> ADC_SampleTime_7Cycles5);
Funktioniert das bei dir wenn du zwei InjectedChannel auf den gleichen
ADC_Channel definiert? Bei mir funktioniert die Messung zwar, allerdings
bekomme ich dann immer Ergebnisse die sehr nahe beieinander liegen
obwohl sie völlig verschieden sein sollten. Und da nirgends definitiv
steh ob das geht oder nicht bin ich mir unsicher.
Vielen Dank für die Hilfe und viele Grüße
Michael