使用 STM32F303VCT6 的 ADC

2019-12-27 18:43发布

本帖最后由 jonyzhu 于 2014-8-5 13:29 编辑

这篇帖子将介绍如何使用 STM32F303VCT6 的 ADC 功能,属于[记录我的 STM32 示波器的研发经历]的副产品。STM32F3 系列的模拟电路部分功能比较强(相对于ST其它的MCU),其中STM32F303VCT6 最高主频 72MHz,256K Flash,48K RAM;最牛的,是它的72MHz的ADC时钟,以及6bit分辨率下8个时钟周期的采样+转换时间,这相当于9M/s的采样率了 。
屏幕快照 2014-08-05 上午10.30.19.png (55.07 KB, 下载次数: 0) 下载附件 2014-8-5 13:14 上传

双ADC的交替采样模式下,有几个参数是需要精心设计的:
  • 采样周期。共分8挡,最短1.5个ADC时钟周期,最长601个时钟周期。采样周期加上前面讲的PLL时钟分频系数,可以搭配出多种不同的采样率,在捕获低频信号时会非常有用。
  • 转换周期。这个参数和分辨率有关。采样周期+转换周期=总周期,采样频率/总周期=采样率。就这么简单。
  • 通道间采样间隔。别忘了我们可是双ADC采样,ADC1和ADC2在对同一个通道进行交替采样,在ADC1完成采样(注意,是采样,不是转换)后,要等几个(最少1个)ADC时钟周期才让开始ADC2的采样。

仍然以6bit分辨率为例:采样周期=1.5,转换周期=6.5,总周期=1.5+6.5=8,通道间采样间隔=3 时,ADC1在 t0 时刻采样,然后ADC2就会在 t0+1.5+3=t0+4.5 的时刻采样,然后如此继续下去。
这样,相当于8个ADC时钟周期里面,采样了2次(虽然2次并不是严格对齐的),72MHz/(8/2)=72MHz/4 = 18M/s采样率。

我为什么老抓住6bit分辨率不放?因为我的显示屏只有320X240啊,垂直不能同时显示2个8bit分辨率的波形啊!!!而且我SPI的显示屏啊,刷新率是硬伤啊,6bit分辨率意味着我能少刷几个像素啊!!!哎。。。(我后来都想整单 {MOD}LCD了,那刷新率杠杠的,不过没关系,我还有STM32F429i Discovery,哈哈哈!)
Common 设置:
  1. cs.ADC_Mode  = ADC_Mode_Interleave;
  2. cs.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  3. cs.ADC_DMAMode = ADC_DMAMode_OneShot;
  4. cs.ADC_TwoSamplingDelay = 2;  //2就是3个周期的通道间间隔
  5. ADC_CommonInit(ADC1, &cs);   //双通道模式下,只需配置Master ADC
复制代码
每个 ADC 的设置:
  1.         ADC_StructInit(&adcs);
  2.         ADC_VoltageRegulatorCmd(ADC1, ENABLE);
  3.         ADC_VoltageRegulatorCmd(ADC2, ENABLE);
  4.         osDelay(1); //延迟 1ms,需要用你自己的延时函数替换。其实2us就足够了,CMSIS_RTOS 没有那么精细,1ms算了。
  5.         ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC1);
  6.         ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC2);
  7.         while(ADC_GetCalibrationStatus(ADC1) != RESET );
  8.         while(ADC_GetCalibrationStatus(ADC2) != RESET );
  9.         adcs.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
  10.         adcs.ADC_Resolution = ADC_Resolution_6b;
  11.         adcs.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_7;         
  12.         adcs.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
  13.         adcs.ADC_DataAlign = ADC_DataAlign_Right;
  14.         adcs.ADC_OverrunMode = ADC_OverrunMode_Enable;
  15.         adcs.ADC_AutoInjMode = ADC_AutoInjec_Disable;  
  16.         adcs.ADC_NbrOfRegChannel = 1;
  17.         ADC_Init(ADC1, &adcs);
  18.         ADC_Init(ADC2, &adcs);
  19.         ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5);
  20.         ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5);
  21.         ADC_Cmd(ADC1, ENABLE);
  22.         ADC_Cmd(ADC2, ENABLE);
复制代码

