OpenEdv-开源电子网

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

想做一个用STM32的双ADC模式,然后用DMA把32位的数据从ADC1->DR中传送到数组的程序,但是传送后的结果有问题

[复制链接]

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
发表于 2011-8-4 19:49:39 | 显示全部楼层 |阅读模式
以下为MAIN程序
#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h" 
#include "key.h"
#include "exti.h"
#include "wdg.h"
#include "timer.h"
#include "lcd.h"
#include "ADC.h"
#include "DMA.h"
//#include "PIC.h"

#include<math.h>

  
u16 ADCmax;
vu16 ADC2_Buf[2000];


int main(void) 
{     
u16 times=0,t;
float V;
static u16 Vx1=0,Vx2,Vy1=120,Vy2; 
Stm32_Clock_Init(9);//72M 
delay_init(72);     //延时初始化 
uart_init(72,9600); //设置波特率 
LCD_Init();   
//Timerx_Init(10000,7200);  
adc_init();
ADC2_Init(); 

  
  while (1) 
    {    
if(DMA1->ISR&(1<<1)) //传输完成了 
times++;   

for(t=0;t<1000;t++)
{
ADC2_Buf[t*2]=ADC_Buf[t]&0xffff;
ADC2_Buf[t*2+1]=ADC_Buf[t]>>16;
if(ADCmax<ADC_Buf[t])
ADCmax=ADC_Buf[t]; 
}
V=(float)ADCmax/4096*3.3*100;
ADCmax=0;
LCD_ShowNum(10,0,V,5,16);
DMA1->IFCR|=1<<1;
MYDMA_GOnes(DMA1_Channel1);
if(times>300)
{
   LCD_Clear(BLUE);
                LCD_DrawRectangle(20,20,300,220);
LCD_DrawGrid();
LCD_ShowNum(10,223,V,5,12);
for(t=20;t<300;t++)
{
V=(float)ADC2_Buf[t]/4096*3.3*50;
LCD_DrawPoint(t,V+30);
// Get_ADC2();
times=0;
}
             }
               
    }  
}



ADC中的程序
#include "adc.h" 
#include "dma.h" 

//V1.0 
//针对PC0口(ADC_IN10)的转换,采用单次软触发    
u32 ADC_Buf[1000];



//初始化ADC
//ADC采样频率为:Fadc/Tcovn 
//Fadc=11Mhz 
//Tcovn=252 
//所以采样频率为:43.65Khz 
//做512点的FFT,得到每点对应频率为:43.65/512=85.255Hz     
void  adc_init(void) 
{     
RCC->APB2ENR|=1<<2;    //使能PORTA口时钟  
GPIOA->CRL&=0XFFFFFFF0;//PA.0 anolog输入         //IO设置 
//RCC->APB2ENR|=1<<2;    //使能PORTA口时钟  
//GPIOA->CRL&=0XFFFFFF0f;//PA.0 anolog输入         //IO设置 
//通道10/11设置   
RCC->APB2ENR|=1<<9;    //ADC1时钟使能    
RCC->APB2RSTR|=1<<9;   //ADC1复位 
RCC->APB2RSTR&=~(1<<9);//复位结束


RCC->CFGR|=3<<14;      //SYSCLK/DIV2=88M/8=11Mhz 得到ADC采样率位43.65Khz   
  

ADC1->CR1|=1<<8;       //扫描模式 

ADC1->CR1&=0XF0FFFF;   //独立工作模式 
ADC1->CR1|=0x07<<16;   //

ADC1->CR2|=1<<1;       //连续转换模式  
ADC1->CR2|=0x000E0000; //软件控制转换 由bit21控制 
ADC1->CR2|=1<<20;      //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发 
ADC1->CR2&=~(1<<11);   //右对齐 

ADC1->SQR1&=0xFFF0FFFF;//1个转换在规则序列中  
ADC1->SQR3&=0XFFFFFFE0;//规则序列1=通道0 
ADC1->SQR3|=0;     
ADC1->SMPR2|=0X00;     //通道0的转换时间为:1.5+12.5个ADC时钟周期    
ADC1->CR2|=1<<0;       //开启AD转换器,第一次唤醒AD转换器  
ADC1->CR2|=1<<3;       //使能复位校准   
while(ADC1->CR2&1<<3); //等待校准结束   
    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。     
ADC1->CR2|=1<<2;       //开启AD校准    
while(ADC1->CR2&1<<2); //等待校准结束 
//该位由软件设置以开始校准,并在校准结束时由硬件清除    
ADC1->CR2|=1<<8;   //开启ADC DMA转换

MYDMA_Config(DMA1_Channel1);//配置DMA通道1 
MYDMA_Enable(DMA1_Channel1);//开启DMA通道1  
ADC1->CR2|=1<<0;   //开启AD转换   
}




