2013-07-09 02:45 PM
2013-07-10 04:22 PM
A blind stab at fixing your incomplete code. Might dig out the STM32F3-Discovery later.
volatile unsigned short ADC_Values[3]; // Changed outside program flow
unsigned short adc_pin0;
unsigned short adc_pin1;
unsigned short adc_pin3;
int main(void)
{
/* Configure the ADC clock
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
/* Enable ADC1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
/* Setup SysTick Timer for 1 µsec interrupts */
if (SysTick_Config(SystemCoreClock / 1000000))
{
/* Capture error */
while (1)
{}
}
/*** DMA ***/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_InitStructure.DMA_BufferSize = 3;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Values[0];
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // unsigned short - 16-bit
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
LED_On_color(GREEN);
/* ADC Channel configuration */
/* GPIOC Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* Configure ADC Channel 6,7 and 9 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_StructInit(&ADC_InitStructure);
/* Calibration procedure */
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
/* Insert delay equal to 10 µs */
Delay(10);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET);
calibration_value = ADC_GetCalibrationValue(ADC1);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 3;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel 6,7 and 9 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7Cycles5); // PC.0
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_7Cycles5); // PC.1
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 3, ADC_SampleTime_7Cycles5); // PC.3
// DMA_ITConfig( DMA1_Channel1, DMA_IT_TC, ENABLE ); // Let's not
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
// ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); // Let's not
// NVIC_SetPriority(ADC1_2_IRQn, 0);
// NVIC_EnableIRQ(ADC1_2_IRQn);
ADC_GetConversionValue(ADC1);
/* Start ADC1 Software Conversion */
ADC_StartConversion(ADC1);
/* Infinite loop */
while (1)
{
adc_pin0 = ADC_Values[0];
adc_pin1 = ADC_Values[1];
adc_pin3 = ADC_Values[2];
}
}
2013-07-12 11:43 AM
Thanks it works now perfectly.
2015-10-09 12:28 AM
Hello,
This works perfectly but only one time. I thought that the following configuration ''ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;'' means that the ADC is converting continuosly or that is the theory. If I use only the ADC (without DMA) and one channel, it works, that is, it converts continuosly.However, I need to convert some analog channels continuosly using DMA and I do not achieve my purpose. Furthermore, I need to know when the ADC and DMA have finished a complete transfer. Then, I have added DMA interrupts or ADC interrupts but I achieve the same, only one transfer.Some suggestion?Thank you very much in advance.2015-10-09 04:07 AM
When using the ADC in continuous mode, you don't necessarily need DMA.
You can use the EOS (EndOfSequence interrupt instead). Otherwise, use the DMA in circular mode, not single-shot as in your code:ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
2015-10-13 02:50 AM
Yes, I know that it is not required to use DMA but I think this will be better in terms of time....I have used the Circular Mode and it doesn't work...
Anyway, if I use the EOS interrupt instead of DMA, how can I access to each converted values of the different channels? If I do something like this in the IRQHandler? ADC_ClearITPendingBit(ADC1, ADC_IT_EOS); ADC1ConvertedValue[0] =ADC_GetConversionValue(ADC1); ADC1ConvertedValue[1] =ADC_GetConversionValue(ADC1); ADC1ConvertedValue[2] =ADC_GetConversionValue(ADC1);2015-10-14 12:26 AM
You still need to pick up each value within the EOC interrupt when you use several channels of the same ADC. In difference to other vendor's devices, the STM32 does not employ a FIFO of channel-wise result registers.
But using the the EOS interrupt, you are able to detect when you are finished with one set of values from each channel.>I have used the Circular Mode and it doesn't work...This must be a problem with your code - there do exist working examples. But admittedly, ST's DMA initialisation and usage is not trivial, and the reference manual is not an easy read.
2015-10-14 02:51 AM
Thank you for your response.
My aim is to convert 3 analog signals using 3 channels of ADC1. This code works one time, but I want to convert the signals continuosly. I'm using Nucleo-F334R8 board. This is the code that I am using. #include ''stm32f30x.h''#include ''stm32f3xx_nucleo.h''#define ARRAYSIZE 3volatile uint32_t status = 0;volatile uint32_t i;volatile unsigned short ADC_Val[ARRAYSIZE];NVIC_InitTypeDef NVIC_InitStructure;//create DMA structureDMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;GPIO_InitTypeDef GPIO_InitStructure;int main(void){RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);/* Enable GPIO Clock */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);/* Enable DMA1 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* Enable ADC1 Clock */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);/* Enable the DMA gloabal Interrupt */NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_BufferSize = ARRAYSIZE;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Val[0];DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_Init(DMA1_Channel1, &DMA_InitStructure);// Enable DMA1 Channel Transfer Complete interruptDMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3;//PC 0, 1, 3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); ADC_StructInit(&ADC_InitStructure); /* Calibration procedure */ ADC_VoltageRegulatorCmd(ADC1, ENABLE); ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1) != RESET ); ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular; ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0; ADC_CommonInit(ADC1, &ADC_CommonInitStructure); ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable; //ADC_InitStructure.ADC_ScanConvMode = ENABLE;//the ScanConvMode does not exist in the library I am using ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0; ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable; ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable; ADC_InitStructure.ADC_NbrOfRegChannel = ARRAYSIZE; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel 6, 7 & 9 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_181Cycles5); //PC0 ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_181Cycles5); //PC1 ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 3, ADC_SampleTime_181Cycles5); //PC3 DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); ADC_GetConversionValue(ADC1); /* wait for ADRDY */ while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY)); ADC_StartConversion(ADC1); while (1) { //interrupts does the job }}void DMA1_Channel1_IRQHandler(void){ //Test on DMA1 Channel1 Transfer Complete interrupt if(DMA_GetITStatus(DMA1_IT_TC1)) { //status=1; //Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits DMA_ClearITPendingBit(DMA1_IT_GL1); DMA_ClearITPendingBit(DMA1_IT_TC1); }Some suggestion? Something wrong?Again, thank you very much for your feedback.2015-10-14 06:06 AM
My code is based on the SPL V1.0.1 for the F30x, not sure if that fits for the F334 on your Nucleo board.
However, I think a call to ADC_DMAConfig() is missing:...
ADC_RegularChannelConfig (ADC1, ADC_Channel_4, 2, ADC_SampleTime_181Cycles5);
ADC_DMAConfig (ADC1, ADC_DMAMode_Circular); /* Configure ADC DMA */
ADC_DMACmd (ADC1, ENABLE); /* Enable ADC DMA */
ADC_Cmd (ADC1, ENABLE); /* Enable ADC1 */
while (!ADC_GetFlagStatus (ADC1, ADC_FLAG_RDY)); /* wait for ADRDY */
...
I mean the call to
ADC_DMAConfig (ADC1,ADC_DMAMode_Circular
); BTW, when posting source code, you can employ the ''Format Source Code'' tool in the upper left corner of the toolbar (looking like a broad brush).2015-10-14 07:03 AM
Thank you very much!!!
Your contribution have been very helpful. I thought that withDMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
, the DMA was working in circular mode but not...
The new configuration is working perfectly: .....DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Val[0];
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
// Enable DMA1 Channel Transfer Complete interrupt
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* GPIOC Periph clock enable */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3;//PC 0, 1, 3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_StructInit(&ADC_InitStructure);
/* Calibration procedure */
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET );
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = ARRAYSIZE;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel 6, 7 & 9 configuration*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_601Cycles5); //PC0
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_601Cycles5); //PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 3, ADC_SampleTime_601Cycles5); //PC3
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMAConfig (ADC1, ADC_DMAMode_Circular);
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
ADC_GetConversionValue(ADC1);
/* wait for ADRDY */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY)); ......