2017-04-20 09: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.
}2017-04-20 09:56 AM
ADC_InitTypeDef init = { 0 }; // try doing this
Also
ADC2_BASE + 0x4C, // ADC2->DR
Wouldn't (uint32_t)&ADC2->DR be simpler/clearer?
2017-04-20 12:11 PM
2017-04-21 09: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
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...
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
2017-04-21 04: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) { }}2017-04-23 04: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
2017-04-23 09: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.