2014-01-04 01:51 PM
Hello,
I would like to sample 2 analog channels with 100kHz (STM32F429 disco). I found examples only with one channel. I tryed to edit it, but my code dont work. If I placed breakpoint into DMA2_Stream4_IRQHandler() , program never break there. thanks for help#include ''stm32f4xx.h''
#define BUFFERSIZE 100 // What size is neccesarry?
__IO uint16_t ADCConvertedValue[BUFFERSIZE];
void
GPIO_config(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
// ADC channel 5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
// ADC channel 13
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void
ADC_config(
void
)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_StructInit(&ADC_InitStructure);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonStructInit(&ADC_CommonInitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
// more then 1 channel in group
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
// conversions triggered
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_NbrOfConversion = 2;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_112Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_112Cycles);
// 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);
}
void
DMA_config()
{
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
//==Configure DMA2 - Stream 4
DMA_DeInit(DMA2_Stream4);
//Set DMA registers to default values
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
//Source address
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0];
//Destination address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFERSIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
//source size - 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
// destination size = 16b
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_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream4, &DMA_InitStructure);
/* Enable DMA - Transfer Complete interrupt */
DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE);
/* DMA2_Stream4 enable */
DMA_Cmd(DMA2_Stream4, ENABLE);
}
void
TIM2_config()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = (180000000 / 100000) - 1;
// 180M/100k = 1800tick = 10us - Is correct?
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}
void
NVIC_config()
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA Stream IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void
DMA2_Stream4_IRQHandler(
void
)
{
/* Test on DMA Stream Transfer Complete interrupt */
if
(DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF0))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_TCIF0);
}
}
int
main(
void
)
{
GPIO_config();
NVIC_config();
TIM2_config();
DMA_config();
ADC_config();
// I need SysTick_Handler() per 1ms
if
(SysTick_Config(SystemCoreClock / 1000))
{
/* Capture error */
while
(1);
}
// start ADC conversion
ADC_SoftwareStartConv(ADC1);
while
(1)
{
}
}
#adc #dma #timer-2channels
2014-01-04 05:14 PM
For C++ make sure the IRQHandler's name isn't mangled (check .MAP, and vector linkage)
Alsoif
(DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF0))
That should be DMA_IT_TCIF4 shouldn't it?
Is it even Stream 4? I'd have to check the manual, but my other 2 Channel (same sample point) example used Stream 0.
/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/ADC%20in%20Dual%20Mode%20Simultaneously&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=404
2014-01-04 05:14 PM
ADC1 is on Channel 0, Stream 0 or 4. See RM00090 Rev 5 Reference Manual, Table 44.
Cheers, Hal2014-01-04 05:19 PM
Yeah, Stream4 should be fine.
2014-01-04 06:08 PM
Just to clarify - Tomas' code is attempting to use Channel 4.
Cheers, Hal2014-01-04 06:33 PM
2014-01-04 10:36 PM
I am using C. You can see a part of file startup_stm32f429_439xx.S with
DMA2_Stream4.
The file system_stm32f4xx.it.cdoes not containDMA2_Stream4_IRQHandler.
It placed
in main.c
file
.
Is it correct?* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,''a'',%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
...
/* External Interrupts */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
2014-01-04 11:11 PM
You mix variable definitions, with function calls, this is a very C++ construct, so just checking.
As Hal highlighted, and I diagrammed your real problem is the Channel4 is not usable as it has NO connectivity to ADC1 Further if you use Stream4 then you need to be examining the TC4 flags, as they are interrelated. You can define the body for the IRQHandler functions in any source/objects files you choose, the linker resolves that. C++ mangles names based on parameters, so the linkage would not occur, and the weak definition would prevail.2014-01-05 12:08 AM
I mixed up ''stream'' and ''channel in stream''. I fixed it, but the code still doesnt work. Program never break on breakpoint in DMA2_Stream4_IRQHandler.
I am not sure of size of ADCConvertedValuetoo.void DMA2_Stream4_IRQHandler(void)
{
// Test on DMA Stream Transfer Complete interrupt
if(DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF4))
{
// Clear DMA Stream Transfer Complete interrupt pending bit
DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_TCIF4);
}
}
void ADC_config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_StructInit(&ADC_InitStructure);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonStructInit(&ADC_CommonInitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // more then 1 channel in group
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // conversions triggered
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_NbrOfConversion = 2;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_112Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_112Cycles);
// 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);
}
void DMA_config()
{
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
//==Configure DMA2
DMA_DeInit(DMA2_Stream4); //Set DMA registers to default values
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //Source address
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0]; //Destination address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFERSIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //source size - 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // destination size = 16b
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_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream4, &DMA_InitStructure); //Initialize the DMA
/* Enable DMA - Transfer Complete interrupt */
DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE);
/* DMA2_Stream4 enable */
DMA_Cmd(DMA2_Stream4, ENABLE);
}
void TIM2_config()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = (180000000 / 100000) - 1; // 180M/100k = 1800tick = 10us
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}
void NVIC_config()
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA Stream IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
2014-01-05 05:09 AM
Size appears correct, it's in units of transfers, not bytes
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
No, don't do that you want it to remain pointing at ADR1->DR, the timer triggers the ADC start, the ADC EOC triggers the DMA