cancel
Showing results for 
Search instead for 
Did you mean: 

3 channels on ADC1 and DMA

fabricepeden
Associate II
Posted on April 10, 2013 at 07:59

Hi Everbody,

I'm trying to configure 3 channels of the ADC (Vbat, Temp and another analog input). Yesterday, I managed to read the value of Vbat. Now I would to read the value of the three channels, but I have '0' in my array. I have started to initialize the DMA. I'm using DMA2 stream 0 (for ADC1 in the datasheet).

/* Initialize the DMA1 Channel1 according to the DMA_InitStructure members */
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/* Enable peripheral clocks *************************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001204C;//ADC1_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&ADCConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 3;
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_Init(DMA2_Stream0, &DMA_InitStructure);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA2_Stream0, ENABLE);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Enabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel18 (VBAT) configuration ******************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_15Cycles);
/* Enable VBAT channel */
ADC_VBATCmd(ENABLE); 
/* Enable Temp channel */
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC1 DMA transfer */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
ADC_SoftwareStartConv(ADC1);

Have you some ideas to suggest to me to help me to solve this problem ? Thank you in advance,
16 REPLIES 16
Posted on April 10, 2013 at 12:06

Have you some ideas to suggest to me to help me to solve this problem ?

Be more attentive to salient details.

uint16_t ADCConvertedValues[3];
..
DMA_InitStructure.DMA_Channel = DMA_Channel_0; // ADC1, per Table 36 RM0090 Rev4
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&ADCConvertedValues[0];
..
ADC_InitStructure.ADC_NbrOfConversion = 3;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabricepeden
Associate II
Posted on April 10, 2013 at 12:35

Thank you for your help.

It works a little bit better.

In my watch window, I can see the value of Vbat, but I have 0 for TEMP and my ADC channel.

It seems like there is no incrementation of the address.

In the DMA option, I think this one is done for that :

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

I

Posted on April 10, 2013 at 12:52

No, you definitely want to keep reading &ADC1->DR

There are perhaps other problems,

/* 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 = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
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 =3;
ADC_Init(ADC1, &ADC_InitStructure);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabricepeden
Associate II
Posted on April 10, 2013 at 13:32

No, you definitely want to keep reading &ADC1->DR --> What do you mean by that ?

Now I did that : DMA_InitStructure.DMA_Channel = DMA_Channel_0; --> Channel as noticed in the datasheet. DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001204C;//ADC1_DR_ADDRESS; --> address of ADC peripheral (cf. datasheet) DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&ADCConvertedValue[0]; --> As you told me two messages before.

/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; -> I think this one must be changed inADC_DMAAccessMode_1
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
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 =3;
ADC_Init(ADC1, &ADC_InitStructure);
It begin to work a little bit better. Now I can watch alternatively inADCConvertedValue[0], Vbat and TEMP.
Now I need to understand how put it inADCConvertedValue[1].
Thanks for your help.

fabricepeden
Associate II
Posted on April 10, 2013 at 13:56

Just to be sure, that I have understand :
DMA_InitStructure.DMA_Channel = DMA_Channel_0; 

--> Channel 0 as mentionned in the datasheet
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001204C; 

--> Address of ADC1 peripheral
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&ADCConvertedValue[0]; 

--> pointer on my data
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 

--> From ADC to memory
DMA_InitStructure.DMA_BufferSize = 3; 

--> 3 data to bring back (Vbat, TEMP, + ANA input)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

--> No incrementation of peripheral, always read at the same address
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 

--> I'm not sure for this one, because for me, it must increment to record data into my array
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);
/* Enable DMA1 Channel1 */
DMA_Cmd(DMA2_Stream0, ENABLE);
/* Configure ADC1 Channel8 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; 

--> mode independant (as mentionned in theAN3116 document)
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 

--> clock for ADC
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

 --> access for DMA in mode 1
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 

--> sampling time
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; -

-> For me,this one must be modified, because it need to know the edge to start conversion ?
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; 

--> It's the trigger, but does I need to activate Timer1 or not ?
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 3;
ADC_Init(ADC1, &ADC_InitStructure);

raptorhal2
Lead
Posted on April 10, 2013 at 17:21

If you are reading 3 channels at once, DMA memory inc needs to be enabled.

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; 

--> It's the trigger, but does I need to activate Timer1 or not ?

This is just to completely initialize the structure to something. Timer1 is not needed. You could rewrite it as

ADC_InitStructure.ADC_ExternalTrigConv = 0; and the result would be the same.

Cheers, Hal
Posted on April 10, 2013 at 18:40

A more complete, working example

// STM32F2/4 Three Channel ADC1 Loop - sourcer32@gmail.com
#include <
stdio.h
>
#include <
stdlib.h
>
#include <
string.h
>
#include ''stm32f2xx.h''
//******************************************************************************
volatile uint16_t ADCConvertedValues[3];
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* Configure ADC1 Channel8 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//******************************************************************************
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* 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 = 3;
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;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
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 = 3;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration ******************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_480Cycles); // PB0
/* Enable VBAT channel */
ADC_VBATCmd(ENABLE);
/* Enable Temp channel */
ADC_TempSensorVrefintCmd(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();
puts(''ADC Testing'');
while(1)
{
if (ADCConvertedValues[2] != 0xFFFF)
{
printf(''%03X %03X %03
X'', ADCConvertedValues[0], ADCConvertedValues[1], ADCConvertedValues[2]);
ADCConvertedValues[2] = 0xFFFF;
}
}
while(1); /* Infinite loop */
}

