OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7223|回复: 12

求助一个F4的用DMA搬运ADC数据,ADC用定时器触发的问题

[复制链接]

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
发表于 2016-1-11 21:36:04 | 显示全部楼层 |阅读模式
50金钱
目前的状态是:
1,已经实现了用定时器的PWM触发ADC转换,我用串口调试助手发送看了;
2,加上用DMA搬运时发送出来全是0.0000,硬件仿真后发现ADC1->DR是有数据,可以确定问题出在DMA上;
3,已经通篇看了手册关于DMA的描述,觉得配置没什么问题,为什么发出了的数据还是0.000000?下面附上代码:

最佳答案

查看完整内容[请看2#楼]

我找到问题了,自己解决了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2016-1-11 21:36:05 | 显示全部楼层
我找到问题了,自己解决了
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2016-1-11 21:38:03 | 显示全部楼层
[mw_shl_code=c,true]void ADC_DMA_init(u32 mar,u16 ndtr)
{
                RCC->AHB1ENR|=1<<22;        //DMA2ê±&#214;óê1&#196;ü
                delay_ms(5);
                DMA2_Stream4->PAR=(u32)&(ADC1->DR);         //DMAíaéèμ&#216;&#214;·
    DMA2_Stream4->M0AR=mar;       //DMA ′&#230;′¢&#198;÷0μ&#216;&#214;·
    DMA2_Stream4->NDTR=ndtr;      //DMA ′&#230;′¢&#198;÷0μ&#216;&#214;·
    DMA2_Stream4->CR=0;           //&#207;èè&#171;2&#191;&#184;′&#206;&#187;CR&#188;&#196;′&#230;&#198;÷&#214;μ

                DMA2_Stream4->CR&=0<<6;        //′&#230;′¢&#198;÷μ&#189;íaéè&#196;£ê&#189;
    DMA2_Stream4->CR|=1<<8;        //&#209;-&#187;·&#196;£ê&#189;
    DMA2_Stream4->CR&=0<<9;        //íaéè·&#199;&#212;&#246;á&#191;&#196;£ê&#189;
    DMA2_Stream4->CR|=1<<10;       //′&#230;′¢&#198;÷&#212;&#246;á&#191;&#196;£ê&#189;
    DMA2_Stream4->CR|=1<<11;       //íaéè′&#230;′¢&#198;÷3¤&#182;è£o16&#206;&#187;                /*2&#187;è·&#182;¨£&#172;μ÷ê&#212;ê±Dèòa×¢òa
    DMA2_Stream4->CR|=1<<13;       //′&#230;′¢&#198;÷êy&#190;Y3¤&#182;è£o16&#206;&#187;                /*2&#187;è·&#182;¨£&#172;μ÷ê&#212;ê±Dèòa×¢òa
    DMA2_Stream4->CR|=2<<16;       //&#184;&#223;ó&#197;&#207;è&#188;&#182;
    DMA2_Stream4->CR&=0<<21;       //íaéèí&#187;·¢μ¥′&#206;′&#171;ê&#228;
    DMA2_Stream4->CR&=0<<23;       //′&#230;′¢&#198;÷í&#187;·¢μ¥′&#206;′&#171;ê&#228;
    DMA2_Stream4->CR|= 0x0<<25;                 //í¨μà0&#209;&#161;&#212;&#241;
    DMA2_Stream4->CR|= 1<< 0;                         //′ò&#191;aDMA       
       
                Adc_Init();
                TIM3_PWM_Init(8-1,21);                                //PWMéè&#214;&#195;£&#172;4M&#188;&#198;êy&#198;μ&#194;ê£&#172;2M&#214;ü&#198;ú£&#172;°&#235;&#214;ü&#198;ú&#206;a1M
//                TIM3_Init_Init(2-1,42-1);                         //2M&#188;&#198;êy&#198;μ&#194;ê£&#172;1M&#214;ü&#198;ú
       
}

void  Adc_Init(void)
{   
        RCC->APB2ENR|=1<<8;            //ê1&#196;üADC1ê±&#214;ó
        RCC->AHB1ENR|=1<<0;            //ê1&#196;üPORTAê±&#214;ó          
        GPIO_Set(GPIOA,PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU);        //PA5,&#196;£&#196;aê&#228;è&#235;,&#207;&#194;à-   

        RCC->APB2RSTR|=1<<8;           //ADCs&#184;′&#206;&#187;
        RCC->APB2RSTR&=~(1<<8);        //&#184;′&#206;&#187;&#189;áê&#248;         
        ADC->CCR=1<<16;                        //ADCCLK=PCLK2/4=84/4=21Mhz,ADCê±&#214;ó×&#238;o&#195;2&#187;òa3&#172;1y36Mhz
       
        ADC1->CR1=0;                           //CR1éè&#214;&#195;&#199;&#229;á&#227;
        ADC1->CR2=0;                           //CR2éè&#214;&#195;&#199;&#229;á&#227;
        ADC1->CR1|=0<<24;              //12&#206;&#187;&#196;£ê&#189;
        ADC1->CR1|=1<<8;            //·&#199;é¨&#195;è&#196;£ê&#189;          http://www.openedv.com/forum.php ... 8%CA%B1%C6%F7%2BDMA
       
        ADC1->CR2&=~(1<<1);            //μ¥′&#206;×a&#187;&#187;&#196;£ê&#189;
        ADC1->CR2&=~(1<<11);           //óò&#182;&#212;&#198;&#235;       
        ADC1->CR2|=3<<28;                    //ó2&#188;t′¥·¢£&#172;é&#207;éyoí&#207;&#194;&#189;μ&#209;&#216;′¥·¢
//        ADC1->CR2|=7<<24;                    //TIM3_CH ′¥·¢
        ADC1->CR2|=8<<24;                    //TIM3_TRGO ′¥·¢
        ADC1->CR2|=1<<8;                    //&#191;aDMA
       
        ADC1->SQR1&=~(0XF<<20);        //í¨μà&#209;&#161;&#212;&#241;£&#172;éè&#214;&#195;×a&#187;&#187;×üêy
        ADC1->SQR1&=0<<20;             //1&#184;&#246;×a&#187;&#187;&#212;ú1&#230;&#212;òDòáD&#214;D ò2&#190;íê&#199;&#214;&#187;×a&#187;&#187;1&#230;&#212;òDòáD1                           
        //éè&#214;&#195;í¨μà5μ&#196;2é&#209;ùê±&#188;&#228;
        ADC1->SMPR2&=~(7<<(3*5));//í¨μà52é&#209;ùê±&#188;&#228;&#199;&#229;&#191;&#213;          
        ADC1->SMPR2|=0<<(3*5);         //í¨μà5  3&#184;&#246;&#214;ü&#198;ú,ìá&#184;&#223;2é&#209;ùê±&#188;&#228;&#191;éò&#212;ìá&#184;&#223;&#190;&#171;è·&#182;è         
       
        ADC1->SQR3|=0x05;                                //&#189;&#171;í¨μà5·&#197;è&#235;1&#230;&#212;òDòáD1&#214;D
       
        ADC1->CR2|=1<<0;                           //&#191;a&#198;&#244;AD×a&#187;&#187;&#198;÷          
        ADC1->CR2|=1<<30;                          //&#198;&#244;&#182;ˉ1&#230;&#212;ò×a&#187;&#187;í¨μà

}               
void TEST_ADC_DMA(void)
{
        u8 i;
        float temp;
        for(i=0;i<100;i++)
        {  
                temp=(float)AdcData*(3.3/4096);
                printf("%f",temp);
                printf("\r\n\r\n");//2&#229;è&#235;&#187;&#187;DD
        }       
}
在main里初始化为
        ADC_DMA_init((u32)AdcData,100);                        //êy&#190;Y′&#171;ê&#228;á&#191;&#206;a100&#184;&#246;
[/mw_shl_code]
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2016-1-11 21:42:50 | 显示全部楼层
为啥注释都是乱码?
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2016-1-11 21:46:19 | 显示全部楼层
[mw_shl_code=applescript,true]void  Adc_Init(void)
{   
        RCC->APB2ENR|=1<<8;            //使能ADC1时钟
        RCC->AHB1ENR|=1<<0;            //使能PORTA时钟          
        GPIO_Set(GPIOA,PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU);        //PA5,模拟输入,下拉   

        RCC->APB2RSTR|=1<<8;           //ADCs复位
        RCC->APB2RSTR&=~(1<<8);        //复位结束         
        ADC->CCR=1<<16;                        //ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
       
        ADC1->CR1=0;                           //CR1设置清零
        ADC1->CR2=0;                           //CR2设置清零
        ADC1->CR1|=0<<24;              //12位模式
        ADC1->CR1|=1<<8;            //非扫描模式       
        ADC1->CR2&=~(1<<1);            //单次转换模式
        ADC1->CR2&=~(1<<11);           //右对齐       
        ADC1->CR2|=3<<28;                    //硬件触发,上升和下降沿触发
//        ADC1->CR2|=7<<24;                    //TIM3_CH 触发
        ADC1->CR2|=8<<24;                    //TIM3_TRGO 触发
        ADC1->CR2|=1<<8;                    //开DMA
       
        ADC1->SQR1&=~(0XF<<20);        //通道选择,设置转换总数
        ADC1->SQR1&=0<<20;             //1个转换在规则序列中 也就是只转换规则序列1                           
        //设置通道5的采样时间
        ADC1->SMPR2&=~(7<<(3*5));//通道5采样时间清空          
        ADC1->SMPR2|=0<<(3*5);         //通道5  3个周期,提高采样时间可以提高精确度         
       
        ADC1->SQR3|=0x05;                                //将通道5放入规则序列1中
       
        ADC1->CR2|=1<<0;                           //开启AD转换器          
        ADC1->CR2|=1<<30;                          //启动规则转换通道

}
void ADC_DMA_init(u32 mar,u16 ndtr)
{
                RCC->AHB1ENR|=1<<22;        //DMA2时钟使能
                delay_ms(5);
                DMA2_Stream4->PAR=(u32)&(ADC1->DR);         //DMA外设地址
    DMA2_Stream4->M0AR=mar;       //DMA 存储器0地址
    DMA2_Stream4->NDTR=ndtr;      //DMA 存储器0地址
    DMA2_Stream4->CR=0;           //先全部复位CR寄存器值

                DMA2_Stream4->CR&=0<<6;        //存储器到外设模式
    DMA2_Stream4->CR|=1<<8;        //循环模式
    DMA2_Stream4->CR&=0<<9;        //外设非增量模式
    DMA2_Stream4->CR|=1<<10;       //存储器增量模式
    DMA2_Stream4->CR|=1<<11;       //外设存储器长度:16位                /*不确定,调试时需要注意
    DMA2_Stream4->CR|=1<<13;       //存储器数据长度:16位                /*不确定,调试时需要注意
    DMA2_Stream4->CR|=2<<16;       //高优先级
    DMA2_Stream4->CR&=0<<21;       //外设突发单次传输
    DMA2_Stream4->CR&=0<<23;       //存储器突发单次传输
    DMA2_Stream4->CR|= 0x0<<25;                 //通道0选择
    DMA2_Stream4->CR|= 1<< 0;                         //打开DMA       
       
                Adc_Init();
                TIM3_PWM_Init(8-1,21);                                //PWM设置,4M计数频率,2M周期,半周期为1M
//                TIM3_Init_Init(2-1,42-1);                         //2M计数频率,1M周期
       
}
void TEST_ADC_DMA(void)
{
        u8 i;
        float temp;
        for(i=0;i<100;i++)
        {  
                temp=(float)AdcData*(3.3/4096);
                printf("%f",temp);
                printf("\r\n\r\n");//插入换行
        }       
}[/mw_shl_code]
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-1-12 12:41:45 | 显示全部楼层
寄存器看不懂,我用库函数写的,下面是我在STM32F103上面用的,仅供参考
[mw_shl_code=applescript,true]void ADC_ChannelInit(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
       
#if ADC_DMA_ENABLE==1
        DMA_InitTypeDef DMA_InitStructure;
       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA时钟
#endif
       
        RCC_APB2PeriphClockCmd(ADCx_CHANNEL_GPIO_CLK, ENABLE);  //使能转换接口时钟
        RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);  //使能ADC时钟
       
        //初始化ADC采集通道PC.00
        GPIO_InitStructure.GPIO_Pin  = GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入
        GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
       
#if ADC_DMA_ENABLE==1
       
        //
        //配置DMA传输
        //
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADCx_DR_ADDRESS;  //目标源地址
        DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)&uhADCxConvertedValue;  //目的地
        DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;  //搬运到内存区域
        DMA_InitStructure.DMA_BufferSize         = 1;  //数据量
        DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;  //外设非增量模式
        DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Disable;  //存储器非增量模式
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //外设数据长度: 16位
        DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;  //存储器数据长度: 16位
        DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;  //循环模式
        DMA_InitStructure.DMA_Priority           = DMA_Priority_High;  //中等优先级
        DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
        DMA_Init(DMA_CHANNELx, &DMA_InitStructure);
        DMA_Cmd(DMA_CHANNELx, ENABLE);
       
