2013-12-17 02:11 AM
Hi i am trying to scan 4 channel using ADC1 and DMA1.
At the end of 1 cycle i will restart the acquision process (triggered in DMA TC interrupt handler). However i realised that it seem on every run the result of my conversion is different when noting is changed e.g. 1st run 2nd Run 3rd Run 0x00000FFF0x00000
FFF0x00000000
0x000000000x00000
FFF0x00000000
0x000000000x00000000 0x00000000
0x000000000x00000000 0x00000
FFFvoid NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART1 TX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void DMA_Configuration(void){
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 16;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
void ADC_Configuration(void){
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 3, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_239Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
}
void ADC_Calibration(void){
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
void Start_Conversion(void){
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void DMA1_Channel1_IRQHandler(void){
/* Test on DMA Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
ADC_DMA_Configuration();
ADC_Start_Conversion();
/* Clear DMA Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC1);
/* ... */
}
}
Did i miss something ? Thanks.
#adc-and-dma #wait-for-you--clive1-!-!-!
2013-12-17 04:11 AM
Did i miss something ?
There appears to be a lot of code/definitions missing, making it undesirable to dig into it. Observe how I present my examples.Why 16x 32-bit words for the DMA transfer?Why continuous mode, if you just want four samples?I think this would be more robust if you just set this up once, in circular mode, and using HT/TC interruptsClear the TC before doing the re-initialization.Do not enable DMA prior to doing calibration2013-12-17 06:00 PM
void RCC_Configuration(void)
{
/* ADCCLK = PCLK2/4 */
RCC_ADCCLKConfig(RCC_PCLK2_Div2);
/* Enable peripheral clocks ------------------------------------------------*/
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1, ADC2 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |
RCC_APB2Periph_GPIOC, ENABLE);
}
/**
* @brief Configures the different GPIO ports.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART1 TX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void DMA_Configuration(void){
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 16;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
void ADC_Configuration(void){
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 3, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_239Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
}
void Calibration(void){
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
void Start_Conversion(void){
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void DMA1_Channel1_IRQHandler(void){
/* Test on DMA Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
/* Clear DMA Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC1);
ADC_DMA_Configuration();
ADC_Start_Conversion();
}
}
int main(void) {
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
ADC_Configuration();
Calibration();
DMA_Configuration();
Start_Conversion();
}
__IO uint32_t ADC_DualConvertedValueTab[16];
Hi Clive i made some changes and added the full code however the issues persist. Thanks.
In addition , may i know what is the different between the following 2
uint32_t DMA_PeripheralDataSize;
/*!< Specifies the Peripheral data width.
This parameter can be a value of @ref DMA_peripheral_data_size */
uint32_t DMA_MemoryDataSize;
/*!< Specifies the Memory data width.
This parameter can be a value of @ref DMA_memory_data_size */
2013-12-18 07:12 AM
Still seems to be missing routines, and some indication of processor/board being used. The goal is to present some code I can drop in a compiler, and evaluate.
Suggest you tie one of the pins to a reference (1.8V or 1.2V perhaps) so you can confirm it's position in the array, if your problem is one of it randomly starting at the wrong channel, or slipping. In circular mode you don't reinitialize the DMA, and start the ADC, it keeps going. The need for 16 samples in a continuous fashion wasn't really addressed. Here's an example of 3 channels on a STM32 VL-Discovery board, observe how it is presented.[DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DMA1_Channel1_IRQHandler&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=119]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FDMA1_Channel1_IRQHandler&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=1192013-12-18 06:48 PM