void ADC2_Init(void)
 {
  RCC->APB2ENR|=1<<10;
  RCC->APB2ENR|=1<<2;
  GPIOA->CRL&=0xffffff0f;
  GPIOA->CRL|=0x00000000;

//  ADC2->CR1|=1<<11; //ADC2->CR1 11位不能开不然就会不转换
  ADC2->CR1|=0x0<<16;
  ADC2->CR1|=0<<13;

  ADC2->CR2|=1<<22;
  ADC2->CR2|=1<<20;
  ADC2->CR2|=0x07<<16;
  ADC2->CR2|=1<<0;

  ADC2->SMPR2|=0x07<<3;
  ADC2->SQR1|=0x00<<20;
  ADC2->SQR3|=0x01;
 
ADC2->CR2|=1<<20;      //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发 


ADC2->CR2|=1<<1;       //连续转换模式  

while(ADC2->CR2&1<<3); //等待校准结束   
    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。     
ADC2->CR2|=1<<2;       //开启AD校准    
while(ADC2->CR2&1<<2); //等待校准结束 
//该位由软件设置以开始校准,并在校准结束时由硬件清除    
 
ADC2->CR2|=1<<0;   //开启AD转换
 }

u16 Get_ADC2(void)
 {
  ADC2->CR2|=1<<22;
  while(!(ADC2->SR&1<<1));
  return ADC2->DR;
 }


DMA中的程序
#include "dma.h"  
//DMA1的各通道配置 
//DMA_CHxMA1的通道 参考手册 