#endif
       
        RCC_APB2PeriphResetCmd(ADCx_CLK, ENABLE);  //开始复位ADC
        RCC_APB2PeriphResetCmd(ADCx_CLK, DISABLE);  //复位ADC结束
       
        //ADC通道采样配置
        ADC_InitStructure.ADC_Mode                 = ADC_Mode_Independent;  //独立工作模式
        ADC_InitStructure.ADC_ScanConvMode         = ENABLE;  //非扫描模式
#if ADC_DMA_ENABLE==1
        ADC_InitStructure.ADC_ContinuousConvMode   = ENABLE;  //连续转换
        ADC_InitStructure.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;
#else
        ADC_InitStructure.ADC_ContinuousConvMode   = DISABLE;  //单次转换
        ADC_InitStructure.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;
#endif
        ADC_InitStructure.ADC_DataAlign            = ADC_DataAlign_Right;  //数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel         = 1;  //1个通道在规则中
        ADC_Init(ADCx, &ADC_InitStructure);
       
#if ADC_DMA_ENABLE==1
       
        /* ADC3 regular channel7 configuration **************************************/
        ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
       
        /* Enable ADC3 DMA */
        ADC_DMACmd(ADCx, ENABLE);
       
#endif
       
        ADC_Cmd(ADCx, ENABLE);  //开启ADC转换
       
        ADC_ResetCalibration(ADCx);  //使能复位校准
        while (ADC_GetResetCalibrationStatus(ADCx));  //等待复位校准完成
        ADC_StartCalibration(ADCx);  //开启AD校准
        while (ADC_GetCalibrationStatus(ADCx));  //等待校准完成
        ADC_SoftwareStartConvCmd(ADCx, ENABLE);  //使能软件启动AD
}[/mw_shl_code]
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2016-1-12 14:29:26 | 显示全部楼层
八度空间 发表于 2016-1-12 12:41
寄存器看不懂,我用库函数写的,下面是我在STM32F103上面用的,仅供参考
[mw_shl_code=applescript,true]v ...

