Question
STM32F4 ADC1 + ADC3, dual or tripple mode?
Posted on October 14, 2013 at 08:32
Hello,
I want to sample 3 channels on ADC1 and 2 channels on ADC3. Does i have the ADCs to use in dual or tripple mode? The following Code does not work :(/*
Sample Temp, VRef, VBat and ports PF9, PF10 using DMA and
trigger via Timer3 at 2 Hz
*/
#define BUFFERLENGTH 5
static __IO uint16_t ADCConvertedValues[BUFFERLENGTH];
__IO uint8_t g_Valid = 0;
void DMA2_Stream0_IRQHandler()
{
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
g_Valid = 1;
}
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TEIF0) != RESET)
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TEIF0);
}
}
void SENSORS_Init (void)
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Timer3, ADC1 und DMA2 clocks einschalten */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
/* PF9 und PF10 als Analog Eingang */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* Interrupts im NVIC freigeben */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_Init(&NVIC_InitStructure);
/* DMA Aufsetzen */
/* DMA2 Stream0 channel0 Konfiguration */
/* Init auf Standardwerte setzen */
DMA_StructInit(&DMA_InitStructure);
DMA_DeInit(DMA2_Stream0);
/* Kanal 0 */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
/* Adresse des ADC Datenregisters (Quelle) */
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x40012308; // &ADC1->DR;
/* Adresse der Datenstruktur (Ziel) */
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) ADCConvertedValues;
/* Richtung des Transfers */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
/* Länge des Datentransfers */
DMA_InitStructure.DMA_BufferSize = BUFFERLENGTH;
/* Die Quelladresse ändert sich nicht */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/* Die Zieladresse muss sich mit jedem Wert ändern */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/* Größe einer Datenübertragung (Quelle, 16 Bit) */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/* Größe einer Datenübertragung (Ziel, 16 Bit) */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/* Datenübertragungen immer wieder von vorne anfangen */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/* Daten mit hoher Priorität übertragen */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/* Direkte Datenübertragung */
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
/* Don't care, da Fifo abgeschaltet */
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
/* Werte einzeln in Speicher übertragen */
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
/* Werte einzeln vom ADC lesen */
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
/* DMA Initialisieren */
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/* DMA Interrupt aktivieren */
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
/* DMA starten */
DMA_Cmd(DMA2_Stream0, ENABLE);
/* Timer aufsetzen */
// Timer aus
TIM_Cmd(TIM3, DISABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
// Der 16 Bit Timer 3 hängt am APB1 mit 42MHz, Timertakt ist damit 84 MHz
// 84MHz / 7000 (Prescaler) = 12000 Hz
// 12000Hz / 6000 (Period) = 2Hz
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 7000-1;
TIM_TimeBaseStructure.TIM_Prescaler = 6000-4;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
/* TIM3 channel2 configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
/* ADC aufsetzen */
ADC_CommonStructInit(&ADC_CommonInitStructure);
ADC_DeInit();
ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult; // ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; // ADC_DMAAccessMode_Disabled;
/* Delay zwischen 2 Sampling Phasen */
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 Init */
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
/* Kontinuierlich samplen */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
/* Kein Trigger */
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; // ADC_ExternalTrigConvEdge_None;
// ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_CC1;
/* Daten Rechtsbündig ablegen */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 3; // BUFFERLENGTH;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_InitStructure.ADC_NbrOfConversion = 2; // BUFFERLENGTH;
ADC_Init(ADC3, &ADC_InitStructure);
/* ADC1 regular channel18 (VBAT) & channel16 (TempSensor) configuration *****/
// TODO: 480 Cycles erklären und ggf anpassen
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 3, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 1, ADC_SampleTime_480Cycles);
/* Enable VBAT channel: channel18 */
ADC_VBATCmd(ENABLE);
/* Enable TempSensor and Vrefint channels: channel16 and channel17 */
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable DMA request after last transfer (Single-ADC mode) */
// ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
/* Enable STM32_TEMPSENS_ADC_DEVICE EOC interupt. */
//ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
/* Enable ADC1 DMA */
//ADC_DMACmd(ADC1, ENABLE);
//ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC3, ENABLE);
/* Start ADC1 */
//ADC_SoftwareStartConv(ADC1);
}
Martin
#timer #dma #adc1 #adc3