DMA only fetching 2 values from ADC
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-20 9:01 AM
STM32F437
This is an update from my previous thread:
https://community.st.com/message/154808-stm32f4-adcdma-always-returns-same-value
The ADC2 DR has the right value in it but the DMA is not working as I thought it would. It is only transferring 2 values although the array size and # of readings is 8. Condensed code is below.
Thanks,
JH
#define ADC_NUM_READINGS 8 // Changing these will require a significant change
void AdcInit(void);
uint16_t readVoltage(void);static uint16_t adc2_result[ADC_NUM_READINGS];static const DMA_InitTypeDef dma2 =
{ DMA_Channel_1, ADC2_BASE + 0x4C, // ADC2->DR (uint32_t)&adc2_result, //Mememory 0 base address DMA_DIR_PeripheralToMemory, ADC_NUM_READINGS, DMA_PeripheralInc_Disable, DMA_MemoryInc_Enable, DMA_PeripheralDataSize_HalfWord, DMA_MemoryDataSize_HalfWord, DMA_Mode_Circular, DMA_Priority_High, DMA_FIFOMode_Disable, DMA_FIFOThreshold_Full, DMA_MemoryBurst_Single, DMA_PeripheralBurst_Single};void adcInit(void)
{ ADC_CommonInitTypeDef cInit; ADC_InitTypeDef init; OS_ERR err;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
DMA_DeInit(DMA2_Stream2);
DMA_Init(DMA2_Stream2, (DMA_InitTypeDef*)&dma2); DMA_Cmd(DMA2_Stream2, ENABLE);cInit.ADC_Mode = ADC_Mode_Independent;
cInit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; cInit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; cInit.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&cInit);init.ADC_Resolution = ADC_Resolution_12b;
init.ADC_ScanConvMode = DISABLE; init.ADC_ContinuousConvMode = ENABLE; init.ADC_DataAlign = ADC_DataAlign_Right; init.ADC_NbrOfConversion = 1; ADC_Init(ADC2, &init);ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 1, ADC_SampleTime_15Cycles);
//ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); ADC_DMACmd(ADC2, ENABLE); ADC_Cmd(ADC2, ENABLE); ADC_SoftwareStartConv(ADC2);}uint16_t readVoltage(void)
{return adc2_result[0]; // I set a break point here and examine the array. Locations 2-7 are always zero.
}- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-20 9:56 AM
ADC_InitTypeDef init = { 0 }; // try doing this
Also
ADC2_BASE + 0x4C, // ADC2->DR
Wouldn't (uint32_t)&ADC2->DR be simpler/clearer?
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-20 12:11 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-21 9:39 AM
Thanks for the post Clive. I walked through your code and the only difference I see is in the buffer size and that you define external trigger configurations. But since I am using continuous ADC triggering that shouldn't matter.
The fact remains that if I enable DMA the ADC never updates its data register after the first reading. Also I still only get one or two values from the DMA for that first transfer. I am beginning to wonder if the DMA does not work without an ISR manipulating its registers.
JH
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-21 11:33 AM
Actually with the external trigger, the ADC buffer fills up even if the code is stopped by breakpoint. No interrupt, full HW...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-21 11:59 AM
Could you expand on 'No interrupt, full HW...' a bit?
I am trying to figure out why the DMA is shutting down my ADC.
Thanks,
JH
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-21 4:40 PM
DMA in the background, happens behind back of CPU and debugger
&sharpdefine ADC_NUM_READINGS 8 // Changing these will require a significant change
void adcInit(void);uint16_t readVoltage(void);volatile uint16_t adc2_result[ADC_NUM_READINGS]; static DMA_InitTypeDef dma2 ={ DMA_Channel_1, (uint32_t)&ADC2->DR, // ADC2->DR (uint32_t)&adc2_result[0], // Memory 0 base address DMA_DIR_PeripheralToMemory, ADC_NUM_READINGS, DMA_PeripheralInc_Disable, DMA_MemoryInc_Enable, DMA_PeripheralDataSize_HalfWord, DMA_MemoryDataSize_HalfWord, DMA_Mode_Circular, DMA_Priority_High, DMA_FIFOMode_Disable, DMA_FIFOThreshold_Full, DMA_MemoryBurst_Single, DMA_PeripheralBurst_Single};void GPIO_Configure(void)
{ GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure);}void adcInit(void)
{ ADC_CommonInitTypeDef cInit; ADC_InitTypeDef init = { 0 }; // Or initialize ALL fields DMA_DeInit(DMA2_Stream2); DMA_Init(DMA2_Stream2, (DMA_InitTypeDef*)&dma2); DMA_Cmd(DMA2_Stream2, ENABLE);cInit.ADC_Mode = ADC_Mode_Independent;
cInit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; cInit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; cInit.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&cInit); init.ADC_Resolution = ADC_Resolution_12b; init.ADC_ScanConvMode = DISABLE; init.ADC_ContinuousConvMode = ENABLE; init.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; init.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; init.ADC_DataAlign = ADC_DataAlign_Right; init.ADC_NbrOfConversion = 1; ADC_Init(ADC2, &init); ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 1, ADC_SampleTime_15Cycles);ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); // Recycles after DMA completes
ADC_DMACmd(ADC2, ENABLE);
ADC_Cmd(ADC2, ENABLE);
ADC_SoftwareStartConv(ADC2); // Start first time} uint16_t readVoltage(void){ return adc2_result[0]; // I set a break point here and examine the array. Locations 2-7 are always zero.}/**
* @brief Main program * @param None * @retval None */int main(void){ /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f4xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f4xx.c file */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); GPIO_Configure(); memset((void *)adc2_result, 0xCD, sizeof(adc2_result)); adcInit(); while(1) { static int i = 0; i += readVoltage(); } while (1) { }}Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-23 4:03 AM
I am trying to figure out why the DMA is shutting down my ADC.
And does it? How do you know? Post the content of relevant ADC and DMA registers.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-04-23 9:02 AM
There are problem with the ADC initialization due to several missing fields containing junk values. The ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); is needed to sustain the stream.
Keil also threw warnings about the addresses in the constant structure, but the linker seemed to fix up properly.
Up vote any posts that you find helpful, it shows what's working..
