Hello I’m new to the STM32 world and I’m making some experiments with the STM32F4 Discovery Board.
I would like to measure the VBAT and Temperature sensor signals using the ADC1 and the DMA, continously scanning both the channels. The results I obtain are quite in the expected values …but I can see no significant changes for example varying the temperature applied to the microcontroller case. I suspect that the ADC stops the conversions or the DMA stops the transferring. I’m getting slightly insane with the ADC and DMA initialization. I use the STM32F4xx DSP and Standard Peripherals Library and the MDK 4.6 32K Version (for the moment, then I will buy the complete license). Is there anybody willing to give me some advice? Here below you will find the code I use.
Thank you Antonio (Milano - Italy)
/* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define ADC1_DR_ADDRESS ((uint32_t)0x4001204C) #define V25 0.760 #define AVG_SLOPE 25.0 #define BUFFERLENGHT 2 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ __IO uint16_t ADC1ConvertedValue[BUFFERLENGHT]; __IO uint32_t ADC1ConvertedVoltage0 = 0; __IO uint32_t ADC1ConvertedVoltage1 = 0; __IO float Vsense = 0.0; __IO float TCelsius = 0.0; __IO float VBATVoltage = 0.0; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ void ADC1_DMA_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; /* Enable ADC1, DMA2 clocks *************************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* DMA2 Stream0 channel0 configuration **************************************/ DMA_DeInit(DMA2_Stream0); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = BUFFERLENGHT; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); /* ADC Common Init **********************************************************/ ADC_DeInit(); ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC1 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = 0; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = BUFFERLENGHT; ADC_Init(ADC1, &ADC_InitStructure); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* ADC1 regular channel18 (VBAT) & channel16 (TempSensor) configuration *****/ ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_480Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, 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); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); } int main(void) { SystemCoreClockUpdate(); /* Get Core Clock Frequency */ if (SysTick_Config(SystemCoreClock / 1000)) { /* SysTick 1 msec interrupts */ while (1); /* Capture error */ } /* ADC1 Channel Temperature Sensor & VBAT measurement configuration */ ADC1_DMA_Config(); /* Start ADC1 Software Conversion */ ADC_SoftwareStartConv(ADC1); while (1) { /* The VBAT pin is internally connected to a bridge divider by 2 */ ADC1ConvertedVoltage1 = (uint32_t)(ADC1ConvertedValue[0] * 2) * 3300 / 0xfff; VBATVoltage = (float)(ADC1ConvertedVoltage1 / 1000.0); ADC1ConvertedVoltage0 = (uint32_t)(ADC1ConvertedValue[1] * 3300 / 0xfff); Vsense = (float)(ADC1ConvertedVoltage0 / 1000.0); TCelsius = ((Vsense - V25) / AVG_SLOPE) + 25.0 ; } }