你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32 多路采样求助

[复制链接]
zzzzzzydb7b11 提问时间:2019-5-14 20:07 /
需要采集四个电压信号,参考了别人的程序,采用了ADC1+DMA的方式,但出来的数据都是0。  
贴一下我的程序。
1557835449.png
1557835477(1).png
1557835477(2).png
1557835477.png
收藏 评论15 发布时间:2019-5-14 20:07

举报

15个回答
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的。这是什么原因呢?
微信图片_20190514205013.jpg
a981223559 回答时间:2019-5-14 20:59:45
void  ADC1_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)
{
    /* ADC1  DMA1 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);
}

       

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

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采样转换。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

zzzzzzydb7b11 回答时间:2019-5-14 21:41:14
a981223559 发表于 2019-5-14 20:59
void  ADC1_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[0];
                        ad2+=adc_data[1];
                        ad3+=adc_data[2];
                  ad4+=adc_data[3];
                        }
     同时,在dma_init()加入了
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
        DMA_ClearFlag(DMA1_FLAG_TC1);

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

感谢您看我的程序。我有一个问题想问您,有的程序里写的是ad+=adc_data[0]或者ad+=ADC_ConvertedValue[0]。adc_data[0]和ADC_ConvertedValue[0] 代表的是通道0里的数据吗,为什么一个u16 adc_data[10]或者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四个采样口,显示依然波动。还在调试中。
wenyangzeng 回答时间:2019-5-15 09:52:19
本帖最后由 wenyangzeng 于 2019-5-15 10:34 编辑
zzzzzzydb7b11 发表于 2019-5-14 22:29
您好:1.主函数部分我已经把ADC转换标志位去除了。改成:
                     while(1)
        {

在楼主的ADC_DMA_Configuration()函数中:
DMA传送数据的基地址是ADC1->DR,目标地址是adc_data[],
按理一次转换4个通道,DMA传输:DMA_Instructure.DMA_BufferSize就应该是4,楼主设置为768,这样一次DMA传输就有192组×4通道的ADC转换数据了。楼主如果要一次转换这么多,adc_data[]数组就要设置足够的缓冲区,读取的通道数据也要认真区分了。
a981223559 回答时间:2019-5-15 09:59:04
zzzzzzydb7b11 发表于 2019-5-15 08:43
原来的程序中有一处错误:DMA_InitStructure.DMA_MemoryInc=DMA_PeripheralInc_Enable;将此语句应改为
        DMA ...

我的那个数值是3通道,采集256次,3*256=768。这个数值等于n*m,n为采样通道个数,m为采样次数
edmundlee 回答时间:2019-5-15 11:47:44
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&adc_data;
把这个&删掉

评分

参与人数 1蝴蝶豆 +1 收起 理由
STMCU + 1

查看全部评分

zzzzzzydb7b11 回答时间:2019-5-15 12:53:26
本帖最后由 zzzzzzydb7b11 于 2019-5-15 12:54 编辑

拜托大家帮帮忙,这是最新的程序和效果图,四个都有数据,而且一直在波动,但是数据都不对,为什么呢?

DMA1

DMA1

DMA2

DMA2

Main1

Main1

Main2

Main2

显示

显示
a981223559 回答时间:2019-5-16 09:57:00
本帖最后由 a981223559 于 2019-5-16 09:58 编辑
zzzzzzydb7b11 发表于 2019-5-15 12:53
拜托大家帮帮忙,这是最新的程序和效果图,四个都有数据,而且一直在波动,但是数据都不对,为什么呢?
...

你采10个数后没平均滤波,而且你计算电压的公式错了
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版