void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx) 
{
 
RCC->AHBENR|=1<<0;//开启DMA1时钟 
DMA_CHx->CPAR=DMA1_DEVICE_ADD;//DMA1 外设地址 ADC1_DR_Address 
DMA_CHx->CMAR=DMA1_MEM_ADD;   //DMA1,ADC 存储器地址 
DMA_CHx->CNDTR=DMA1_MEM_LEN;  //DMA1,传输数据量 
DMA_CHx->CCR=0X00000000;//复位 
DMA_CHx->CCR|=0<<4;  //从外设器件读数据 
DMA_CHx->CCR|=0<<5;  //非循环模式 
DMA_CHx->CCR|=0<<6;  //外设地址非增量模式 
DMA_CHx->CCR|=1<<7;  //存储器增量模式 
DMA_CHx->CCR|=2<<8;  //外设数据宽度为32位 
DMA_CHx->CCR|=2<<10; //存储器数据宽度32位 
DMA_CHx->CCR|=1<<13; //高优先级 
DMA_CHx->CCR|=0<<14; //非存储器到存储器模式  
//开启 DMA传输 
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx) 
DMA_CHx->CCR|=1<<0;  //开启DMA传输 
}   
//开启一次DMA传输 
//单次DMA转换之后,必须把DMA关闭,再次启动,才能实现第二次DMA传输!!! 
void MYDMA_GOnes(DMA_Channel_TypeDef*DMA_CHx) 
{    
DMA_CHx->CCR&=~(1<<0);  //关闭DMA传输 
DMA_CHx->CNDTR=DMA1_MEM_LEN;  //DMA1,传输数据量 
DMA_CHx->CCR|=1<<0;  //开启DMA传输 


程序基本就是采集ADC1 与ADC2 的值然后通过DMA传送支ADC_BUF【1000】这一个数组中,程序基本功能都能实现,但是出现一个好奇怪的问题就是就是DMA传送完成后,我查看数组u32 ADC_Buf[1000]数时,高16位(就是ADC2的转换结果)总是连继性地出现18个相同的高16位,但是我是测交流电。附件里有ADC_Buf[1000]的值。
请论坛里面的高手帮一下忙。





QQ截图20110804194202.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2011-7-13
在线时间
0 小时
发表于 2011-8-4 21:59:48 | 显示全部楼层
我想对多个通道的交流信号进行连续转换,每秒钟交流采样n次如何设置
还有资料上说转换结果存在ADC-DR寄存器中,多个通道同时转换、连续转换,会不会出现转换结果覆盖的情况
楼主能不能给点意见,谢谢
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-5 00:14:09 | 显示全部楼层
     我还没用过ADC2呢.如果单独用adc2+dma,数据是否正确?单独adc2呢?
转换结果是会被覆盖的,所以需要及时取走数据.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-5 08:37:13 | 显示全部楼层
回复【2楼】ty19224:
---------------------------------
多个通道同时转换、连续转换,是会覆盖结果。如果你一定要这样做,你可以用ADC开一个中断,一转换完就去读里面的数据。单通道我试过,应该是可以,多个通道同时转换我就还没试过!
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-5 08:49:35 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
我用的STM32型号的芯片  DMA通道只支持ADC1的不支持ADC2 ,所以单独用adc2+dma我没没有试过。还有没有用DMA单独adc2转换、单独ADC1转换又是正确的。而且我双ADC模式下,用仿真时查看ADC1—>DR中的高16时又是正确的,不会出现多个相同的植,但是通过DMA转换后就出现这种情况,不知道是不是DMA设置有问题。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-5 09:13:47 | 显示全部楼层
adc2没有DMA通道,能传输么?
不能的话,你如何把adc2的结果放到buf里面去的?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

6

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2011-7-13
在线时间
0 小时
发表于 2011-8-5 10:17:23 | 显示全部楼层
资料上说STM32有1-3个ADC,有18个通道,却没有介绍对应关系,比如说我想用通道10,应该使能哪个ADC
谢谢
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-5 10:46:07 | 显示全部楼层
3个ADC的型号,应该是大容量才有吧?
如果要用通道10,比如STM32的原理图上,会有ADC123_10的标志,说明这个IO脚,对应了ADC1,ADC2,ADC3的通道10,但是你同一时刻只能是属于一个ADC的,要嘛是ADC1的通道10,要嘛是其他两个中的一个的通道10.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-5 11:38:41 | 显示全部楼层
现在问题解决了,谢谢各位,原因是ADC2与ADC1的转换时间分别设置为1.5与239.5所以才出现这样的的情况。我现在想问一个问题,我现在要外加一个超高速AD,如果用GPIO读感觉会好慢,有没有什么提高速度的方法。DMA通道的能不能做GPIO的传输。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-5 12:44:53 | 显示全部楼层
你搞这么高速,做示波器?
GPIO可以DMA传输的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-5 15:25:56 | 显示全部楼层

这一个是DMA的请求映射表,没有通道是支持GPIO的。是的,我打算自己DIY一个数字示波器,打算用60M的AD做。这一个表在附件的105页

STM32中文参考手册.pdf

3.69 MB, 下载次数: 2718

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-5 18:29:41 | 显示全部楼层
60M!!
STM32只怕是应付不过来的.
60M采用 AD->fpga+FIFO->STM32比较好实现.
STM32的DMA GPIO我用过了,速度不快的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-5 20:06:22 | 显示全部楼层
回复【12楼】正点原子:
---------------------------------
DMA1->CPAR 1=&GPIOA->IDR原来这样设置就行。。。书上又不写,搞到我还以为GPIO不能用DMA模式。现在还有一点不解,就是ADC+DMA就是每当ADC转换完一次DMA才传送一次,然而GPIO+DMA好像没有这样的标志位,DMA是根据什么样的规则去提取GPIOA->IDR里面的值??原子哥请问你有没有GPIO+DMA的程序,可不可以给我参考一下??
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-6 09:20:44 | 显示全部楼层
程序是有,不过目前还没公开.
GPIO+DMA+定时器TRG触发.就可以了.不过需要你的adc能提供一个trg信号.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2011-8-3
在线时间
0 小时
 楼主| 发表于 2011-8-6 14:46:31 | 显示全部楼层
谢谢了,现在总算明白了。等器件买回来,我再继续做
回复 支持 反对

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-3-13 12:51:11 | 显示全部楼层
回复【12楼】正点原子:

---------------------------------
STM32的DMA GPIO我用过了,速度不快的.

那速度能达到多少呢?我现在想用DMA GPIO的方式去取AD9235的12位并行数据,时钟是10M。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-3-13 14:01:24 | 显示全部楼层
具体的值,我也没测试过。
给你个数据吧,IO口抓8位数据,内部转换为16位,再送LCD。320*240点,速度在10帧。
算下来才1.5M。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-3-14 14:08:26 | 显示全部楼层
回复【17楼】正点原子:

---------------------------------
对这个速度,我不会算。请教
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-3-14 14:47:36 | 显示全部楼层
回复【18楼】lkl10800139:
---------------------------------
320*240*2*10
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-3-14 22:22:40 | 显示全部楼层
回复【14楼】正点原子:
程序是有,不过目前还没公开. 
GPIO+DMA+定时器TRG触发.就可以了.不过需要你的adc能提供一个trg信号.
---------------------------------
现在在做这个试验,无法取到GPIO IDR的值?能交流一下么,原子哥
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-3-14 23:06:40 | 显示全部楼层
回复【20楼】lkl10800139:
---------------------------------
这个简单吧?你自己写代码测试一下就知道了.另外看看寄存器设置是否都对了
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-3-15 00:08:33 | 显示全部楼层
回复【21楼】正点原子:

---------------------------------
我先是测试读IDR,读出来的值不对,然后试着往ODR里面写数据,数据写不进去。很奇怪,所以到论坛里面来问你。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-3-15 00:43:34 | 显示全部楼层
那是你代码有问题了吧?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-3-15 00:50:06 | 显示全部楼层
首先,我先不怀疑官方的例程。现在结果不对。自己写吧。原子哥赐教
回复 支持 反对

使用道具 举报

0

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2013-10-22
在线时间
15 小时
发表于 2014-1-23 00:51:45 | 显示全部楼层
程序是有,不过目前还没公开. 
GPIO+DMA+定时器TRG触发.就可以了.不过需要你的adc能提供一个trg信号.
--------------------------------------------------------------------------------
能不能把例子发给我呀/,学习了,,,,
回复 支持 反对

使用道具 举报

0

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2013-5-30
在线时间
3 小时
发表于 2016-5-19 21:18:49 | 显示全部楼层
学习下!
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-9 02:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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