AnsweredAssumed Answered

STM32F4 - ADC to PWM outputs

Question asked by b.gui on Aug 18, 2012
Latest reply on Aug 18, 2012 by b.gui
Hi, for my project I would like to take multiple adc to pwm outputs. I think I'm almost done, but I can't seem to make it works. I would be very grateful if someone can have a little look at my code below and tell me if I made a mistake somewhere ! Also, I was wondering, I saw that in the STM32F10x_StPeriph_Lib there is a function to calibrate the adc but didn't find it on the STM32F4 library. So is there a function to calibrate the adc on the stm32f4 or I need to do it manually or this shouldn't be something to worry about ?

thanks!

Code:
001.int main(void)
002.{
003.  RCC_ClocksTypeDef RCC_Clocks;
004.     
005.  /* SysTick end of count event each 10ms */
006.  RCC_GetClocksFreq(&RCC_Clocks);
007.  SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); 
008.   
009.  /* USB configuration */
010.  USBConfig();
011. 
012.  //Configuration of DMA for the ADC channels
013.  DMA_ADC_Config();
014. 
015.  //Configuration of the ADC channels used
016.  ADC_Config();
017. 
018.  /* Start ADC1 Software Conversion */
019.  ADC_SoftwareStartConv(ADC1);
020. 
021.  //Configuration of the PWM (Timers) channels used
022.  PWM_Config();
023. 
024.  while(1)
025.  {}
026.}
027. 
028. 
029./////////////////////////////////////////
030. 
031.#define ADC_CDR_ADDRESS    ((uint32_t)0x40012308)
032.__IO uint32_t ADCValue[9];
033. 
034.void ADC_Config(void)
035.{
036.      GPIO_InitTypeDef      GPIO_AdcInit;
037.      ADC_InitTypeDef       ADC_InitStructure;
038.      ADC_CommonInitTypeDef ADC_CommonInitStructure;
039. 
040.      /* Deinitializes the ADC peripheral registers */
041.      ADC_DeInit();
042. 
043.      /* Enable the GPIOC Clock & ADC1 Periph Clock */
044.      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
045.      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE);
046. 
047.      /* Configure the  PA0 pin (ADC123_IN0)
048.       *                PA1 pin (ADC123_IN1)
049.       *                PA2 pin (ADC123_IN2)
050.       *                PA3 pin (ADC123_IN3)
051.       *                PA4 pin (ADC12_IN4) */
052.      GPIO_AdcInit.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
053.      GPIO_AdcInit.GPIO_Mode = GPIO_Mode_AN;
054.      GPIO_AdcInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
055.      GPIO_Init(GPIOA, &GPIO_AdcInit);
056. 
057.      /* Configure the  PB0 pin (ADC12_IN8)
058.       *                PB1 pin (ADC12_IN9) */
059.      GPIO_AdcInit.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
060.      GPIO_AdcInit.GPIO_Mode = GPIO_Mode_AN;
061.      GPIO_AdcInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
062.      GPIO_Init(GPIOB, &GPIO_AdcInit);
063. 
064.      /* Configure the  PC0 pin (ADC123_IN10)
065.       *                PC2 pin (ADC123_IN12) */
066.      GPIO_AdcInit.GPIO_Pin = GPIO_Pin_0  |  GPIO_Pin_2;
067.      GPIO_AdcInit.GPIO_Mode = GPIO_Mode_AN;
068.      GPIO_AdcInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
069.      GPIO_Init(GPIOC, &GPIO_AdcInit);
070. 
071.      /* ADC Common configuration -- ADC_CCR Register */
072.      ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult ;
073.      ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;
074.      ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1  ;
075.      ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
076.      ADC_CommonInit(&ADC_CommonInitStructure);
077. 
078. 
079.      /* ADC1 regular channel 6 configuration -- ADC_CR1, ADC_CR2, ADC_SQR1 Register */
080.      ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
081.      ADC_InitStructure.ADC_ScanConvMode = ENABLE;
082.      ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
083.      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
084.      ADC_InitStructure.ADC_ExternalTrigConv = 0;
085.      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
086.      ADC_InitStructure.ADC_NbrOfConversion = 3;
087.      ADC_Init(ADC1, &ADC_InitStructure);
088.      ADC_Init(ADC2, &ADC_InitStructure);
089.      ADC_Init(ADC3, &ADC_InitStructure);
090. 
091.      /* ADC1 regular channel6 configuration -- ADCx->SMPR1,SMPR2 et ADCx->SQR1,SQR2,SQR3
092.       *              channel8 */
093.      ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_15Cycles );
094.      ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_15Cycles );
095.      ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 3, ADC_SampleTime_15Cycles );
096. 
097.      /* ADC2 regular channel12 configuration -- ADCx->SMPR1,SMPR2 et ADCx->SQR1,SQR2,SQR3  */
098.      ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 1, ADC_SampleTime_15Cycles );
099.      ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 2, ADC_SampleTime_15Cycles );
100.      ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 3, ADC_SampleTime_15Cycles );
101. 
102.      /* ADC3 regular channel12 configuration -- ADCx->SMPR1,SMPR2 et ADCx->SQR1,SQR2,SQR3  */
103.      ADC_RegularChannelConfig(ADC3, ADC_Channel_0, 1, ADC_SampleTime_15Cycles );
104.      ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 2, ADC_SampleTime_15Cycles );
105.      ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 3, ADC_SampleTime_15Cycles );
106. 
107.      /* DMA2 Stream0 channel0 configuration */
108.      DMA_ADC_Config();
109. 
110.      /* Enable DMA request after last transfer (Multi-ADC mode)  */
111.      ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
112. 
113.      /* Enable ADC1 -- ADC_CR2_ADON */
114.      ADC_Cmd(ADC1, ENABLE);
115. 
116.      /* Enable ADC2 */
117.      ADC_Cmd(ADC2, ENABLE);
118. 
119.      /* Enable ADC3 */
120.      ADC_Cmd(ADC3, ENABLE);
121. 
122.      /* Enable ADC1 DMA since ADC1 is the Master*/
123.      ADC_DMACmd(ADC1, ENABLE);
124.}
125. 
126. 
127./**
128.  * @brief  Configuration of the DMA for the ADC
129.  * @param  None
130.  * @retval None
131.  */
132.void DMA_ADC_Config(void)
133.{
134.  DMA_InitTypeDef DMA_InitStructure;
135. 
136.  DMA_InitStructure.DMA_Channel = DMA_Channel_0;                           
137.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCValue;             
138.  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS;    
139.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                  
140.  DMA_InitStructure.DMA_BufferSize = 9;                                 
141.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;      
142.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;               
143.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
144.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;       
145.  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                       
146.  DMA_InitStructure.DMA_Priority = DMA_Priority_High;                   
147.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;                 
148.  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; 
149.  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;           
150.  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;   
151.  DMA_Init(DMA2_Stream0, &DMA_InitStructure);                           
152. 
153.  /* DMA2_Stream0 enable */
154.  DMA_Cmd(DMA2_Stream0, ENABLE);
155.}
156. 
157. 
158. 
159./////////////////////////////////////////
160. 
161. 
162.TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
163.TIM_OCInitTypeDef  TIM_OCInitStructure;
164. 
165.uint16_t PWM_PrescalerValue = 0;
166.uint16_t PWM_Period = 4095;
167. 
168.uint16_t PWM_CCR1 = 0;
169.uint16_t PWM_CCR2 = 0;
170.uint16_t PWM_CCR3 = 0;
171.uint16_t PWM_CCR4 = 0;
172.uint16_t PWM_CCR5 = 0;
173.uint16_t PWM_CCR6 = 0;
174. 
175.void PWM_Config(void)
176.{
177.  /* TIM Configuration */
178.  TIM8_Config();
179. 
180.  /* Time base configuration */
181.  TIM_TimeBaseStructure.TIM_Period = PWM_Period;
182.  TIM_TimeBaseStructure.TIM_Prescaler = PWM_PrescalerValue;
183.  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
184.  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
185. 
186.  TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
187. 
188.  /* PWM1 Mode configuration: Channel1 */
189.  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
190.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
191.  TIM_OCInitStructure.TIM_Pulse = PWM_CCR1;
192.  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
193. 
194.  TIM_OC1Init(TIM8, &TIM_OCInitStructure);
195. 
196.  TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);
197. 
198.  /* PWM1 Mode configuration: Channel2 */
199.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
200.  TIM_OCInitStructure.TIM_Pulse = PWM_CCR2;
201. 
202.  TIM_OC2Init(TIM8, &TIM_OCInitStructure);
203.  TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);
204. 
205.  /* PWM1 Mode configuration: Channel3 */
206.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
207.  TIM_OCInitStructure.TIM_Pulse = PWM_CCR3;
208. 
209.  TIM_OC3Init(TIM8, &TIM_OCInitStructure);
210.  TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);
211. 
212.  /* PWM1 Mode configuration: Channel4 */
213.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
214.  TIM_OCInitStructure.TIM_Pulse = PWM_CCR4;
215. 
216.  TIM_OC4Init(TIM8, &TIM_OCInitStructure);
217.  TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Enable);
218. 
219.  /* Enable TIM8 Preload register on ARR */
220.  TIM_ARRPreloadConfig(TIM8, ENABLE);
221. 
222.  /* TIM8 enable counter */
223.  TIM_Cmd(TIM8, ENABLE);
224. 
225.  /* TIM8 Main Output Enable */
226.  TIM_CtrlPWMOutputs(TIM8, ENABLE);
227. 
228.  // TIM IT enable
229.  TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);
230. 
231.}
232. 
233./**
234.  * @brief  Configure the TIM8 Output Channels.
235.  * @param  None
236.  * @retval None
237.  */
238.void TIM8_Config(void)
239.{
240.  GPIO_InitTypeDef GPIO_InitStructure;
241. 
242.  /* TIM8 clock enable */
243.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
244. 
245.  /* GPIOC clocks enable */
246.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
247.   
248.  /* GPIOC Configuration: TIM8 CH1 (PC6), TIM8 CH2 (PC7), TIM8 CH3 (PC8) and TIM8 CH4 (PC9) */
249.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
250.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
251.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
252.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
253.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
254.  GPIO_Init(GPIOC, &GPIO_InitStructure);
255.   
256. 
257.  /* Connect TIM8 pins to AF2 */
258.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8);
259.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM8);
260.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM8);
261.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM8);
262.}
263.
264.void TIM8_IRQHandler(void)
265.{
266.  if (TIM_GetITStatus(TIM8, TIM_IT_Update) != RESET)
267.  {
268.    TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
269. 
270.    TIM8->CCR1 = ADCValue[0]; // PWM output 1
271.    TIM8->CCR2 = ADCValue[1]; // PWM output 2
272.    TIM8->CCR3 = ADCValue[2]; // PWM output 3
273.    TIM8->CCR4 = ADCValue[3]; // PWM output 4
274.  }
275.}

Outcomes