ADC Testing 7F6 45B 010 7F6 45B 010 7F6 45B 00E 7F5 45B 00D 7F7 45A 00E 7F6 45A 00E 7F6 45A 00E 7F5 45A 00E 7F6 45B 00E 7F7 45B 00F
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabricepeden
Associate II
Posted on April 11, 2013 at 06:39

Thank you for your help.

Now it's working perfectly.

My biggest mistake was the peripheral base address.

The order of instructions is a little bit different, I have read somehere on the forum, that this point is very important.

Thank you.

oyakovlev
Associate II
Posted on January 30, 2014 at 12:48

Hi Clive,

I've used your example from here [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/STM32F3%20Discovery%20next%20steps&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=2221]STM32 ADC Quad Mode STM32F3-Discovery for implement the same functionality (3 ADC channels acq) for STM32F3DISCOVERY. But I've couldn't achieve the same results as in your example here. My code works fine for 1 channel in ADC group, but provides some garbage for 1st and 3rd channels like this: FF97 0EC 000 2797 0EB 000 ..... Please help me, what am I doing wrong? Thanks in advance! Code below:

#include <
stdio.h
>
#include <
stdlib.h
>
#include ''main.h''
#include ''stm32f30x_rcc.h''
#include ''stm32f30x_gpio.h''
#include ''stm32f30x_dma.h''
#include ''stm32f30x_adc.h''
#include ''stm32f30x_tim.h''
#include ''ST77h''
// STM32 ADC Quad Mode STM32F3-Discovery - sourcer32@gmail.com
/**************************************************************************************/
// ADC1 ADC2 ADC3 ADC4
// IN1 PA0* PA4 PB1 PE14*
// IN2 PA1 PA5* PE9* PE15*
// IN3 PA2 PA6* PE13* PB12
// IN4 PA3 PA7* --- PB14
// IN5 PF4 PC4 PB13 PB15
//
// *Used on STM32F3-Discovery
// Free pins located in STM32F3-Discovery manual, UM1570
// ADC1/2 Trigger EXT3 TIM2_CC2
// ADC3/4 Trigger EXT1 TIM2_CC3
// Pins for this example PA1, PA2, PA3, PF4
/**************************************************************************************/
//#include ''stm32f30x.h''
#include ''stm32f3_discovery.h''
/**************************************************************************************/
#define SAMPLES 10
#define ADC12_CDR_ADDRESS ((uint32_t)0x5000030C)
volatile uint16_t ADCConvertedValues[SAMPLES*3];
uint16_t CalibrationValue;
/**************************************************************************************/
void ADC_GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA and GPIOB Periph clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
/* ADC Channels configuration */
/* Configure as analog input */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;// | GPIO_Pin_2; // | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**************************************************************************************/
void ADC12_DMA_Configuration(void) {
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA configuration */
/* DMA1 Channel1 Init Test */
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC12_CDR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 3;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord; //DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure); // ADC1
}
/**************************************************************************************/
void ADC_Configuration(void) {
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
volatile int i;
/* Configure the ADC clocks */
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1);
/* Enable ADC1/2 clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
/* ADC GPIO configuration */
ADC_GPIO_Configuration();
/* ADC DMA Channel configuration */
ADC12_DMA_Configuration();
/* ADC Calibration procedure */
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
/* Insert delay equal to 10 µs */
//Delay(10);
for(i=0; i<10000; i++);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET );
CalibrationValue = ADC_GetCalibrationValue(ADC1);
/* ADC Quad mode configuration */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; // 12-bit
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
/* */
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable; // Triggered
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 3;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_3; // ADC1/2 EXT3 TIM2_CC2
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_7Cycles5); // PA1
/* Enable VBAT channel */
ADC_VrefintCmd(ADC1,ENABLE);
/* Enable Temp channel */
ADC_TempSensorCmd(ADC1,ENABLE);
/* Configures the ADC DMA */
ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);
/* Enable the ADC DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC[1..4] */
ADC_Cmd(ADC1, ENABLE);
/* wait for ADC1 ADRDY */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
/* Enable the DMA channel */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Start ADC1 Software Conversion */
ADC_StartConversion(ADC1);
}
/**************************************************************************************/
void TIM2_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Enable ADC1/2 clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 2) - 1; // very slow for test purposes
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel2 & 3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 10; // Some arbitary width
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
// TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
/**************************************************************************************/
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* Enable DMA1 channel1 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
void DMA1_Channel1_IRQHandler(void) { // 2 Hz
/* Test on DMA1 Channel1 Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
/* Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits */
DMA_ClearITPendingBit(DMA1_IT_GL1);
STM_EVAL_LEDToggle(LED3); // 1 Hz
//TIM_Cmd(TIM2, DISABLE);
}
}
/**************************************************************************************/
int main(void) {
/* Initialize LEDs available on STM32F3-Discovery board */
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Turn on LD3 */
STM_EVAL_LEDOn(LED3);
/* Turn off LD4 */
STM_EVAL_LEDOff(LED4);
TIM2_Configuration();
ADC_Configuration();
/* Use LED's to confirm sample periodicity */
NVIC_Configuration();
/* Enable DMA1 Channel1 Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
lcd7735_setup();
delay_ms(50);
lcd7735_initR(INITR_REDTAB);
lcd7735_init_screen((void *)&SmallFont[0],ST7735_GREEN,ST7735_BLACK,PORTRAIT);
while(1) {
if (ADCConvertedValues[0] != 0xFFFF) {
printf(''%03X %03X %03
X'', ADCConvertedValues[0], ADCConvertedValues[1], ADCConvertedValues[2]);
ADCConvertedValues[0] = 0xFFFF;
}
}
}