打印

ADC过采样 使用DMA 遇到数据不准的问题

[复制链接]
393|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
冰糖炖雪梨|  楼主 | 2018-8-4 07:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
不使用DMA及过采样 实际测得电压2.5V,使用万用表测量该值准确,ADC基准电压3.3V.贴上DMA及ADC采样的代码,只测量了一个通道。
uint16_t ADCxValues[1];

uint16_t get_adc(void)
{
    SCB_InvalidateDCache_by_Addr((uint32_t *)ADCxValues,  sizeof(ADCxValues));
    return ADCxValues[0];           //返回最近一次ADC1规则组的转换结果
}

int rt_hw_adc_init(void)
{
    DMA_Handle.Instance                     = DMA1_Stream5;                  //使用的DMA1 Stream5
    DMA_Handle.Init.Request                 = DMA_REQUEST_ADC1;              //请求类型采用DMA_REQUEST_ADC1
    DMA_Handle.Init.Direction               = DMA_PERIPH_TO_MEMORY;          //传输方向是从外设到存储器
    DMA_Handle.Init.PeriphInc               = DMA_PINC_DISABLE;              //外设地址自增禁止
    DMA_Handle.Init.MemInc                  = DMA_MINC_ENABLE;               //存储器地址自增使能
    DMA_Handle.Init.PeriphDataAlignment     = DMA_PDATAALIGN_HALFWORD;       //外设数据传输位宽选择半字,即16bit
    DMA_Handle.Init.MemDataAlignment        = DMA_MDATAALIGN_HALFWORD;       //存储器数据传输位宽选择半字,即16bit
    DMA_Handle.Init.Mode                    = DMA_CIRCULAR;                  //循环模式
    DMA_Handle.Init.Priority                = DMA_PRIORITY_LOW;              //优先级低
    DMA_Handle.Init.FIFOMode                = DMA_FIFOMODE_DISABLE;          //禁止FIFO
    DMA_Handle.Init.FIFOThreshold           = DMA_FIFO_THRESHOLD_FULL;       //禁止FIFO此位不起作用,用于设置阀值
    DMA_Handle.Init.MemBurst                = DMA_MBURST_SINGLE;             //禁止FIFO此位不起作用,用于存储器突发
    DMA_Handle.Init.PeriphBurst             = DMA_PBURST_SINGLE;             //禁止FIFO此位不起作用,用于外设突发

    HAL_DMA_Init(&DMA_Handle);
   
    __HAL_LINKDMA(&ADC1_Handler, DMA_Handle, DMA_Handle);
   
    ADC1_Handler.Instance                   =  ADC1;
    ADC1_Handler.Init.ClockPrescaler        =  ADC_CLOCK_ASYNC_DIV6;         //6分频
    ADC1_Handler.Init.Resolution            =  ADC_RESOLUTION_16B;           //16位模式
    ADC1_Handler.Init.ScanConvMode          =  ADC_SCAN_DISABLE;             //非扫描模式
    ADC1_Handler.Init.EOCSelection          =  ADC_EOC_SINGLE_CONV;          //关闭EOC中断
    ADC1_Handler.Init.LowPowerAutoWait      =  DISABLE;                      //自动低功耗关闭
    ADC1_Handler.Init.ContinuousConvMode    =  ENABLE;                       //连续转换
    ADC1_Handler.Init.NbrOfConversion       =  1;                            //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DiscontinuousConvMode =  DISABLE;                      //禁止不连续采样模式
    ADC1_Handler.Init.NbrOfDiscConversion   =  0;                            //不连续采样通道数为0
    ADC1_Handler.Init.ExternalTrigConv      =  ADC_SOFTWARE_START;           //软件触发
    ADC1_Handler.Init.ExternalTrigConvEdge  =  ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
    ADC1_Handler.Init.Overrun               =  ADC_OVR_DATA_OVERWRITTEN;     //有新的数据的死后直接覆盖掉旧数据
    ADC1_Handler.Init.OversamplingMode      =  ENABLE;                       //过采样
    ADC1_Handler.Init.Oversampling.Ratio    =  15;                           //15+1倍过采样
    ADC1_Handler.Init.Oversampling.RightBitShift         = ADC_RIGHTBITSHIFT_4; //数据右移4bit
    ADC1_Handler.Init.Oversampling.TriggeredMode         = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
    ADC1_Handler.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
    ADC1_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR;//DMA循环模式接收ADC转换的数据
    HAL_ADC_Init(&ADC1_Handler);                                             //初始化

    HAL_ADCEx_Calibration_Start(&ADC1_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); //ADC校准
   
    ADC1_ChanConf.Channel                   = ADC_CHANNEL_5;                      //通道
    ADC1_ChanConf.Rank                      = ADC_REGULAR_RANK_1;                 //1个序列
    ADC1_ChanConf.SamplingTime              = ADC_SAMPLETIME_810CYCLES_5;         //采样时间
    ADC1_ChanConf.SingleDiff                = ADC_SINGLE_ENDED;                   //单边采集
    ADC1_ChanConf.OffsetNumber              = ADC_OFFSET_NONE;            
    ADC1_ChanConf.Offset                    = 0;
    ADC1_ChanConf.OffsetRightShift          = DISABLE;
    ADC1_ChanConf.OffsetSignedSaturation    = DISABLE;
    HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);                          //通道配置
   
    HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)ADCxValues, 1);
   
    return RT_EOK;
}复制代码ad_vol = get_adc()/65536.0*3.3

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

430

主题

436

帖子

0

粉丝