DMA的设置
ADC转换那么快,用CPU等中断再往数组里面存那是不现实的哇!(我用注入交替触发模式试过,用中断存数组大约只有200K/s的速率)
ADC1、2做双交替采样的DMA设置,有2个选择:
  • 只用1个DMA通道,一次在ADC2的EOC事件后一次读取2个采样结果到一个数组中
  • 用2个DMA通道,分别读取2个ADC的采样结果到2个数组中

我选了第二个,原因么:
  • 我不缺DMA
  • 以后从双采样切换到独立采样(也就是双通道示波器变身四通道示波器)时,比较自然
DMA里面需要确定你的采样存储深度,让DMA在读取完这么多组数据后自动停止,发送给LCD去显示。当然,你也可以让DMA继续采样来提高捕获率或者实现余辉效果,不过那需要内存支持,算法就复杂了,我还没有搞到那么深。等以后用到那个地步了,可能我也不会选择 soc 的 ADC 了。
  1.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1|RCC_AHBPeriph_DMA2, ENABLE);
  2.         ds.DMA_PeripheralBaseAddr         = (uint32_t)&ADC1->DR;
  3.         ds.DMA_MemoryBaseAddr                 = (uint32_t)&appADCValue1[0];
  4.         ds.DMA_BufferSize                         = ADCDeepth;
  5.         ds.DMA_DIR                                         = DMA_DIR_PeripheralSRC;
  6.         ds.DMA_PeripheralDataSize         = DMA_PeripheralDataSize_Byte;
  7.         ds.DMA_MemoryDataSize                 = DMA_MemoryDataSize_Byte;
  8.         ds.DMA_PeripheralInc                 = DMA_PeripheralInc_Disable;
  9.         ds.DMA_MemoryInc                         = DMA_MemoryInc_Enable;
  10.         ds.DMA_Mode                                 = DMA_Mode_Circular;
  11.         ds.DMA_Priority                         = DMA_Priority_VeryHigh;
  12.         ds.DMA_M2M                                         = DMA_M2M_Disable;
  13.         DMA_Init(DMA1_Channel1, &ds);
  14.         ds.DMA_PeripheralBaseAddr         = (uint32_t)&ADC2->DR;
  15.         ds.DMA_MemoryBaseAddr                 = (uint32_t)&appADCValue2[0];
  16.         DMA_Init(DMA2_Channel1, &ds);
  17.         DMA_Cmd(DMA1_Channel1, ENABLE);
  18.         DMA_Cmd(DMA2_Channel1, ENABLE);
  19.         DMA_ITConfig(DMA2_Channel1, DMA_IT_TC, ENABLE);
  20.         ns.NVIC_IRQChannel = DMA2_Channel1_IRQn;
  21.         ns.NVIC_IRQChannelPreemptionPriority = 4;
  22.         ns.NVIC_IRQChannelSubPriority = 8;
  23.         ns.NVIC_IRQChannelCmd = ENABLE;
  24.         NVIC_Init(&ns);
复制代码

好了,最后启动 Master ADC的转换就开始了 ADC_StartConversion(ADC1);