你用的循环模式,是不是只需要开启一次启动,后续就不用再开启动了?
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11552
金钱
11552
注册时间
2014-4-1
在线时间
1317 小时
发表于 2016-1-12 16:23:42 | 显示全部楼层

DMA把ADC数据搬运到哪里,串口?


回复

使用道具 举报

17

主题

98

帖子

0

精华

高级会员

Rank: 4

积分
658
金钱
658
注册时间
2015-12-22
在线时间
128 小时
发表于 2016-1-12 17:48:24 | 显示全部楼层
xuande 发表于 2016-1-12 16:23
DMA把ADC数据搬运到哪里,串口?

搬运到内存
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-1-12 21:38:41 | 显示全部楼层
布沙尼神甫 发表于 2016-1-12 14:29
你用的循环模式,是不是只需要开启一次启动,后续就不用再开启动了?

嗯,连续采集,不停的
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

5

主题

19

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2016-1-12
在线时间
9 小时
发表于 2016-1-12 21:59:55 | 显示全部楼层
这边需要做一个adc双通道采集8000个数据并进行相关算法,我想问407内存192K够用么(定义a[8000]去存)?因为我需要8000个数,还是要用到外部SRAM存储或者DMA传输,不用DMA可不可以?
回复

使用道具 举报

37

主题

146

帖子

0

精华

高级会员

Rank: 4

积分
836
金钱
836
注册时间
2016-12-22
在线时间
165 小时
发表于 2017-6-20 16:19:56 | 显示全部楼层
大神,在吗?可不可以分享一下代码
回复

使用道具 举报

28

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
223
金钱
223
注册时间
2013-4-14
在线时间
24 小时
 楼主| 发表于 2017-6-23 16:45:20 | 显示全部楼层
Leeweiyi 发表于 2016-1-12 21:59
这边需要做一个adc双通道采集8000个数据并进行相关算法,我想问407内存192K够用么(定义a[8000]去存)?因 ...

192K的内存,一共是192*1024,存你8000,就算每个数据4个字节,也够了。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-17 15:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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