2014-04-16 05:26 PM
I finally got ADC to work, so I went overboard and enabled 6 adc channels plus the temp, vref and vbat all on ADC1. Problem is when its running my data coming out of dcmi seems to get garbled.
I know its the ADC because if I disable the ADC clock the DCMI output has no issues. So I'm wondering what happens if there are two dma requests on DMA2 ? ADC1 DMA2,STR0,CH0 DCMI DMA2,STR1,CH1 Is there anything I can do to avoid this ? Can I slow down the ADC conversion more so it has less chance of conflicting ?void initADC()
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)&ADC1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&mygVars->ADCIN1;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 9;
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_Low;
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);
/* Configure ADC3 Channel12 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 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 = 9;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC3 regular channel12 configuration *************************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 7, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 8, ADC_SampleTime_15Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 9, ADC_SampleTime_15Cycles );
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC3 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC1, ENABLE);
Delay(100);
ADC_SoftwareStartConv(ADC1);
}
2014-04-16 07:12 PM
Well after looking at my garbled video for a while I thought maybe I could forgo the whole DMA option (all though I like it!) and jut int on completion of conversion. Any Idea how I could do that. I dont know how I can tell which channel has been converted ? This code below does not seem to work all of the samples change too much.
void initADC(int level)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
int adcChannels = 9;
DMA_Cmd(DMA2_Stream0, DISABLE);
while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE)
{
Delay(1);
}
ADC_Cmd(ADC1, DISABLE);
Delay(10);
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/
/*DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)&ADC1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&mygVars->ADCIN1;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = adcChannels;
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_Low;
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);*/
/* Configure ADC3 Channel12 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 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 = adcChannels;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC3 regular channel12 configuration *************************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 7, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 8, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 9, ADC_SampleTime_480Cycles );
//ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC3 DMA */
//ADC_DMACmd(ADC1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC1, ENABLE);
Delay(100);
ADC_SoftwareStartConv(ADC1);
}
void ADC_IRQHandler(void){
static int i=0;
if(ADC_GetITStatus(ADC1, ADC_IT_EOC))
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
Samples[i%9]=ADC1->DR;
i++;
}
}
2014-04-17 08:53 AM
Check the errata, other people have reported DMA issues as I recall
2014-04-18 07:58 AM
I went down this path, it seems to be almost working. Just the tmp/vbat/vref dont seem right. I'll look for errata.
void ADC_IRQHandler(void){
static int i;
if(ADC_GetITStatus(ADC1, ADC_IT_EOC))
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
Samples[i%9]=ADC1->DR;
i++;
switch(i%9){
case 0:
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles );
break;
case 1:
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_480Cycles );
break;
case 2:
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_480Cycles );
break;
case 3:
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_480Cycles );
break;
case 4:
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_480Cycles );
break;
case 5:
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_480Cycles );
break;
case 6:
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles );
break;
case 7:
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_480Cycles );
break;
case 8:
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 1, ADC_SampleTime_480Cycles );
break;
}// end switch
ADC_SoftwareStartConv(ADC1);
}
}
2014-04-18 01:26 PM
Yes Clive your exactly right (as usual). The errata states
2.1.10 DMA2 data corruption when managing AHB and APB peripherals in a concurrent way Description When the DMA2 is managing AHB Peripherals (only peripherals embedding FIFOs) and also APB transfers in a concurrent way, this generates a data corruption (multiple DMA access). When this condition occurs: • The data transferred by the DMA to the AHB peripherals could be corrupted in case of a FIFO target. • For memories, it will result in multiple access (not visible by the Software) and the data is not corrupted. • For the DCMI, a multiple unacknowledged request could be generated, which implies an unknown behavior of the DMA. AHB peripherals embedding FIFO are DCMI, CRYPTO, and HASH. On sales types without CRYPTO, only the DCMI is impacted. External FIFO controlled by the FSMC is also impacted. Workaround Avoid concurrent AHB (DCMI, CRYPTO, HASH, FSMC with external FIFO) and APB transfer management using the DMA2. Which I found stemmed and was discovered by through this blog post http://blog.frankvh.com/2012/01/13/stm32f2xx-stm32f4xx-dma-maximum-transactions/ So now I know exactly what is wrong. Do you have any idea how I could do it through software ? That was the path I was taking anyway. Simply setup the adc int and use that to change the channel and start the conversion again. No DMA. It seems to be working except channels 16,17,18 dont seem to be right. Does this look like a good way of doing software adc without dma ? I hate to do so much in the int, I do have a update tick that is driven very slowly by another source that I could use. I'm sure I'll figure it out, now that I know what the problem was. Thanks Clive !void initADC(int level)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
int adcChannels = 1;
DMA_Cmd(DMA2_Stream0, DISABLE);
while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE)
{
Delay(1);
}
ADC_Cmd(ADC1, DISABLE);
Delay(10);
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/
/*DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)&ADC1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&mygVars->ADCIN1;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = adcChannels;
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_Low;
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);*/
/* Configure ADC3 Channel12 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
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 = adcChannels;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC3 regular channel12 configuration *************************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles );
/*ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 7, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 8, ADC_SampleTime_480Cycles );
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 9, ADC_SampleTime_480Cycles );*/
//ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC3 DMA */
//ADC_DMACmd(ADC1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC1, ENABLE);
Delay(100);
ADC_SoftwareStartConv(ADC1);
}
void ADC_IRQHandler(void){
static int i;
if(ADC_GetITStatus(ADC1, ADC_IT_EOC))
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
Samples[i%9]=ADC1->DR;
i++;
switch(i%9){
case 0:
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles );
break;
case 1:
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_480Cycles );
break;
case 2:
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_480Cycles );
break;
case 3:
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_480Cycles );
break;
case 4:
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_480Cycles );
break;
case 5:
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_480Cycles );
break;
case 6:
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles );
break;
case 7:
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_480Cycles );
break;
case 8:
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 1, ADC_SampleTime_480Cycles );
break;
}// end switch
ADC_SoftwareStartConv(ADC1);
}
}