cancel
Showing results for 
Search instead for 
Did you mean: 

Multiple Channel ADC on STM32 L1 Discovery with CooCox

cht35
Associate II
Posted on January 29, 2016 at 13:46

Hello STM users,

I have been thrown in 'at the deep' using an STM32L152 in a commercial product design. I have inherited some code which uses the CooCox CooIDE for development and an STM32 L1 discovery board which uses the same IC. I am trying to get 4 channels of ADC acquisition working, either polled or ideally DMA/Interrupt driven. I've been through a few days of trawling the web now but can't seem to find an example which works in this environment. Most of my problems stem from differences in target IC for the examples I have found online. This si my first outing with STM, I'm used to Microchip.

Does anyone have a straight up example of multiple channel ADC on the L1 discovery board that may be compiled under CooCox?

Warmest regards from cold Mid Wales,

Peter

my CoIDE version is Version: 1.7.8

#discovery-l1-adc-multiple
15 REPLIES 15
Posted on January 29, 2016 at 17:41

Quick blind 4 UP

// sourcer32@gmail.com - STM32L15x ADC DMA Demo (Four Channel, PA6,PA7,PB0 and PB1)
#include ''stm32l1xx.h''
// Thousand samples for each of the 4 channels, interrupting every 500 groups
#define SAMPLES (1000 * 4)
volatile uint16_t ADC_ConvertedValues[SAMPLES];
//******************************************************************************
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*!< 
At
this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32l1xx_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32l1xx.c file
*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
/* Configure PB6 (BLUE LED) and PB7 (GREEN LED) */
GPIO_InitStructure.GPIO_Pin
= 
GPIO_Pin_6
| GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode
= 
GPIO_Mode_OUT
;
GPIO_InitStructure.GPIO_OType
= 
GPIO_OType_PP
;
GPIO_InitStructure.GPIO_PuPd
= 
GPIO_PuPd_NOPULL
;
GPIO_InitStructure.GPIO_Speed
= 
GPIO_Speed_2MHz
;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIOB->ODR &= ~GPIO_Pin_7;
GPIOB->ODR |= GPIO_Pin_6;
/* PA6 ADC_IN6 clash Linear Touch Sensor */
/* PA7 ADC_IN7 clash Linear Touch Sensor */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PB0 ADC_IN8 clash Linear Touch Sensor */
/* PB1 ADC_IN9 clash Linear Touch Sensor */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Enable the DMA Stream IRQ Channel */
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);
/* Enable The HSI (16Mhz) */
RCC_HSICmd(ENABLE);
/* Check that HSI oscillator is ready */
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
/* ADC1 Configuration ------------------------------------------------------*/
/* Enable ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Deinitialize ADC */
ADC_DeInit(ADC1);
ADC_CommonStructInit(&ADC_CommonInitStructure);
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC Configuration */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // Multiple channels
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // Continuously back-to-back, not triggered
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // Not triggered
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; // Not used, valid placeholder
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC1,&ADC_InitStructure);
/* ADC1 regular channel 6 for PA6 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 7 for PA7 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 8 for PB0 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 9 for PB1 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 4, ADC_SampleTime_192Cycles);
/* Enable ADC1 Power Down during Delay */
ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA Stream Half / Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, ENABLE);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Enable the request after last transfer for DMA Circular mode */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait until ADC1 ON status */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);
/* Infinite loop */
while(1);
}
//******************************************************************************
void DMA1_Channel1_IRQHandler(void)
{
/* Test on DMA Channel Half Transfer interrupt */
if (DMA_GetITStatus(DMA1_IT_HT1))
{
/* Clear DMA Channel Half Transfer interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_HT1);
/* Toggle BLUE LED: Half Transfer */
GPIOB->ODR ^= GPIO_Pin_6; // Toggle
// Add code here to process first half of buffer (ping)
}
/* Test on DMA Channel Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
/* Clear DMA Channel Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC1);
/* Toggle GREEN LED: Transfer Complete */
GPIOB->ODR ^= GPIO_Pin_7; // Toggle
// Add code here to process second half of buffer (pong)
}
}
//******************************************************************************
#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
//******************************************************************************

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cht35
Associate II
Posted on January 29, 2016 at 17:43

Okay thank you so much both will investigate, still on the picosecond part of the rise time here, my apologies.

Peter

cht35
Associate II
Posted on January 29, 2016 at 18:30

Thank you Clive for the example code, you've gone above and beyond, as I've gathered from your other postings here as well. Peter.

cht35
Associate II
Posted on January 29, 2016 at 21:03

Hello Clive, 

finally getting something like here with your help, I can't figure out how to PM you but if you can point me in the right direction to getting hold of your details I'd like to send you 'a slice of my slice' for today.

Best Regards

Peter
Posted on January 29, 2016 at 21:44

Click the name under the avatar, or see the email tag in most posted code examples.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cht35
Associate II
Posted on January 30, 2016 at 11:20

Tis' done, and well worth it. : )