2015-02-20 11:02 AM
Hello
It seems that I do have huge challange. I need 14 analog inputs working continuously. According this I'm using DMA transmission. I've setup the GPIO config I've setup the DMA config. I've setup the ADC1 config.for all 14 analog inputs I've compared these config with some of the examples here at this forum. All of them show me differences in particular. But what ever I configure at DMA and ADC it will not work. The ADC gets one time a value and seems then to be stuck. The DMA does nothing. The memory array is empty all the time. I've check the configuration more times and found some faults due my own settings. But still the same problem like described above. Does anyone know whether there is a matching example anywhere or can giv eme a hint what I hav eto take care for e.g. for the deployment of the 14 analog inputs etc.?2015-02-20 11:44 AM
As entertaining as it is to guess what you've done wrong, I'll post this, and you can provide your code here, or via email, and I'll try an identify what's going on.
// STM32 ADC Sample 4x at 160 KHz STM32F4 Discovery - sourcer32@gmail.com
// (C) Copyright 2013-2014, All Rights Reserved
// Assumptions per system_stm32f4xx.c CPU @ 4 MHz, APB2 @ 2 MHz (/2), APB1 @ 6 MHz (/4)
// PLL ((HSI / 25) * 320) / 2, where HSI is ~0 MHz
// or
// ((HSE / 4) * 160) / 2, where HSE is 5.120 MHz
// ((HSE / 8) * 160) / 2, where HSE is 240 MHz
// ((HSE / 16) * 160) / 2, where HSE is 480 MHz
#include ''stm32f4_discovery.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* ADC Channel 10 -> PC0 - Clashes USB PowerOn
ADC Channel 11 -> PC1
ADC Channel 12 -> PC2
ADC Channel 13 -> PC3 - Clashes DOUT
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/**************************************************************************************/
void ADC_Configuration(void)
{
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; // 2,4,6,8
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; // 5-20 if interleave mode
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 4 Channels
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // Back-to-Back, maximal rate
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel 11 configuration */
ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_28Cycles); // 3,15,28,56,84,112,144,480
ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_28Cycles);
ADC_RegularChannelConfig(ADC1,ADC_Channel_12,3,ADC_SampleTime_28Cycles);
ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_28Cycles);
// Conversion time is 12 cycles, per manual
// (2 MHz / 2) / (12 + 28) = 640 KHz (1.5625 us)
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
}
/**************************************************************************************/
#define BUFFERSIZE 8
__IO uint16_t ADCConvertedValues[BUFFERSIZE];
static void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFERSIZE; // Count of 16-bit words
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_Enable;
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);
/* Enable DMA Stream Half / Transfer Complete interrupt */
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA Stream IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
void DMA2_Stream0_IRQHandler(void) // Called at 160 KHz, LED Toggles at 80 KHz
{
/* Test on DMA Stream Half Transfer interrupt */
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0))
{
/* Clear DMA Stream Half Transfer interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
/* Turn LED3 off: Half Transfer */
STM_EVAL_LEDOff(LED3);
// Add code here to process first half of buffer (ping)
}
/* Test on DMA Stream Transfer Complete interrupt */
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
/* Turn LED3 on: End of Transfer */
STM_EVAL_LEDOn(LED3);
// Add code here to process second half of buffer (pong)
}
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
DMA_Configuration();
ADC_Configuration();
STM_EVAL_LEDInit(LED3); /* Configure LEDs to monitor program status */
STM_EVAL_LEDOn(LED3); /* Turn LED3 on */
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);
while(1); // Don't want to exit
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**************************************************************************************/
2015-02-20 11:49 AM
I know I built a 13-UP example for someone, it don't have it to hand on this system.
2015-02-22 03:59 AM
Many thanks for the example.
It is although a bit a Problem for me to put the code here because of confidential requirements. But I'll compare your example to find out what is wrong. It can't be more than just a register bit.2015-02-22 07:04 PM
Makes for a bit of a one-way street...
// STM32F4-Discovery ADC1x13 (13UP) - sourcer32@gmail.com
// (C) Copyright 2013-2015, All Rights Reserved
#define SAMPLES 13
#include <
stdio.h
>
#include <
stdlib.h
>
#include <
string.h
>
#include ''stm32f4xx.h''
//****************************************************************************
volatile uint16_t ADCConvertedValues[SAMPLES];
//****************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
/* Configure ADC1 Channel 0 pin as analog input PA0 *****************************/
/* Configure ADC1 Channel 4 pin as analog input PA4 *****************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure ADC1 Channel 8 pin as analog input PB0 *****************************/
/* Configure ADC1 Channel 9 pin as analog input PB1 *****************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure ADC1 Channel 10 pin as analog input PC0 *****************************/
/* Configure ADC1 Channel 11 pin as analog input PC1 *****************************/
/* Configure ADC1 Channel 12 pin as analog input PC2 *****************************/
/* Configure ADC1 Channel 13 pin as analog input PC3 *****************************/
/* Configure ADC1 Channel 14 pin as analog input PC4 *****************************/
/* Configure ADC1 Channel 15 pin as analog input PC5 *****************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
//****************************************************************************
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
int i;
/* Enable peripheral 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;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = SAMPLES;
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);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
/* ADC Common Init **********************************************************/
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_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // Multiple Channels
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // Keep Sampling
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = SAMPLES;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration ******************************/
i = 1;
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, i++, ADC_SampleTime_480Cycles); // PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, i++, ADC_SampleTime_480Cycles); // PA4
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, i++, ADC_SampleTime_480Cycles); // PC4
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, i++, ADC_SampleTime_480Cycles); // PC5
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, i++, ADC_SampleTime_480Cycles); // PB0
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, i++, ADC_SampleTime_480Cycles); // PB1
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, i++, ADC_SampleTime_480Cycles); // PC0
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, i++, ADC_SampleTime_480Cycles); // PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, i++, ADC_SampleTime_480Cycles); // PC2
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, i++, ADC_SampleTime_480Cycles); // PC3
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, i++, ADC_SampleTime_480Cycles); // 16
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, i++, ADC_SampleTime_480Cycles); // 17
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, i++, ADC_SampleTime_480Cycles); // 18
/* Enable TempSensor and Vrefint */
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable VBAT channel */
ADC_VBATCmd(ENABLE);
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);
}
//****************************************************************************
int main(void)
{
GPIO_Configuration();
ADC1_Configuration();
while(1) /* Infinite loop */
{
if (ADCConvertedValues[SAMPLES-1] != 0xFFFF) // Check for new values loaded
{
int i;
for(i=0; i<
SAMPLES
; i++)
{
printf(''%03X '', ADCConvertedValues[i]);
}
printf(''
'');
ADCConvertedValues[SAMPLES-1] = 0xFFFF; // Invalidate
}
}
}
//****************************************************************************
// Hosting of stdio functionality through SWD (Keil)
//****************************************************************************
/* Implementation of putchar (also used by printf function to output data) */
int SendChar(int ch) /* Write character to Serial Port */
{
ITM_SendChar(ch); // From core_cm4.c
return(ch);
}
//****************************************************************************
#include <rt_misc.h>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
int fputc (int ch, FILE *f) { return (SendChar(ch)); }
int ferror (FILE *f) {
/* Your implementation of ferror */
return EOF;
}
void _ttywrch (int ch) { SendChar(ch); }
void _sys_exit (int return_code) { for (;;); }
//****************************************************************************
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
while (1)
{}
}
#endif
//****************************************************************************
2015-02-22 11:39 PM
2015-02-25 08:03 AM
2016-03-08 04:18 AM
2016-03-08 04:25 AM
2016-03-08 05:41 AM
Can we please stick to one thread. Ideally if discussing your own code, do so in your own thread.
[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/ADC%20trigger%20on%20timer%20update&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx¤tviews=3631]Other thread, cross posted