2016-01-29 04:46 AM
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,Petermy CoIDE version is Version: 1.7.8 #discovery-l1-adc-multiple2016-01-29 05:41 AM
This is a single up example, to do multiple, you select scan mode, tell it the number of channels, enumerate them with ranking.
[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/STM32%20ADC%20DMA%20Circular%20Mode&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F¤tviews=225]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/STM32%20ADC%20DMA%20Circular%20Mode&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F¤tviews=225 CooCox has historically not called SystemInit() properly, in CMSIS implementations it is normally called before main() and the runtime initialization. For things that expect clocks to be working as expected you might need to call SystemInit() as you enter main(), to use more general examples. I might well have other examples, but the stuff is reasonable portable. You'd have to address the pin configuration and channels, but something like this/* 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
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC1,&ADC_InitStructure);
/* ADC1 regular channel 1 for PA1 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 2 for PA2 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 3 for PA3 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_192Cycles);
/* ADC1 regular channel 4 for PA4 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_192Cycles);
2016-01-29 05:45 AM
What library are you/they using? Standard Peripherals Library (
) or or maybe something other? You can say it from the library file names, i.e. if it's stm32l1xx_adc.c then it's StdPeriph, if the filenames are like stm32l1xx_hal_adc.c then it's HAL. In any case, you can find examples in the official packages of those libraries (linked above).2016-01-29 05:54 AM
Thanks Clive I shall have a gander at this and see what gives.
2016-01-29 05:56 AM
The libraries I am using are the Std Periph ones. I'll take a look at the links you suggest thank you. Peter
2016-01-29 07:17 AM
Hello Clive,
I am having progress, I can see values changing when I ground each of the pins however the grounded pin doesn't always match the indicated value on my output.Its very possible that I haven't got my head round the GPIO to Analog channel mapping.From the STM32L15x datasheet I found mappings of ADC_IN10 to PC0 etc. and am attempting to acquire the analog values on PC0 - 3.I can see where GPIO Pin number is mapped but am unclear as to whether the initial line in GPIO_Init: RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);is where the Pin number is connected with the PCx ports rather than PAx for example.Am I getting this part wrong?Many thanks for your suggestions so far, I had the single acquire going already and had tried the multiple but neglected this line: ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;which seems to have sprung the multiple convert into life.Here's my code so far in the quest:#include ''stm32l1xx.h''#include ''stm32l1xx_gpio.h''#include ''stm32l1xx_rcc.h''#include ''stm32l1xx_exti.h''#include ''stm32l1xx_syscfg.h''#include ''stm32l1xx_adc.h''ADC_InitTypeDef ADC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;__IO uint16_t ADCdata[4] = { 0, 0, 0, 0};void GPIO_Config(void);void ADC_Config(void);int main(){ GPIO_Config(); ADC_Config(); while(1) { ADCdata[0] = ADC_GetConversionValue(ADC1); printf(''ADC0 IS %d '',ADCdata[0]); ADCdata[1] = ADC_GetConversionValue(ADC1); printf(''ADC1 IS %d '',ADCdata[1]); ADCdata[2] = ADC_GetConversionValue(ADC1); printf(''ADC2 IS %d '',ADCdata[2]); ADCdata[3] = ADC_GetConversionValue(ADC1); printf(''ADC3 IS %d \n'',ADCdata[3]); }}void GPIO_Config(void){ /* Enable The HSI (16Mhz) */ RCC_HSICmd(ENABLE); /* Enable the GPIOC Clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); /* Configure GPIO pins to Analog mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Check that HSI oscillator is ready */ while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);}void ADC_Config(void){ /* ADC1 Configuration ------------------------------------------------------*/ /* Enable ADC1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* Setup ADC Structure */ ADC_StructInit(&ADC_InitStructure); 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_T2_CC2; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 4; ADC_Init(ADC1, &ADC_InitStructure); /* ADC channels configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_192Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_192Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_192Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_192Cycles); /* 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); /* Wait until ADC end of conversion */ while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) { }}2016-01-29 07:41 AM
2016-01-29 07:45 AM
2016-01-29 08:23 AM
You can't do this, you have to use DMA for multiple channels
ADCdata[0] = ADC_GetConversionValue(ADC1);
printf(''ADC0 IS %d '',ADCdata[0]);
ADCdata[1] = ADC_GetConversionValue(ADC1);
printf(''ADC1 IS %d '',ADCdata[1]);
ADCdata[2] = ADC_GetConversionValue(ADC1);
printf(''ADC2 IS %d '',ADCdata[2]);
ADCdata[3] = ADC_GetConversionValue(ADC1);
printf(''ADC3 IS %d
'',ADCdata[3]);
And use the DMA interrupts to provide EOC, also the data is going to change faster than you can print it to a terminal. So you'd need to take a snap shot of the measurements, and then print them.
Now if you need 4 measurements in a polled loop, don't use continuous mode, leave the DMA in circular, and then trigger the set of 4 conversions, and wait for DMA TC to flag (vs ADC EOC)
2016-01-29 08:25 AM
See the complete example in the thread I cited, and merge in the second fragment in place of the single up configuration, along with the pin configurations.