野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14686|回复: 11

单ADC多通道电压采集,dma溢出问题,帮忙看看谢谢

[复制链接]
发表于 2017-11-6 18:46:13 | 显示全部楼层 |阅读模式
没有采集到数据怎么溢出了?什么原因导致的,我是模仿着野火程序写的。 仿真结果如下图。
RPHJ_2O7FEHK){0`S4I}XGV.png
回复

使用道具 举报

发表于 2017-11-6 19:48:42 | 显示全部楼层
直接用我们的程序仿真试一试
回复 支持 反对

使用道具 举报

发表于 2017-11-7 14:19:41 | 显示全部楼层
那你倒把程序贴出来啊 光看图片怎么分析问题
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 17:47:59 | 显示全部楼层
fire 发表于 2017-11-6 19:48
直接用我们的程序仿真试一试

用源程序仿真没问题  没有溢出
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 17:48:43 | 显示全部楼层
Mascreda 发表于 2017-11-7 14:19
那你倒把程序贴出来啊 光看图片怎么分析问题

好的  马上发出来
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 17:49:10 | 显示全部楼层
Mascreda 发表于 2017-11-7 14:19
那你倒把程序贴出来啊 光看图片怎么分析问题

好的马上发出来
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 17:49:38 | 显示全部楼层
__IO uint16_t ADC_ConvertedValue[3]={0};

static void adc_init(void)
{
        ADC_InitTypeDef                                  ADC_InitTypeStructure;
        ADC_CommonInitTypeDef          ADC_CommonInitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);                //开打ADC1的时钟
        ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;     //单ADC使用独立模式
        ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;  //失能DMA访问(多ADC用)
        ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;  //84M / 4 =21M
        ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_20Cycles;  //两次转换之间的间隔

        ADC_CommonInit(&ADC_CommonInitStructure);   
       
        ADC_StructInit(&ADC_InitTypeStructure);
        ADC_InitTypeStructure.ADC_Resolution=ADC_Resolution_12b; //12位分辨率
        ADC_InitTypeStructure.ADC_ScanConvMode=ENABLE;  //扫描适用于多通道
        ADC_InitTypeStructure.ADC_ContinuousConvMode=ENABLE;   //打开连续转换模式
        ADC_InitTypeStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;  //

          //外部触发通道,本例子使用软件触发,此值随便赋值即可
  ADC_InitTypeStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
        ADC_InitTypeStructure.ADC_DataAlign=ADC_DataAlign_Right;
        ADC_InitTypeStructure.ADC_NbrOfConversion=3;    //转换通道的个数
        ADC_Init(ADC1,&ADC_InitTypeStructure);

        ADC_RegularChannelConfig(ADC1,ADC_Channel_5,3,ADC_SampleTime_3Cycles);  //ADC1 CH5
        ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_3Cycles);  //ADC1 CH2
        ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_3Cycles);  //ADC1 CH1

        ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE); //打开ADC_DMA请求
       
        ADC_DMACmd(ADC1,ENABLE);    //ADC_DAM使能

        ADC_Cmd(ADC1,ENABLE);           //使能ADC
        ADC_SoftwareStartConv(ADC1);   //软件触发方式

}

static void adc_gpio_init(void)  
{
        GPIO_InitTypeDef         GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);        //打开端口A的时钟
               
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN ;                    //模拟输入模式       
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;    //浮空       
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5 ;          //PA5  
        GPIO_Init(GPIOA,&GPIO_InitStructure) ;          

        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN ;                    //模拟输入模式       
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;    //浮空       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1 ;          //PA1  ADC_CH1
        GPIO_Init(GPIOA,&GPIO_InitStructure) ;          

        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN ;                    //模拟输入模式
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;    //浮空
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2 ;          //PA2  ADC_CH2
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
}

static void dma_adc_init(void)
{       
        DMA_InitTypeDef  DMA_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);  //DMA时钟使能
       
        DMA_InitStructure.DMA_PeripheralBaseAddr= RHEOSTAT_ADC_DR_ADDR;
        DMA_InitStructure.DMA_Memory0BaseAddr=(u32)ADC_ConvertedValue;
        DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;   //外设到MEMORY
        DMA_InitStructure.DMA_BufferSize=3;       
        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_FIFOMode=DMA_FIFOMode_Disable;
        DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;       
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;       
        DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;       
        DMA_InitStructure.DMA_Channel=DMA_Channel_0;
       
        DMA_Init(DMA1_Stream0,&DMA_InitStructure);       
        DMA_Cmd(DMA1_Stream0,ENABLE);    //打开DMA
       
}
void adc_config(void)
{
        adc_init();       
        adc_gpio_init();
        dma_adc_init();

}       
void adc_start(void )
{
        ADC_SoftwareStartConv(ADC1);   //软件触发方式
}

回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 17:50:51 | 显示全部楼层
main 函数
        while(1)
        {

                LED0=~LED0;
                ADC_ConvertedValueLocal[0]=(float)ADC_ConvertedValue[0]/4096*(float)3.3;       
                ADC_ConvertedValueLocal[1]=(float)ADC_ConvertedValue[1]/4096*(float)3.3;       
                ADC_ConvertedValueLocal[2]=(float)ADC_ConvertedValue[2]/4096*(float)3.3;       
               
                printf("采集到的电压为%f\r\n",ADC_ConvertedValueLocal[0]);
                printf("采集到的电压为%f\r\n",ADC_ConvertedValueLocal[1]);
                printf("采集到的电压为%f\r\n",ADC_ConvertedValueLocal[2]);
                delay_ms(1000);
        }
回复 支持 反对

使用道具 举报

发表于 2017-11-8 15:38:49 | 显示全部楼层
  1. /*****************************************************************
  2. 四路ADC采用连续转换 扫描模式,每路采集100个值后开启DMA中断,
  3. 在DMA中断中进行平均值滤波处理
  4. *****************************************************************/

  5. #include "ADC.h"
  6. #include "delay.h"

  7. uint16_t ADC_ConvertedValue[4]={0,0,0,0}; // ADC1转换的电压值通过 MDA 方式传到 SRAM
  8. float ADC_ConvertedValueLocal[4];        //转换后电压值

  9. uint16_t AD_Value[100][4];        //AD采样值
  10. uint16_t After_filter[4];        //AD滤波后

  11. uint16_t TEMP0,TEMP1;        //左侧,右侧设置温度值

  12. float Temp[4] ={0};//转换后温度值
  13. u8 TempValue_change = 0;//采集的值变化标志位

  14. /**
  15.   * @brief  ADC GPIO 初始化
  16.   * @param  无
  17.   * @retval 无
  18.   */
  19. static void ADC1_GPIO_Config(void)        //使用ADC1的channel 10,11,12,13,IO口为PC0~PC3
  20. {
  21.         GPIO_InitTypeDef GPIO_InitStructure;
  22.        
  23.         // 打开 ADC IO端口时钟
  24.         RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC, ENABLE);
  25.        
  26.         // 配置 ADC IO 引脚模式
  27.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;        //TC1
  28.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;        //TC2
  29.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //ADC1
  30.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;        //ADC2

  31.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  32.        
  33.         // 初始化 ADC IO
  34.         GPIO_Init(GPIOC, &GPIO_InitStructure);                               
  35. }


  36. /**
  37.   * @brief  配置DMA1工作模式
  38.   * @param  无
  39.   * @retval 无
  40.   */
  41. static void DMA1_Mode_Config(void)
  42. {
  43.         DMA_InitTypeDef DMA_InitStructure;
  44.        
  45.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 打开DMA时钟
  46.        

  47.         DMA_DeInit(DMA1_Channel1);        // 复位DMA控制器
  48.        
  49.         // 配置 DMA 初始化结构体
  50.         DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)0x40012400+0x4c);                // 外设基址为:ADC 数据寄存器地址       
  51.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value;                                                                // 存储器地址               
  52.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                                                                                // 数据源来自外设       
  53.         DMA_InitStructure.DMA_BufferSize = 400;                                                                                                                                                // 缓冲区大小,应该等于数据目的地的大小       
  54.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                        // 外设寄存器只有一个,地址不用递增
  55.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                                                         // 存储器地址递增       
  56.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;// 外设数据大小为半字,即两个字节       
  57.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                                // 内存数据大小也为半字,跟外设数据大小相同               
  58.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                                                                                // 循环传输模式       
  59.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;                // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
  60.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                                                                        // 禁止存储器到存储器模式,因为是从外设到存储器
  61.                
  62.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);                        // 初始化DMA
  63.         DMA_Cmd(DMA1_Channel1 , ENABLE);                                                                        // 使能 DMA 通道
  64.         DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);               
  65. }

  66. static void DMA1_NVIC_Config(void)
  67. {
  68.         NVIC_InitTypeDef NVIC_InitStructure;
  69.        
  70.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断组为1,2个抢占优先级,8个响应优先级
  71.        
  72.         NVIC_InitStructure.NVIC_IRQChannel =        DMA1_Channel1_IRQn;       
  73.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       
  74.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0; //抢占优先级       
  75.         NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //响应优先级

  76.         NVIC_Init(&NVIC_InitStructure);
  77. }

  78. /**
  79.   * @brief  配置ADC工作模式
  80.   * @param  无
  81.   * @retval 无
  82.   */
  83. static void ADC1_Mode_Config(void)
  84. {
  85.        
  86.         ADC_InitTypeDef ADC_InitStructure;
  87.        
  88.         RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1, ENABLE);        // 打开ADC时钟
  89.        
  90.         // ADC 模式配置
  91.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        // 只使用一个ADC,属于单模式
  92.         ADC_InitStructure.ADC_ScanConvMode = ENABLE ;                                // 扫描模式
  93.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;        // 连续转换模式,
  94.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        // 不用外部触发转换,软件开启即可
  95.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                                        // 转换结果右对齐
  96.         ADC_InitStructure.ADC_NbrOfChannel = 4;                                                                                                                        // 转换通道个数
  97.                
  98.        
  99.         ADC_Init(ADC1, &ADC_InitStructure);        // 初始化ADC
  100.        
  101.         RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 配置ADC时钟为CLK2的8分频,即9MHz 确保ADC时钟不超过14M
  102.        
  103.         // 配置ADC 通道的转换顺序和采样时间
  104.         ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);  //PC0 ->TC1
  105.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);        //PC1 ->TC2
  106.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_239Cycles5);        //PC2        ->ADC1
  107.         ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_239Cycles5);        //PC3 ->ADC2
  108.                
  109.         ADC_DMACmd(ADC1, ENABLE);                                // 使能ADC DMA 请求
  110.         ADC_Cmd(ADC1, ENABLE);                                        // 开启ADC ,并开始转换
  111.        
  112.         /* 必须执行复位校准和AD校准,不准将导致结果不准确*/
  113.        
  114.         ADC_ResetCalibration(ADC1);                        // 初始化ADC 复位校准寄存器  
  115.         while(ADC_GetResetCalibrationStatus(ADC1));// 等待校准寄存器初始化完成
  116.         ADC_StartCalibration(ADC1);                                                                        // ADC开始校准
  117.         while(ADC_GetCalibrationStatus(ADC1));                  // 等待校准完成
  118.                
  119.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);        // 由于没有采用外部触发,所以使用软件触发ADC转换
  120. }

  121. /**
  122.   * @brief  ADC初始化
  123.   * @param  无
  124.   * @retval 无
  125.   */
  126. void ADC1_Init(void)
  127. {
  128.   DMA1_Mode_Config();
  129.   DMA1_NVIC_Config();
  130.         ADC1_GPIO_Config();
  131.         ADC1_Mode_Config();
  132. }

  133. void filter(void)                //在中断中滤波
  134. {
  135.         int sum = 0;
  136.         u8 count,i;
  137.         for(i=0;i<4;i++)
  138.         {
  139.                 for(count=0;count<100;count++)
  140.                 {
  141.                         sum += AD_Value[count][i];
  142.                 }
  143.                 After_filter[i] = sum/100;
  144.                 sum = 0;
  145.         }
  146.         TEMP0 =         After_filter[0]*70/4096;        //左侧设置温度值
  147.         TEMP1 =         After_filter[1]*70/4096;        //右侧设置温度值
  148.         TempValue_change =1;
  149. }


  150. void DMA1_Channel1_IRQHandler(void)
  151. {
  152.         if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
  153.         {
  154.                 filter();
  155.                 DMA_ClearITPendingBit(DMA1_IT_TC1);
  156.         }
  157. }


  158. void Get_ADC()        //换算电压值(调试用)
  159. {
  160.         int i = 0;
  161. //        for(i = 0;i<2;i++)
  162. //        {
  163. //                ADC_ConvertedValueLocal[i] =(float) ADC_ConvertedValue[i]/4096*3.22;                //设置电压值
  164. //        }
  165.         for(i=2;i<4;i++)
  166.         {
  167.                 ADC_ConvertedValueLocal[i] =(float) After_filter[i]/4096*3.20;        //实际电压值
  168.         }
  169. }
  170. /*********************************************END OF FILE**********************/













复制代码
回复 支持 反对

使用道具 举报

发表于 2017-11-8 15:40:24 | 显示全部楼层
这是我写的一个采集4路ADC值得程序 ,用了DMA中断 ,你可以参考一下,每一路ADC采100个电压值(为了平均滤波处理)。
回复 支持 反对

使用道具 举报

发表于 2018-11-20 11:06:57 来自手机 | 显示全部楼层
你这个CLK的配置有问题吧 ADC的工作频率最高位12MHz
回复 支持 反对

使用道具 举报

发表于 2021-9-27 11:39:18 | 显示全部楼层

这个你主函数怎么写的呢,头文件ADC.h也分享下吧。谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-4-19 20:17 , Processed in 0.048872 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表