I have looked through most of the posts in the forums on setting up the DMA and ADC1, but I could not fine a solution to what I am experience. I have also successfully compiled the examples in the library but still no luck. I have been trying to configure the DMA1 channel 5 to read ADC1 in continues conversion mode, but every time I run my program, DMA1 Channel 5 does not want to read my ADC, it stays idle. But the moment I change the DMA channel to channel 1 it suddenly works, but channel 1 of DMA1 is used for battery monitoring by the circle OS 3.8. When i copy the example code to my circle OS application and try to run it compiles but I have the same problem. The DMA values stays idle and nothing happens.
In STM32, DMA channels requests are preaffected to peripherals. ADC1 requests are send to DMA1 Channel1. The channel 5 is connected to SPI2/USART1/I2C2_Rx ans some TIM).
It’s like having one of those moments that everything is quiet, and you look around to see if someone is looking at you while you crawling under a rock.
I have the following problem: ADC1 is configured to be serviced by DMA1 channel 1. But the end of transfer complete interrupt does not want to work although I have set it up as in the examples. I have done the following setup:
Code:
/* Includes ------------------------------------------------------------------*/
#include "circle_api.h"
#include "myinclude.h"
/* Private defines -----------------------------------------------------------*/
#define ADC1_DR_Address ((uint32_t)0x4001244C)// address of ADC data register in memory
// The following should be the minimal CircleOS version needed by your application
#define NEEDEDVERSION "V 3.7"
/* Private functions ---------------------------------------------------------*/
static enum MENU_code MsgVersion(void);
void RCC_Setup(void);
void GPIO_Setup(void);
void NVIC_Setup(void);//interrupt setup
void DMA_Setup(void);
void ADC_Setup(void);
/* Public variables ----------------------------------------------------------*/
const char Application_Name[8+1] = {"ADC_DMA"}; // Max 8 characters
uint32_t sourceclock;
uint32_t ADC_Clock_Prev;
u32 uGain;
/* Private variables ---------------------------------------------------------*/
RCC_ClocksTypeDef RCC_Clocks;//
GPIO_InitTypeDef GPIO_InitStructure;//Step 0.5
NVIC_InitTypeDef NVIC_InitStructure;//
DMA_InitTypeDef DMA_InitStructure;//
ADC_InitTypeDef ADC_InitStructure;//
/*******************************************************************************
* Function Name : Application_Ini
* Description : Initialization function of Circle_App. This function will
* be called only once by CircleOS.
* Input : None
* Return : MENU_CONTINUE_COMMAND
*******************************************************************************/
enum MENU_code Application_Ini(void)
{
// Ensure that the current OS version is recent enough
if(strcmp(UTIL_GetVersion(), NEEDEDVERSION) < 0)
{
return MsgVersion();
}
RCC_Setup();
NVIC_Setup();
DMA_Setup();
ADC_Setup();
//debug code
uGain =0;
///////////////////
// TODO: Write your application initialization function here.
return MENU_CONTINUE_COMMAND;
}
/*******************************************************************************
* Function Name : Application_Handler
* Description : Management of the Circle_App.
*
* Input : None
* Return : MENU_CONTINUE
*******************************************************************************/
enum MENU_code Application_Handler(void)
{
// TODO: Write your application handling here.
// This routine will get called repeatedly by CircleOS, until we
// return MENU_LEAVE
#if 1
// If the button is pressed, the application is exited
if(BUTTON_GetState() == BUTTON_PUSHED)
{
BUTTON_WaitForRelease();
return MENU_Quit();
}
#endif
return MENU_CONTINUE; // Returning MENU_LEAVE will quit to CircleOS
}
/*******************************************************************************
* Function Name : MsgVersion
* Description : Display the current CircleOS version and the version needed
* exit to main menu after 4 secondes
*
* Input : None
* Return : MENU_REFRESH
*******************************************************************************/
static enum MENU_code MsgVersion(void)
{
int hh,mm,ss,ss2;
DRAW_DisplayString(5,60,"CircleOS",17);
DRAW_DisplayString(80,60,UTIL_GetVersion(),6);
DRAW_DisplayString(5,34,NEEDEDVERSION,6);
DRAW_DisplayString(50,34," required",12);
RTC_GetTime( &hh, &mm, &ss);
ss = ss + 4; // 4 secondes
ss = ss%60;
do
{
RTC_GetTime( &hh, &mm, &ss2 );
}
while ( ss2 != ss ); // do while < 4 secondes
DRAW_Clear();
return MENU_REFRESH;
}
/****************************************************************************
*
* NAME: RCC_Setup
*
* DESCRIPTION:
* Configures the RCC pheriperals clocks
*
*
* RETURNS:
* Zero returns.
*
****************************************************************************/
void RCC_Setup(void)
{
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// Enable PORT clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable ADC1 clock */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE );
}
/****************************************************************************
*
* NAME: NVIC_Setup
*
* DESCRIPTION:
* Configures the NVIC -- Interrupt controller
*
*
*
* RETURNS:
* Zero returns.
*
****************************************************************************/
void NVIC_Setup(void)
{
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;//
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//
NVIC_Init(&NVIC_InitStructure);//
}
/****************************************************************************
*
* NAME: DMA_Setup
*
* DESCRIPTION:
* Configures the DMA
*
* RETURNS:
* Zero returns.
*
****************************************************************************/
void DMA_Setup(void)
{
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//
DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)&ADCConvertedValue;//
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
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;//Hight priority
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// tomemory transfer
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);//
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
/****************************************************************************
*
* NAME: ADC_Setup
*
* DESCRIPTION:
* Configures the ADC pheriperal
*
* RETURNS:
* Zero returns.
*
****************************************************************************/
void ADC_Setup(void)
{
ADC_DeInit(ADC1);
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 = 1;//
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel14 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_239Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
/****************************************************************************
*
* NAME: GPIO_Setup
*
* DESCRIPTION:
* Configures the GPIO pheriperal
*
* RETURNS:
* Zero returns.
*
****************************************************************************/
void GPIO_Setup(void)
{
/* Configure pin as analog input ---------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
What I want to accomplish with this code is to read the ADC1 in to a memory area by using the DMA controller. Then afterwards write the logged data to the external SDCARD interface. This is my DMA interrupt handler for my DMA interrupt.
Code:
/
******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f10x_xx.s). */
/******************************************************************************/
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
/*void PPP_IRQHandler(void)
{
}*/
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
void DMA1_Channel1_IRQHandler(void)
{
ADCValue_DMA1 = ADCConvertedValue;
}
I do not know what I’m doing wrong. Any suggestions or help maybe?
I noticed it and have made changes to it to Pin_4. This change had no effect on generating a DMA_IT_TC interrupt from the DMA controller. I started a new application without the circle OS and used exactly the same code setup for NVIC, DMA, ADC and it worked.
I don’t know any more. It may be that my priorities are setup wrong or something.