We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi, I use a MCBSTM32E evaluation board, which is composed of an STM32F103ZET6 MCU, and I loaded the measure example provided by Keil. It works perfectly, but I want to add another variable resistor on PC13 which is the channel 13 of ADC1. The onboard variable resistor is connected to channel 14. Thus I configured the ADC to work with two channels (13 & 14), the DMA to have a buffersize of 2 and created an int ADC_ConvertedValue2 that should contain the second conversion result. I configured the channels like underneath : ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_55Cycles5);
My result is that each conversion result is store on the same variable (ADC_ConvertedValue) and the second one has nothing. I dont know how to get the value of the second conversion in the EOC interruption routine. Can I still use this interruption and do i have to use a DMA one ? I'm a bit confused about how ADC channels really works and neither the datasheet nor the FWLib helped me. Thanks in advance for any hint. Gary
Interrupts and DMA are two separate mechanisms.
You may use: - no interrupts, no DMA. Just poll the ADC. - no interrupts but DMA. Poll DMA or ADC when a full DMA transfer is done (all channels processed). - interrupts for each individual read, without use of DMA. - interrupts together with DMA - you get the interrupt when all enabled channels have been processed (and DMA have written the values into an array).
If you are going to change existing code (or write new) then you must read the datasheet for the processor - especially the settings available for the DMA unit (if you decide to use DMA), the ADC and the interrupt logic (if you decide to use interrupts).
In the end, there are almost always multiple ways to solve a problem. In your case, you must choose if you want to use interrupts or not and if you want to use DMA or not. If you do use DMA then you will have to configure it to step the destination address, since it isn't meaningful to use DMA for reading from ADC to memory unless you step the address. Either because you want multiple samples from one channel. Or you want one sample each from multiple channels. Without activating the destination step function, you would just overwrite the previous value. How you do it is described in the datasheet. If you want to use DMA is something you must decide.
If you want to use interrupts, you may normally configure to get one interrupt for each ADC read, or one interrupt for each full pass through all activated ADC channels. How you do is mentioned in the datasheets. If you want to do it is something you must decide.
If you want to poll the ADC to check if a value is ready (i.e. skip interrupts and DMA) the required information is in the datasheet. The decision to do this is up to you.
If you want to use DMA and poll the DMA unit to check when a full DMA burst is done, then the datasheet should tell how to check the running state of the DMA unit. The decision if this is a good solution for your application is obviously up to you.
What I would recommend is that you do your best to get it to work. Then post a reference to a named datasheet and tell what part of that text you don't understand. And/or a sample code that you have designed (based on information in examples and the datasheet) and what you think the code does, and what it actually does. Then people may comment about code lines where you might have misunderstood something, or where you might have forgotten required steps.
About defining symbols to control your compilation (__USE_IRQ), you can open your target options and then select the tab "C/C++". The top text is "Preprocessor Symbols" and the first field is labeled "Define".
If you write a symbol name there, you will directly see your compiler command line update in the bottom-most field of the tab.
The tab "Asm" have similar fields for controlling symbols used together with assembler files.
I'm back on my problem. I made it work with DMA without interrupts. It works well, it is quite simple to get data in an array which size depends on the number of channels. I did not find how to generate an interrupt from DMA to tell that the transfer is done. I configured the DMA like this :
/* DMA1 channel1 configuration */ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_result; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 2; 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 DMA1 channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1 , ENABLE);
and the NVIC as below :
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_DeInit(); /*Deinitializes the NVIC*/ NVIC_SCBDeInit(); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
It seems to me that the problem comes from the NVIC because once it is initialised, my Systick_IRQHandler (which is necessary in my case to activate conversion every 10ms) runs only once and then doesnt work anymore. Do I need to put my systick interrupt in the NVIC structure ? I've seen that this latter is automatically in it. If I need to, what is the name of the IRQ_Channel because I tried SysTick but it did not compiled. Is it a better solution to use a timer to get my 10ms interrupt ? Thanks in advance (again).
NB : Documents I read : Reference Manual (www.st.com/.../13902.pdf) Insider's Guide (www.st.com/.../1221142709.pdf) FWLib (www.st.com/.../13475.pdf) STM32 Datasheet (www.st.com/.../14611.pdf)