zzzzzzydb7b11 发表于 2019-5-14 20:07:00

stm32 多路采样求助

需要采集四个电压信号,参考了别人的程序,采用了ADC1+DMA的方式,但出来的数据都是0。
贴一下我的程序。

zzzzzzydb7b11 发表于 2019-5-14 20:17:21

采样口是PA0,PA1,PA2,PA3。

a981223559 发表于 2019-5-14 20:42:42

本帖最后由 a981223559 于 2019-5-14 20:45 编辑

ADC_SoftwareStartConvCmd(ADC1, ENABLE)这个函数写在初始化最后,DMA初始化在校准前

zzzzzzydb7b11 发表于 2019-5-14 20:52:54

a981223559 发表于 2019-5-14 20:42
ADC_SoftwareStartConvCmd(ADC1, ENABLE)这个函数写在初始化最后,DMA初始化在校准前

您好。目前只有PA0口有数据显示(我还没有把AD值转换为电压值,所以数据有点大)。目前这四个AD口都是悬空的,应该有1V左右电压,所以不可能都是0的。这是什么原因呢?

a981223559 发表于 2019-5-14 20:59:45

voidADC1_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );          //使能ADC1通道时钟

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                               //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M                     
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                                                                  //模拟输入引脚
        GPIO_Init(GPIOA, &GPIO_InitStructure);       
        ADC_DMA_Configuration();
        ADC_DeInit(ADC1);                                                                                                                                //复位ADC1
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                                        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                                                        //扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                                                //连续转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;                                //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                                        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 3;                                                                        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);       
        // 设置指定的规则组通道和转换顺序
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_239Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_239Cycles5);
        // 开启ADC的DMA
        ADC_DMACmd(ADC1, ENABLE);
        ADC_Cmd(ADC1, ENABLE);                                                                        //使能指定的ADC1
        ADC_ResetCalibration(ADC1);                                                          //使能复位校准
        while(ADC_GetResetCalibrationStatus(ADC1));                                //等待复位校准结束
        ADC_StartCalibration(ADC1);                                                               //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));                                        //等待校准结束
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
        /* Clear Channel 1 DMA1_FLAG_TC flag */
        DMA_ClearFlag(DMA1_FLAG_TC1);       
}       

void ADC_DMA_Configuration(void)
{
    /* ADC1DMA1 Channel Config */
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                                         //使能DMA时钟

    DMA_DeInit(DMA1_Channel1);                                                                                   //将DMA的通道1寄存器重设为缺省值:ADC1连接DMA通道1
    DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR;                                //DMA外设ADC基地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;                      //DMA内存基地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                                //内存作为数据传输的目的地
    DMA_InitStructure.DMA_BufferSize = 768;                                                                //此值为完整一轮DMA传输的次数,3通道每通道采集50次
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                        //外设地址不变
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                //内存地址递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;         //外设数据位宽度16位,即DMA传输尺寸
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                 //数据宽度16位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                //工作在循环缓存模式,一轮结束后自动开始下轮传输
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                 //DMA通道 x拥有高优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                //DMA通道x禁止内存到内存
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);                                                        //根据DMA_InitStruct中参数DMA通道
        DMA_Cmd(DMA1_Channel1, ENABLE);
}

       

a981223559 发表于 2019-5-14 21:00:21

zzzzzzydb7b11 发表于 2019-5-14 20:52
您好。目前只有PA0口有数据显示(我还没有把AD值转换为电压值,所以数据有点大)。目前这四个AD口都是悬 ...

直接参考我的程序吧,已经测试过没问题的

wenyangzeng 发表于 2019-5-14 21:35:19

本帖最后由 wenyangzeng 于 2019-5-14 21:39 编辑

1、楼主既然配置了DMA,就应该等待DMA传输结束标志位,才去读取数据而非等待ADC转换结束。
2、既然ADC配置了连续采样模式,启动一次就够了,不应该一直启动ADC采样转换。

zzzzzzydb7b11 发表于 2019-5-14 21:41:14

a981223559 发表于 2019-5-14 20:59
voidADC1_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;


DMA_InitStructure.DMA_BufferSize = 768;
这个数据是怎么计算出来的呢?如果是4个通道,计算式子是什么呢?


按照您给的程序试了一次,四路都有示数,但我把每个引脚下拉后,示数并未回到0,应该还有一些问题。

十分感谢您的帮助!

zzzzzzydb7b11 发表于 2019-5-14 22:29:45

wenyangzeng 发表于 2019-5-14 21:35
1、楼主既然配置了DMA,就应该等待DMA传输结束标志位,才去读取数据而非等待ADC转换结束。
2、既然ADC配置 ...

您好:1.主函数部分我已经把ADC转换标志位去除了。改成:
                     while(1)
        {
                                while(1)
        {
                ad1=0;ad2=0;ad3=0;ad4=0;
                for(i=0;i<10;i++)
                {
                  ad1+=adc_data;
                        ad2+=adc_data;
                        ad3+=adc_data;
                  ad4+=adc_data;
                        }
   同时,在dma_init()加入了
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
        DMA_ClearFlag(DMA1_FLAG_TC1);

2.那个不知道怎么写重复了,已经删除了。

感谢您看我的程序。我有一个问题想问您,有的程序里写的是ad+=adc_data或者ad+=ADC_ConvertedValue。adc_data和ADC_ConvertedValue 代表的是通道0里的数据吗,为什么一个u16 adc_data或者u16 ADC_ConvertedValue就可以把DMA的数值存在这个数组里了呢,是在哪个函数里定义了么?

zzzzzzydb7b11 发表于 2019-5-15 08:43:33

原来的程序中有一处错误:DMA_InitStructure.DMA_MemoryInc=DMA_PeripheralInc_Enable;将此语句应改为
        DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
此时都能读到数据,但不正确,情况和5楼的程序效果一样。显示的都为波动数字(1-900多变化),四个都是。即使下拉PA0,PA1,PA2,PA3四个采样口,显示依然波动。还在调试中。
页: [1] 2
查看完整版本: stm32 多路采样求助