最后,把上面的代码整合一下,看个全貌(不是全部工程,但应该更容易应用到你自己到项目中去,因为少了很多乱七八糟的和我个人环境设置有关的东西):
  1. #define ADCDeepth 300
  2. uint8_t appADCValue1[ADCDeepth];
  3. uint8_t appADCValue2[ADCDeepth];

  4. void ADCInit(void){
  5.         GPIO_InitTypeDef         gs;
  6.         ADC_CommonInitTypeDef cs;
  7.         ADC_InitTypeDef         adcs;
  8.         DMA_InitTypeDef         ds;
  9.         NVIC_InitTypeDef         ns;

  10.         RCC_AHB1PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  11.         gs.GPIO_Mode = GPIO_Mode_AN;
  12.         gs.GPIO_OType = GPIO_OType_PP;
  13.         gs.GPIO_PuPd = GPIO_PuPd_NOPULL;
  14.         gs.GPIO_Speed = GPIO_Speed_50MHz;
  15.         gs.GPIO_Pin = GPIO_Pin_3;
  16.         GPIO_Init(GPIOA, &gs);
  17.         gs.GPIO_Pin = GPIO_Pin_7;
  18.         GPIO_Init(GPIOA, &gs);

  19.         RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1);
  20.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
  21.         cs.ADC_Clock = ADC_Clock_AsynClkMode;
  22.         cs.ADC_Mode  = ADC_Mode_Interleave;
  23.         cs.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  24.         cs.ADC_DMAMode = ADC_DMAMode_OneShot;
  25.         cs.ADC_TwoSamplingDelay = 2;  //2就是3个周期的通道间间隔
  26.         ADC_CommonInit(ADC1, &cs);    //双通道模式下,只需配置Master ADC

  27.         ADC_StructInit(&adcs);
  28.         ADC_VoltageRegulatorCmd(ADC1, ENABLE);
  29.         ADC_VoltageRegulatorCmd(ADC2, ENABLE);
  30.         osDelay(1); //延迟 1ms,需要用你自己的延时函数替换。其实2us就足够了,CMSIS_RTOS 没有那么精细,1ms算了。
  31.         ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC1);
  32.         ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC2);
  33.         while(ADC_GetCalibrationStatus(ADC1) != RESET );
  34.         while(ADC_GetCalibrationStatus(ADC2) != RESET );
  35.         adcs.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
  36.         adcs.ADC_Resolution = ADC_Resolution_6b;
  37.         adcs.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_7;         
  38.         adcs.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
  39.         adcs.ADC_DataAlign = ADC_DataAlign_Right;
  40.         adcs.ADC_OverrunMode = ADC_OverrunMode_Enable;
  41.         adcs.ADC_AutoInjMode = ADC_AutoInjec_Disable;  
  42.         adcs.ADC_NbrOfRegChannel = 1;
  43.         ADC_Init(ADC1, &adcs);
  44.         ADC_Init(ADC2, &adcs);
  45.         ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5);
  46.         ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_1Cycles5);
  47.         ADC_Cmd(ADC1, ENABLE);
  48.         ADC_Cmd(ADC2, ENABLE);

  49.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1|RCC_AHBPeriph_DMA2, ENABLE);
  50.         ds.DMA_PeripheralBaseAddr         = (uint32_t)&ADC1->DR;
  51.         ds.DMA_MemoryBaseAddr                 = (uint32_t)&appADCValue1[0];
  52.         ds.DMA_BufferSize                         = ADCDeepth;
  53.         ds.DMA_DIR                                         = DMA_DIR_PeripheralSRC;
  54.         ds.DMA_PeripheralDataSize         = DMA_PeripheralDataSize_Byte;
  55.         ds.DMA_MemoryDataSize                 = DMA_MemoryDataSize_Byte;
  56.         ds.DMA_PeripheralInc                 = DMA_PeripheralInc_Disable;
  57.         ds.DMA_MemoryInc                         = DMA_MemoryInc_Enable;
  58.         ds.DMA_Mode                                 = DMA_Mode_Circular;
  59.         ds.DMA_Priority                         = DMA_Priority_VeryHigh;
  60.         ds.DMA_M2M                                         = DMA_M2M_Disable;
  61.         DMA_Init(DMA1_Channel1, &ds);
  62.         ds.DMA_PeripheralBaseAddr         = (uint32_t)&ADC2->DR;
  63.         ds.DMA_MemoryBaseAddr                 = (uint32_t)&appADCValue2[0];
  64.         DMA_Init(DMA2_Channel1, &ds);
  65.         DMA_Cmd(DMA1_Channel1, ENABLE);
  66.         DMA_Cmd(DMA2_Channel1, ENABLE);
  67.         DMA_ITConfig(DMA2_Channel1, DMA_IT_TC, ENABLE);
  68.         ns.NVIC_IRQChannel = DMA2_Channel1_IRQn;
  69.         ns.NVIC_IRQChannelPreemptionPriority = 4;
  70.         ns.NVIC_IRQChannelSubPriority = 8;
  71.         ns.NVIC_IRQChannelCmd = ENABLE;
  72.         NVIC_Init(&ns);
  73. }
  74. void DMA2_Channel1_IRQHandler(void){
  75.         if(DMA_GetITStatus(DMA2_IT_TC1)!=RESET){
  76.                 DMA_ClearITPendingBit(DMA2_IT_TC1);
  77.                 //数据拿到了,接下来看你的了!
  78.         }
  79. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
30条回答
30zero
1楼-- · 2019-12-28 20:17
jonyzhu 发表于 2014-8-11 14:13
上面就是程序,我特地从项目里面摘出来的;否则全是自定义的配置,直接给出来你们是根本编译不了的。 ...

楼主,我想请教一下,最近在学校搞个检测项目,也是用到 STM32F303VCT6。需要多路ADC检测,问题是ADC12_IN6,ADC34_IN1,这些通道怎么开启呢?
jonyzhu
2楼-- · 2019-12-28 21:49
 精彩回答 2  元偷偷看……
30zero
3楼-- · 2019-12-29 02:00
jonyzhu 发表于 2014-9-15 16:47
  • IO 配置为 GPIO_Mode_AN
  • ADC_RegularChannelConfig(ADC1, %你的采样通道%, 1, ADC_SampleTime_1 ...

  • 请问STM32F303VCT6的ADC连续采样多路该怎么配置了?我搞了一天都搞不懂。希望你们帮助我。配置为:
    void ADC_Config(void)
    {
            ADC_InitTypeDef ADC_InitStructure;
            ADC_CommonInitTypeDef ADC_CommonInitStructure;
           
            RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1|RCC_ADC34PLLCLK_Div1);  
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12|RCC_AHBPeriph_ADC34, ENABLE);
           
            ADC_GPIO_Config();
            ADC_DMA_Config();
           
            ADC_StructInit(&ADC_InitStructure);
           
            ADC_VoltageRegulatorCmd(ADC1, ENABLE);
            ADC_VoltageRegulatorCmd(ADC2, ENABLE);
            ADC_VoltageRegulatorCmd(ADC3, ENABLE);
            ADC_VoltageRegulatorCmd(ADC4, ENABLE);
           
            Delay(10);
           
            ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
            ADC_StartCalibration(ADC1);

            ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single);
            ADC_StartCalibration(ADC2);
           
            ADC_SelectCalibrationMode(ADC3, ADC_CalibrationMode_Single);
            ADC_StartCalibration(ADC3);
           
            ADC_SelectCalibrationMode(ADC4, ADC_CalibrationMode_Single);
            ADC_StartCalibration(ADC4);

            while(ADC_GetCalibrationStatus(ADC1) != RESET );
            calibration_value_1 = ADC_GetCalibrationValue(ADC1);

            while(ADC_GetCalibrationStatus(ADC2) != RESET );
            calibration_value_2 = ADC_GetCalibrationValue(ADC2);

            while(ADC_GetCalibrationStatus(ADC3) != RESET ){}
            calibration_value_3 = ADC_GetCalibrationValue(ADC3);

            while(ADC_GetCalibrationStatus(ADC4) != RESET ){}
            calibration_value_4 = ADC_GetCalibrationValue(ADC4);
           
            /* ADC Dual mode configuration */  
            ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Interleave;                                                                    
            ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;                     
            ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;            
            ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;                 
            ADC_CommonInitStructure.ADC_TwoSamplingDelay = 2;         
            ADC_CommonInit(ADC1, &ADC_CommonInitStructure);

            /* 配置ADC1在连续模式下分辨率为12bits*/
            ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//配置ADC的转化分辨率
            ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;//配置选择连续采样或单次采样
            ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;//ADC内部边沿触发               
            ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
            ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//设置ADC是左对齐还是右对齐
            ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;   
            ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;  
            ADC_InitStructure.ADC_NbrOfRegChannel = 1;
                   
            ADC_Init(ADC1, &ADC_InitStructure);
            ADC_Init(ADC2, &ADC_InitStructure);
            ADC_Init(ADC3, &ADC_InitStructure);
            ADC_Init(ADC4, &ADC_InitStructure);
           
      ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_19Cycles5);
      
            ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 6, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 7, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 8, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 9, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 10, ADC_SampleTime_19Cycles5);
              
      ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 11, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 12, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 13, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 14, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 15, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 16, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 17, ADC_SampleTime_19Cycles5);
      
      ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 18, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 19, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 20, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 21, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 22, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 23, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 24, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 25, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC3, ADC_Channel_16, 26, ADC_SampleTime_19Cycles5);
      
      ADC_RegularChannelConfig(ADC4, ADC_Channel_1, 27, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_2, 28, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_3, 29, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_4, 30, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_5, 31, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_12, 32, ADC_SampleTime_19Cycles5);
      ADC_RegularChannelConfig(ADC4, ADC_Channel_13, 33, ADC_SampleTime_19Cycles5);
      
            ADC_RegularChannelConfig(ADC4, ADC_Channel_6, 34, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC4, ADC_Channel_7, 35, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC4, ADC_Channel_8, 36, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC4, ADC_Channel_9, 37, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC4, ADC_Channel_10, 38, ADC_SampleTime_19Cycles5);
            ADC_RegularChannelConfig(ADC4, ADC_Channel_11, 39, ADC_SampleTime_19Cycles5);
      
            ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);//配置DMA循环模式
            ADC_DMAConfig(ADC2, ADC_DMAMode_Circular);//配置DMA循环模式
            ADC_DMAConfig(ADC3, ADC_DMAMode_Circular);//配置DMA循环模式
            ADC_DMAConfig(ADC4, ADC_DMAMode_Circular);//配置DMA循环模式
           
            ADC_DMACmd(ADC1, ENABLE);        /* Enable ADC_DMA */
            ADC_DMACmd(ADC2, ENABLE);        /* Enable ADC_DMA */
            ADC_DMACmd(ADC3, ENABLE);        /* Enable ADC_DMA */
            ADC_DMACmd(ADC4, ENABLE);        /* Enable ADC_DMA */
           
            ADC_Cmd(ADC1, ENABLE);
            ADC_Cmd(ADC2, ENABLE);
            ADC_Cmd(ADC3, ENABLE);
            ADC_Cmd(ADC4, ENABLE);
           
            while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
            while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY));
            while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_RDY));
            while(!ADC_GetFlagStatus(ADC4, ADC_FLAG_RDY));
      
    //  DMA_Cmd(DMA1_Channel1, ENABLE);//DMA频道使能
    //  DMA_Cmd(DMA1_Channel1, ENABLE);//DMA频道使能
    //  DMA_Cmd(DMA1_Channel1, ENABLE);//DMA频道使能
            ADC_StartConversion(ADC1);
            ADC_StartConversion(ADC2);
            ADC_StartConversion(ADC3);
            ADC_StartConversion(ADC4);
    }

    void ADC_DMA_Config(void)
    {
            DMA_InitTypeDef DMA_InitStruct;
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
           
            /* DMA1 Channel1 Config */
            DMA_DeInit(DMA1_Channel1);//选择通道
            DMA_InitStruct.DMA_PeripheralBaseAddr = ADC_CDR_ADDRESS;//设置外设地址
            DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;//设置内存映射地址
            DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//外设作为数据传输的来源
            DMA_InitStruct.DMA_BufferSize = 39;//缓冲为39
            DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//关外设地址映射
            DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//关内存地址计数
            DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//字节 外设数据宽度为32位
            DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
            DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;//循环模式
            DMA_InitStruct.DMA_Priority = DMA_Priority_High;//高优先级
            DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;//关内存到内存
            DMA_Init(DMA1_Channel1, &DMA_InitStruct);
    }
    jonyzhu
    4楼-- · 2019-12-29 06:39
    30zero 发表于 2014-9-17 21:17
    请问STM32F303VCT6的ADC连续采样多路该怎么配置了?我搞了一天都搞不懂。希望你们帮助我。配置为:
    void  ...
    1. ADC_InitStructure.ADC_NbrOfRegChannel = 1;
    复制代码
    这里的数字不能瞎写,你需要采样几个通道就是几。例如,你 ADC1 采样 10 个通道,你就要写 10。“1” 是你从别人代码里面拷贝过来的,看过手册,搞明白每行代码的用途才行。
    hyghyg1234
    5楼-- · 2019-12-29 10:31
    写的很好,谢谢。
    30zero
    6楼-- · 2019-12-29 11:45
    楼主,我的多路采样ADC还是不行我ADC1、ADC2、ADC3、ADC4都要用起来,楼主能教导一下吗?下午是我配置的ADC1和ADC12通道采样都正常的程序:
    void ADC_Configuration(void)
    {
            ADC_InitTypeDef ADC_InitStructure;
            ADC_CommonInitTypeDef ADC_CommonInitStructure;
            /* Configure the ADC clock */
            RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2|RCC_ADC34PLLCLK_Div2);

            /* Enable ADC1 clock */
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12|RCC_AHBPeriph_ADC34, ENABLE);
           
            ADC_CommonInitStructure.ADC_Clock             = ADC_Clock_AsynClkMode;
            ADC_CommonInitStructure.ADC_DMAAccessMode     = ADC_DMAAccessMode_Disabled;
            ADC_CommonInitStructure.ADC_DMAMode           = ADC_DMAMode_OneShot;
            ADC_CommonInitStructure.ADC_Mode              =  ADC_Mode_Independent;
            ADC_CommonInitStructure.ADC_TwoSamplingDelay  = 2;
            ADC_CommonInit(ADC1,&ADC_CommonInitStructure);
           
            ADC_StructInit(&ADC_InitStructure);
            /* Calibration procedure */  
            ADC_VoltageRegulatorCmd(ADC1, ENABLE);

            /* Insert delay equal to 10 */
            Delay(10);

            ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);ADC_StartCalibration(ADC1);

            while(ADC_GetCalibrationStatus(ADC1) != RESET );

            ADC_InitStructure.ADC_ContinuousConvMode      = ADC_ContinuousConvMode_Enable;
            ADC_InitStructure.ADC_DataAlign               = ADC_DataAlign_Right;
            ADC_InitStructure.ADC_ExternalTrigConvEvent   = ADC_ExternalTrigConvEvent_1;
            ADC_InitStructure.ADC_ExternalTrigEventEdge   = ADC_ExternalTrigEventEdge_None;
            ADC_InitStructure.ADC_NbrOfRegChannel         = 10;
            ADC_InitStructure.ADC_OverrunMode             =   ADC_OverrunMode_Disable;
            ADC_InitStructure.ADC_AutoInjMode             = ADC_AutoInjec_Disable;
            ADC_InitStructure.ADC_Resolution              = ADC_Resolution_12b;
            ADC_Init(ADC1, &ADC_InitStructure);

            /* ADC1 Regular Channel1 Configuration */
            ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_1Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_1Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_1Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_1Cycles5);
            ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 6, ADC_SampleTime_1Cycles5);//PC0
            ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 7, ADC_SampleTime_1Cycles5);//PC1
            ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 8, ADC_SampleTime_1Cycles5);//PC2
            ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 9, ADC_SampleTime_1Cycles5);//PC3
            ADC_RegularChannelConfig(ADC1, ADC_Channel_10,10, ADC_SampleTime_1Cycles5);//PF2
           
            ADC_Cmd(ADC1, ENABLE);             /* Enable ADC1                        */

            DMA1_Configuration();
            ADC_DMAConfig(ADC1,ADC_DMAMode_Circular);
            ADC_DMACmd(ADC1, ENABLE);             /* Enable ADC1's DMA interface        */

            /* Start ADC1 calibaration */
            ADC_StartCalibration(ADC1);
           
            while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
            ADC_StartConversion(ADC1);/* Start ADC1 Software Conversion*/
    }

    void DMA1_Configuration(void)
    {
            DMA_InitTypeDef DMA_InitStruct;
            /* ADC Channel configuration */
           
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
           
            DMA_DeInit(DMA1_Channel1);
            DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR); //外设首地址
            DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue0;  //自己定义的存储区
            DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;    //数据传输外设到内存
            DMA_InitStruct.DMA_BufferSize = 10;//数据大小10
            DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器地址自动增加地址禁止
            DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;    //内存地址自动增加

            DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据大小

            DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //内存数据大小,同上
            DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;       //DMA循环传输
            DMA_InitStruct.DMA_Priority = DMA_Priority_High; //高优先级

            DMA_Init(DMA1_Channel1, &DMA_InitStruct);
            DMA_Cmd(DMA1_Channel1, ENABLE);      //使能DMA1_Stream        
    }
    但就不知道怎么添加其他通道进行采样,ADC2、ADC3、ADC4的一些通道进行采样,希望你能帮我这个小菜鸟

    一周热门 更多>